使用ggplot2覆盖列表中具有不同点数的行

时间:2017-06-03 16:38:18

标签: r ggplot2

我想绘制多行,每行使用不同数量的点,使用ggplot2使用不同的颜色。我的MWE由

给出
test <- list()
length(test) <- 10
for(i in 1:10){
  test[[i]] <- rnorm(100 - i) # Note - different number of points per line!!!!
}

请注意列表中每个向量的长度不同。然后,无法在data.frame中进行转换。

3 个答案:

答案 0 :(得分:4)

所以这让你想要你想要我想。请注意,它适用于您的列表,每个向量具有不同的点数 - 这当然是列表而不是数据帧的一个主要原因。

此方案的SO上的大多数(如果不是全部)示例都使用数据框而不是列表中的数据。由于向量具有不同的长度,因此通过将数据帧熔化为长形式来解决此问题的链接不适用。

但是,如果您确实碰巧有一个数据帧,这意味着一组长度相同的向量,那么您可以使用melt。但是,使用gather中的tidyr可能比melt reshape2更为现代。请注意,melt也可用于列表,但我必须研究它如何处理id。

我也选择不使用lapply类中的函数,因为我想强调&#34;宽数据&#34;到#34;长数据&#34;方面 - 我认为for循环的东西比lapply好得多,开始用户可以发现神秘的东西。

无论如何,我们现在应该使用来自purrr的东西,因为这是一个现代类型稳定的功能库。

以下是一些代码 - 使用for循环,因此不是最紧凑的,而是展开以使其易于理解和快速理解:

library(ggplot2)
test <- list()
length(test) <- 10
for(i in 1:10){
  test[[i]] <- rnorm(100 - i) 
}

# Convert data to long form
df <- NULL
for(i in 1:10){
  ydat <- test[[i]]
  ndf <- data.frame(key=paste0("id",i),x=1:length(ydat),y=ydat)
  df <- rbind(df,ndf)
}

# plot it
ggplot(df) + geom_line(aes(x=x,y=y,color=key))

产量:

enter image description here

答案 1 :(得分:2)

正如Mike Wiseaccepted answer已经指出,gplot2需要data.frame作为输入,最好是长格式

然而,问题和接受的答案都使用for循环,尽管R具有简洁的功能。要创建test数据集,可以使用以下“单行” 使用:

set.seed(1234L)   # required to ensure reproducible data
test <- lapply(100L - 1:10, rnorm)

而不是

test <- list()
length(test) <- 10
for(i in 1:10){
  test[[i]] <- rnorm(100 - i) 
}

请注意使用set.seed()确保可重现的随机数据

要将test从长格式转换为长格式,请使用unlist()将整个列表一次性转换为data.frame,并根据需要添加其他列:

df <- data.frame(
  id = rep(seq_along(test), lengths(test)),
  x = sequence(lengths(test)),
  y = unlist(test)
)

而不是将每个列表元素转换为单独的小型data.frame,并使用for循环逐步将这些片段附加到目标data.frame。

然后通过

创建绘图
library(ggplot2)
ggplot(df) + geom_line(aes(x = x, y = y, color = as.factor(id)))

或者,melt()函数有一个列表方法:

library(data.table)
long <- melt(test, measure.vars = seq_along(test))
setDT(long)[, rn := rowid(L1)] # add row numbers for each group
ggplot(long) + aes(x = rn, y = value, color = as.factor(L1)) + geom_line()

答案 2 :(得分:1)

由于有关于for循环的一些评论,这里是现代习语中的另一种更复杂的方法(即来自tidyverse的java.lang.NoClassDefFoundError)。

  • 创建一个id向量作为因子(purrr),以避免以后有关组合级别的警告。
  • 设置一个函数(ids),以便根据id变量和数据向量生成数据框。
  • 使用mkdf中的map2合并purrr,将原始数据列表与ids
  • 合并
  • 使用mkdf中的bind_rows将结果数据框列表合并为一个。
  • 绘制它。

代码:

dplyr

情节。我减少了数据量,以便更容易看到: enter image description here