R制图:按频率变化线条粗细

4
更新:找到了一个粗略的解决方案,该解决方案仅适用于R中的plot()函数,但是它会受益于更好的图形。有什么想法吗?这是另一种绘图水平,但潜在地,向增加厚度的过渡可能是逐渐的。

我在R中有一个简单的数据框。

dft <- data.frame(line=c(rep("X1",4),rep("X2",4),rep("X3",4)),+ 
       time=rep(c("t1","t2","t3","t4"),3), value=c(0,1,1,1,0,0.5,1,1,0,0,1,1))

> dft
   line time value
1    X1   t1   0.0
2    X1   t2   1.0
3    X1   t3   1.0
4    X1   t4   1.0
5    X2   t1   0.0
6    X2   t2   0.5
7    X2   t3   1.0
8    X2   t4   1.0
9    X3   t1   0.0
10   X3   t2   0.0
11   X3   t3   1.0
12   X3   t4   1.0

我希望能够绘制这样的图表,每当线条重叠时,它们相对于线条数量会更加粗细。因此,当值从1开始到1结束时,如果有更多的线在同一时间点具有相同的转换,则该线将更加粗细。
相同的数据也可以表示为转换频率。
transitions <- data.frame(line=character(), generation=character(), t0=numeric(),t1=numeric())
for (line in unique(dft$line)){
  for (number in 1:3)  {
    generation= c("t1","t2","t3","t4")[number]
    generation2= c("t1","t2","t3","t4")[number+1]
    transitions <- rbind(transitions, data.frame(line=line, generation=generation, t0=dft[dft$line == line & dft$time == generation ,]$value, t1=dft[dft$line == line & dft$time == generation2 ,]$value))

  }
}

> transitions
  line generation  t0  t1
1   X1         t1 0.0 1.0
2   X1         t2 1.0 1.0
3   X1         t3 1.0 1.0
4   X2         t1 0.0 0.5
5   X2         t2 0.5 1.0
6   X2         t3 1.0 1.0
7   X3         t1 0.0 0.0
8   X3         t2 0.0 1.0
9   X3         t3 1.0 1.0

这听起来像是一个常见的问题。我找到了一些关于如何改变厚度的答案,但并没有真正涉及到频率的基础。有人能指点我正确的方向吗?谢谢!
更新:最终每条线(X1、X2、X3)应该在时间t1:t4中被跟踪,时间在x轴上,值在y轴上。就像下面的图片(使用下面的初步解决方案生成)。也许R中有更好的图形工具。

Example result


你能展示一下图表应该长什么样吗?就像这个代码一样:plot(as.numeric(dft$time), dft$value, type="l") - Roman
谢谢,差不多了!我的意思是X1、X2和X3应该是线条,生成应该是x轴,值应该被绘制在这些线条上,收敛转换应该更加明显(更新Q)。我刚刚想出了一个简单的解决方案并在下面发布了它。但如果您知道如何改进输出,我会非常感激。 - puslet88
3个回答

2
这是一个通过改变线条透明度来快速绘制的图表。 enter image description here
dft$x <- dft$time
levels(dft$x) <- 0:3
dft$x <- as.numeric(dft$x)
ggplot(dft, aes(x, value, group=line)) + geom_line(size=1, alpha=0.15)

谢谢!有没有可能将线条粗细和透明度结合起来呢?真实数据的问题在于频率在1到20之间变化,线条粗细可能是展示这一点的有用方式。不过这个解决方案非常有帮助! - puslet88
也许可以通过某种方式使行抖动,以便它们不完全重叠,从而允许在行之间产生更明显的差异? - puslet88

2
我也遇到了这个问题。我用ggplot将频率作为线段的宽度来解决它。
dft <- data.frame(
  line = c(rep("X1", 4), rep("X2", 4), rep("X3", 4)), 
  time = rep(c("t1","t2","t3","t4"), 3), 
  value = c(0,1,1,1,0,0.5,1,1,0,0,1,1))

# you need a data frame with each transition and the frequency for it
dft_wide <- dft %>% pivot_wider( names_from = "time", values_from = "value")
# which columns are the different time transitions
t <- 2:5
t_seq <- paste(t, t+1, sep = ":")[-length(t)]
timeseq <- 1:4

# add the frequency for each transition
freqtable <- data.frame()
for (i in 1:length(t_seq)){
  temp <- eval(parse(text = paste0("dft_wide[", t_seq[[i]],"]"))) %>% group_by_all %>% count()
  names(temp) <- c("from", "to", "n")
  freqtable <- rbind.data.frame(freqtable, 
                                cbind.data.frame(temp, 
                                                 trans = t_seq[[i]],
                                                 tstart = timeseq[[i]], 
                                                 tend = timeseq[[i+1]]))
}

#draw the transition as separate segments and use the frequency as line width 
freqtable %>%
  ggplot(aes ( x = tstart, xend = tend, y = from, yend = to ))+
  geom_segment(aes(lwd = n))

输出 1 如果你只有两个时间点,那就更容易了:

dft_2 <- data.frame(t1 = c(0,1,0,0,2, 1, 1), t2 = c(1,1,1,2,1,1,1))

data.frame(table(dft_2$t1, dft_2$t2)) %>%
  mutate(transition = paste(Var1, Var2))%>%
  pivot_longer(cols = c(Var1, Var2), names_to = "x", values_to = "y")%>%
  filter(Freq != 0 & !grepl("NA", transition )) %>%
  ggplot(aes ( x = x, y = y, group = transition ))+
    geom_point()+
    geom_line(aes(lwd = Freq, ))

output 2

这是否被认为是“一个更好的情节”,这是一个个人的判断。

1

我想出了一个使用常规图表的简单解决方案。如果有人有更好的解决方案,比如使用ggplot制作更漂亮的图表,我会非常乐意学习。也许在ggplot中使用不同程度的透明度可以解决问题。

df<-ddply(transitions,.(generation,t0,t1),nrow)
levels(df$generation) <- c(0,1,2,3)
df$generationnr <- as.numeric(as.character(df$generation))

plot(1:1, 1:1, lwd = 1, type = 'l', xlim = c(0,3), ylim = c(0,1))
for (item in 1:nrow(df))
  lines(c(df$generationnr[item],(df$generationnr[item]+1)),+
              c(df$t0[item],df$t1[item]),lwd=df$V1[item] )

Crude solution with plot

使用更真实的数据后,这种简单的解决方案变得有些粗糙,线条粗细难以感知。带真实数据的粗略解决方案

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接