【问题标题】:One plot, multiple time series, from CSV files with ggplot2一个情节,多个时间序列,来自带有 ggplot2 的 CSV 文件
【发布时间】:2016-02-11 04:01:06
【问题描述】:

我对 R 还是很陌生,只是不知道如何做到这一点,尽管有一些类似但不完全一样的问题四处流传。我有几个 (~10) CSV 文件,如下所示:

time, value
0, 5
100, 4
200, 8
etc.

那是他们记录了当时一长串的时间和价值观。我想使用 ggplot2 将它们全部绘制在 R 中的一个图表上,使其看起来像这样。我一直在尝试各种融合和合并,但到目前为止都没有成功(尽管 read.csv 工作正常,我可以轻松地一一绘制文件)。我不知道的一件事是是否在所有数据到达 ggplot2 之前合并所有数据,或者以某种方式将所有数据单独传递给 ggplot2。

我可能应该注意到,每个数据系列共享完全相同的时间点。我的意思是,如果文件 1 在时间 100、200、300、...、1000 处具有值,那么所有其他文件也是如此。 理想情况下,我希望解决方案不依赖于它,因为我可以看到未来的情况,时间比例相似但不完全相同,例如文件 1 的时间为 99、202、302、399,...,文件 2 的时间为 101、201、398、400,...

非常感谢。

编辑:我可以像这样(笨拙地)使用普通的plot 来做到这一点,这可能说明了我想做的事情:

f1 = read.csv("file1.txt")
f2 = read.csv("file2.txt")
f3 = read.csv("file3.txt")
plot(f1$time,f1$value,type="l",col="red")
lines(f2$time, f2$value, type="l",col="blue" )
lines(f3$time, f3$value, type="l",col="green" )

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    我会将其分为 4 个任务。这也有助于为每个人寻找答案。

    1. Reading a few files automatically, without harcoding the file names 
    2. Merging these data.frame's , using a "left join"
    3. Reshaping the data for ggplot2
    4. Plotting a line graph
    

    .

    # Define a "base" data.frame
    max_time = 600
    base_df <- data.frame(time=seq(1, max_time, 1))
    
    # Get the file names
    all_files = list.files(pattern='.*csv')
    
    # This reads the csv files, check if you need to make changes in read.csv
    all_data <- lapply(all_files, read.csv)
    
    # This joins the files, using the "base" data.frame
    ls = do.call(cbind, lapply(all_data, function(y){
      df = merge(base_df, y, all.x=TRUE, by="time")
      df[,-1]
    }))
    
    # This would have the data in "wide" format
    data = data.frame(time=base_df$time, ls)
    
    # The plot
    library(ggplot2)
    library(reshape2)
    
    mdf = melt(data, id.vars='time')
    ggplot(mdf, aes(time, value, color=variable, group=variable)) +
      geom_line() +
      theme_bw()
    

    【讨论】:

    • 嘿,非常感谢。这行得通。我认为你的意思是你把“输出”放在“数据”的地方,小错字。数据最终标记为 X1、X2 等,有没有办法控制每列的​​名称?理想情况下,列名应该是“.csv”之前的文件名,如果这不是太难的话。
    【解决方案2】:
    # Creating fake data
    fNames <- c("file1.txt", "file2.txt", "file3.txt")
    
    write.csv(data.frame(time=c(1, 2, 4), value=runif(3)), file=fNames[1])
    write.csv(data.frame(time=c(3, 4), value=runif(2)), file=fNames[2])
    write.csv(data.frame(time=c(5), value=runif(1)), file=fNames[3])
    

    这是我的尝试,

    fNames <- c("file1.txt", "file2.txt", "file3.txt")
    
    allData <- do.call(rbind, # Read the data and combine into single data frame
                   lapply(fNames,
                          function(f){
                            cbind(file=f, read.csv(f))
                          }))
    require(ggplot2)
    ggplot(allData)+
      geom_line(aes(x=time, y=value, colour=file)) # This way all series have a legend!
    

    【讨论】:

    • @marbel 我不确定我是否理解你。我使用cbind 只是为了添加一个标识文件名的附加列,同时使用rbind 组合文件。在不同的文件中有不同的时间点应该不会影响这一点。
    • 我明白了。那么,如果第一个文件中有时间:{1, 2, 4} 和第二个 {1, 3, 4} 呢?
    • 这不是问题,我已经更新了我的答案以反映相同的情况。现在每个文件都会有一个随机的时间戳。
    • 这不仅仅是随机的,而是不同的数量。我已经用一个更现实的案例调整了你的代码并且它有效。查看编辑。
    • 谢谢?我使用了sample(1000, 100),所以时间不同!无论如何,我想可读性确实会增加你的方式。
    【解决方案3】:

    您有四种方法可以做到这一点。

    第一

    您可以将所有数据合并到一个数据框中,然后分别绘制每条线。下面是使用示例数据的代码:

    library(ggplot2)
    library(reshape2)
    data1 <- data.frame(time=1:200, series1=rnorm(200))
    data2 <- data.frame(time=1:200, series2=rnorm(200))
    
    mergeData <- merge(data1, data2, by="time", all=TRUE)
    
    g1 <- ggplot(mergeData, aes(time, series1)) + geom_line(aes(color="blue")) + ylab("")
    g2 <- g1 + geom_line(data=mergeData, aes(x=time, y=series2, color="red")) + guides(color=FALSE)
    g2
    

    第二次

    您可以融合合并的数据,然后使用单个 ggplot 代码进行绘图。下面是代码:

    library(reshape2)
    meltData <- melt(mergeData, id="time")
    ggplot(meltData, aes(time, value, color=variable)) + geom_line()
    

    第三 这与您的编辑类似。变量名应该相同。

    library(ggplot2)
    data1 <- data.frame(time=1:200, series1=rnorm(200))
    data2 <- data.frame(time=1:200, series1=rnorm(200))
    
    g1 <- ggplot(data1, aes(time, series1)) + geom_line(aes(color="blue")) + ylab("")
    g2 <- g1 + geom_line(data=data2, aes(color="red")) + guides(color=FALSE)
    g2
    

    第四法:

    这是完成任务的最通用方法,做出最少的假设。这种方法并不假设每个数据集中的变量名称都相同,但它会让你编写更多代码(代码中的变量名称错误, 会报错)。

    library(ggplot2)
    
    data1 <- data.frame(id=1:200, series1=rnorm(200))
    data2 <- data.frame(id=1:200, series2=rnorm(200))
    
    g1 <- ggplot() + geom_line(data=data1, aes(x=id, y=series1, color="red")) +
           geom_line(data=data2, aes(x=id, y=series2, color="blue")) + guides(color=FALSE)
    g1
    

    【讨论】:

    • 在第三种方法中,请注意我在两个 data.frames 中保持列的名称相同。您可以为不同的 csv 文件执行类似的代码。如果对您有帮助,请点赞回答。
    • 您没有阅读答案中的文件。你错过了第一部分
    • 我认为读取 csv 文件不是问题。我认为这个问题是能够使用不同的 data.frames 绘制多个折线图。因此我的回答。
    猜你喜欢
    • 2010-10-05
    • 2016-11-30
    • 1970-01-01
    • 2020-08-10
    • 2021-05-15
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    相关资源
    最近更新 更多