【问题标题】:Generate multiple serial graphs/scatterplots from data in two dataframes从两个数据帧中的数据生成多个串行图/散点图
【发布时间】:2011-11-08 20:57:10
【问题描述】:

我有 2 个数据帧,Tg 和 Pf,每个数据帧 127 列。所有列都至少有一行,最多可以有数千个。所有值都在 0 和 1 之间,并且存在一些缺失值(空单元格)。这是一个小子集:

Tg
Tg1 Tg2 Tg3 ... Tg127
0.9 0.5 0.4     0
0.9 0.3 0.6     0
0.4 0.6 0.6     0.3
0.1 0.7 0.6     0.4
0.1 0.8
0.3 0.9
    0.9
    0.6
    0.1

Pf
Pf1 Pf2 Pf3 ...Pf127
0.9 0.5 0.4    1
0.9 0.3 0.6    0.8 
0.6 0.6 0.6    0.7
0.4 0.7 0.6    0.5
0.1     0.6    0.5
0.3
0.3
0.3

请注意,某些单元格是空的,并且同一子集(即 1 到 127)的向量长度可能非常不同,并且很少有完全相同的长度。 我想为 127 个向量生成 127 个图形,如下所示(即图形用于每个数据帧的 col 1,图形 2 用于每个数据帧的 col 2 等...):

希望这是有道理的。我期待您的帮助,因为我不想一张一张地制作这些图表...... 谢谢!

【问题讨论】:

    标签: r graph dataframe repeat


    【解决方案1】:

    这是一个让您入门的示例(数据位于https://gist.github.com/1349300)。如需进一步调整,请查看网络上出色的 ggplot2 文档。

    library(ggplot2)
    
    # Load data
    Tg = read.table('Tg.txt', header=T, fill=T, sep=' ')
    Pf = read.table('Pf.txt', header=T, fill=T, sep=' ')
    
    # Format data
    Tg$x        = as.numeric(rownames(Tg))
    Tg          = melt(Tg, id.vars='x')
    Tg$source   = 'Tg'
    Tg$variable = factor(as.numeric(gsub('Tg(.+)', '\\1', Tg$variable)))
    
    Pf$x        = as.numeric(rownames(Pf))
    Pf          = melt(Pf, id.vars='x')
    Pf$source   = 'Pf'
    Pf$variable = factor(as.numeric(gsub('Pf(.+)', '\\1', Pf$variable)))
    
    # Stack data
    data = rbind(Tg, Pf)
    
    # Plot
    dev.new(width=5, height=4)
    p = ggplot(data=data, aes(x=x)) + geom_line(aes(y=value, group=source, color=source)) + facet_wrap(~variable)
    p
    


    突出显示线条之间的区域

    首先,将数据插入到更精细的网格中。这样,功能区将跟随线条的实际包络线,而不仅仅是原始数据点所在的位置。

    data = ddply(data, c('variable', 'source'), function(x) data.frame(approx(x$x, x$value, xout=seq(min(x$x), max(x$x), length.out=100))))
    names(data)[4] = 'value'
    

    接下来,计算geom_ribbon 所需的数据——即ymaxymin

    ribbon.data = ddply(data, c('variable', 'x'), summarize, ymin=min(value), ymax=max(value))
    

    现在是时候进行绘图了。请注意我们如何添加了一个新的功能区层,我们用新的ribbon.data 框架代替了它。

    dev.new(width=5, height=4)
    p + geom_ribbon(aes(ymin=ymin, ymax=ymax),  alpha=0.3, data=ribbon.data)
    


    线条之间的动态着色

    最棘手的变化是如果您希望颜色根据数据而变化。为此,您当前必须创建一个新的分组变量来识别不同的段。例如,在这里,我们可能会使用一个函数来指示“Tg”组何时位于顶部:

    GetSegs <- function(x) {
      segs = x[x$source=='Tg', ]$value > x[x$source=='Pf', ]$value
      segs.rle = rle(segs)
    
      on.top = ifelse(segs, 'Tg', 'Pf')
      on.top[is.na(on.top)] = 'Tg'
    
      group = rep.int(1:length(segs.rle$lengths), times=segs.rle$lengths)
      group[is.na(segs)] = NA
    
      data.frame(x=unique(x$x), group, on.top)
    }
    

    现在我们应用它并将结果与​​我们的原始功能区数据合并。

    groups = ddply(data, 'variable', GetSegs)
    ribbon.data = join(ribbon.data, groups)
    

    对于情节,关键是我们现在为带状几何体指定分组美学。

    dev.new(width=5, height=4)
    p + geom_ribbon(aes(ymin=ymin, ymax=ymax, group=group, fill=on.top),  alpha=0.3, data=ribbon.data)
    

    代码一起在:https://gist.github.com/1349300

    【讨论】:

    • 我听说 ggplot2 很强大,但那真是令人震惊!这正是我所需要的。我将玩弄显示布局和颜色。是否可以为两条线之间的区域着色?
    • 很棒的 ggplot2 插图。 Olivier,请注意@John Colby 如何通过堆叠数据使他的数据“高”。当人们开始使用 ggplot2 时,这一步是造成很多混乱/沮丧的根源。
    • @Olivier 太好了,我很高兴它有帮助! ggplot2 确实令人印象深刻,这是一个很好的例子,它可以在单行中捕获整个图形描述。 JD 也提出了一个 优秀 的观点,使用 ggplot2 获得快乐的关键是熟悉如何重塑数据。
    • @Olivier 当你想在这样交叉的两条线之间填充时,它会变得有点棘手。我认为目前您必须制作一个额外的分组变量来标识每个细分市场。这是一个很好的参考类似的问答:stackoverflow.com/questions/7883154/…。有时间我也会发布这个示例的相关代码。
    • 是的... 用data = data[!is.na(data$value), ]ribbon.data = ribbon.data[!is.na(ribbon.data$ymax), ] 之类的东西删除最后的NA。然后在第一个 ggplot 调用中添加 scales='free' 可选参数并重做绘图。 x 限制现在将全部齐平。
    【解决方案2】:

    这是一个三班轮做同样的事情:-)。我们首先从basereshape 将数据转换为长格式。然后,它被融化以适应ggplot2。最后,我们生成情节!

    mydf   <- reshape(cbind(Tg, Pf), varying = 1:8, direction = 'long', sep = "")
    mydf_m <- melt(mydf, id.var = c(1, 4), variable = 'source') 
    qplot(id, value, colour = source, data = mydf_m, geom = 'line') + 
      facet_wrap(~ time, ncol = 2)
    

    注意。 base R 中的 reshape 函数非常强大,尽管使用起来非常混乱。它用于在longwide 格式之间转换数据。

    【讨论】:

    • 非常简约的代码,它也可以工作!我现在正在学习 ggplot2 !
    【解决方案3】:

    感谢您使用 R 将您以前在 Excel 中执行的操作自动化!这正是我开始使用 R 的方式以及通向 R 启蒙的共同途径 :)

    您真正需要的只是一点点循环。这是一个示例,其中大部分是创建代表您的数据结构的示例数据:

    ## create some example data
    
    Tg <- data.frame(Tg1 = rnorm(10))
    for (i in 2:10) {
      vec <- rep(NA, 8)
      vec <- c(rnorm(sample(5:10,1)), vec)
      Tg[paste("Tg", i, sep="")] <- vec[1:10]
    
    }
    
    Pf <- data.frame(Pf1 = rnorm(10))
    for (i in 2:10) {
      vec <- rep(NA, 8)
      vec <- c(rnorm(sample(5:10,1)), vec)
      Pf[paste("Pf", i, sep="")] <- vec[1:10]
    
    }
    ## ok, sample data created
    
    ## now lets loop through all the columns
    ## if you didn't know how many columns there are you could 
    ## use ncol(Tg) to figure out
    
    for (i in 1:10) {
      plot(1:10, Tg[,i], type = "l", col="blue", lwd=5, ylim=c(-3,3), 
         xlim=c(1, max(length(na.omit(Tg[,i])), length(na.omit(Pf[,i])))))
      lines(1:10, Pf[,i], type = "l", col="red", lwd=5, ylim=c(-3,3))
      dev.copy(png, paste('rplot', i, '.png', sep=""))
      dev.off()
    }
    

    这将在您的工作目录中生成 10 个图表,如下所示:

    【讨论】:

    • 确实,你在读我的心!我可以看到它需要编写脚本,但我不知道该怎么做。玩弄你的代码,直到我得到它,这将有很大的指导帮助。非常感谢!我会继续阅读 R 书籍并玩转。很高兴听到你这样开始!如果你有什么让你成功的通用指针,我会全神贯注:)
    • 坚韧。在无情的汗水下,一切都放弃了。技能被高估了:)
    • 哈哈。我希望有一颗灵丹妙药;)但蛮力经常做到这一点。
    • 关于能够改变 X 轴使其最大值为向量 Tg 或 Pf 的最大值的任何建议,以较长者为准。实际上,在我的真实数据集中,x 值从 200 到 10,000 并且在 10,000 轴上绘制所有内容会压缩较短的向量。与此同时,我正在玩你的代码。
    • @ JD :我认为以下方法可行,但不知何故它仍然绘制到 10:for (i in 1:ncol(Tg)) { plot(1:length(Tg[,i]) , Tg[,i], type = "l", col="blue", lwd=5, ylim=c(-3,3)) 行(1:length(Pf[,i]), Pf[,i ], type = "l", col="red", lwd=5, ylim=c(-3,3)) dev.copy(png, paste('rplot', i, '.png', sep=" ")) dev.off() }
    猜你喜欢
    • 2018-03-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    • 2023-01-14
    • 1970-01-01
    相关资源
    最近更新 更多