【问题标题】:Overlay lines with a varying number of points from a list using ggplot2使用ggplot2从列表中覆盖具有不同数量点的线
【发布时间】:2017-06-03 16:38:18
【问题描述】:

我想使用 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中进行转换了。

【问题讨论】:

  • 您必须将数据从“宽格式”转换为“长格式”才能执行此操作。这将需要为每个流添加一个标识符。可能ggplot 最令人困惑的事情是必须这样做,并且在你完成六次左右之前它并不是微不足道的。
  • 到目前为止你尝试过什么?这里有很多类似的问题。
  • 当然,这些都不是特别合适,因为他从列表中的数据开始 - 每个列表可能有不同数量的点,而不是数据框。从宽到长的所有简单方法都假设一个数据框。
  • 列表中每个向量的长度不同。那么,是不可能在data.frame中转换的。
  • @MikeWise 感谢您编辑 Q。现在很明显我不是骗子。我已投票决定重新开放。

标签: r ggplot2


【解决方案1】:

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

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

但是,如果您确实有一个数据框,这意味着一组相同长度的向量,那么您可以使用melt。然而,使用来自tidyrgather 可能比来自reshape2melt 更现代。请注意,melt 也可以用于列表,尽管我必须研究它如何处理 id。

我也选择不使用 lapply 类中的函数,因为我想强调“宽数据”到“长数据”方面 - 我认为 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))

产量:

【讨论】:

  • n &lt;- sequence(10); ind &lt;- 100 - n; df &lt;- data.frame(id = rep(n, ind), x = sequence(ind), y = rnorm(sum(ind)))
  • 就像@rawr 我很困惑为什么问答都使用笨拙的for 循环,尽管R 具有简洁的功能。 type可以在单行中创建:set.seed(1234L); test &lt;- lapply(100L - 1:10, rnorm)。要将test 从宽格式重塑为适合ggplot2 的长格式,我们可以使用df &lt;- data.frame(id = rep(seq_along(test), lengths(test)), x = sequence(lengths(test)), y = unlist(test))
  • 我当然知道lapply,而且我一直都在使用它,但我认为在这里使用它并不合适。用户使用for 循环提出问题,这让我相信他可能不熟悉lapply。我觉得for 循环具有更高的教学价值——因为我试图理解的主要教训是在使用ggplot2 时需要从宽(ish)数据到长数据,这当然是主要障碍为初学者使用ggplot。一次一节课。并且for 循环并没有那么糟糕,尽管反对者显然是这么认为的。
  • 链接的副本是为melt 应用于数据框,显然不是我们这里的。
  • 无论如何,您为什么不将您的方法作为解决方案发布?当然是从他的数据开始。顺便说一句,我没有看到您使用任何与“重复链接”相关的内容。
【解决方案2】:

正如Mike Wise 在他的accepted answer 中已经指出的那样,gplot2 需要一个 data.frame 作为输入,最好是长格式

但是,尽管 R 具有简洁的功能,但问题和接受的答案都使用了 for 循环。要创建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()

【讨论】:

  • 我喜欢使用基本的 base-R 函数创建一步数据框(好吧,除了 unlist 我猜,但仍然如此)。
【解决方案3】:

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

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

代码:

library(tidyr)

# dummpy up some wide data (but of different lengths) in a **list** of curves
test <- list()
for(i in 1:5){
  test[[i]] <- rnorm(10 - i) 
}

# helper data (could do inline, but it would be harder to read)
ids <- as.factor(sprintf("id-%d",1:length(test)))             # curve ids as factors
mkdf <- function(x,y) data.frame(xx=1:length(x),yy=x,key=y)   # makes into dataframe

df <- test %>% map2(ids,mkdf) %>%  bind_rows()   #single pipe using purrr and dplyr

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

一个情节。我减少了数据大小以使其更易于查看:

【讨论】:

    猜你喜欢
    • 2018-09-30
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    • 2017-06-26
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    • 2019-05-06
    相关资源
    最近更新 更多