【问题标题】:merging Large csv files合并大型csv文件
【发布时间】:2017-05-24 05:59:00
【问题描述】:

我有几个 csv 文件,每个文件大约有 50,000 行。所有文件都有名为idPositionX 的列。我只想在 id 和 PositionX 相同的情况下绑定它们。如果不一样,只需放一个 NA。我正在使用以下内容:

datlist<-list(Cfour,Cfive,Csix,Cseven,Cten,Ctwelve,Cthirteen,Cfourteen,Cfifteen,Csixteen,Cseventeen,Cnineteen,Ctwoone,Ctwofour,Ctwosix,Ctwonine,Cthreethree,Cthreeseven,Cfourty)
ss<-Reduce(function(df1,df2) merge(df1,df2,by=c("id", "PositionX"),all=T),datlist)

例如文件 1 有,

id PositionX val1
1 5 4.2
2 8 4.3

文件 2 有

  id PositionX val2
    1 5 6.3
    2 8 9.3

文件 3 有

  id PositionX val3
        0 5 6.2
        2 8 9.3

我想拥有

     id PositionX val1 val2 val3
      0 5  NA NA 6.2
      1 5  4.2 6.3 NA
  ...

有没有办法快速做到这一点?

【问题讨论】:

  • 你检查过full_joindplyr 包吗?
  • 这有点不清楚。您想要合并多个 CSV 文件(数据框),其中包含 id、positionX 和其他数据。还有什么数据?如果两个以上的 csv 文件具有相同的 id、positionX 变量怎么办?输出数据中有多少个变量?您只是想从长格式转换为宽格式吗?显示一些示例输入和输出。
  • @Spacedman 我希望这很清楚。
  • @Jamil 是的!更清晰。

标签: r csv


【解决方案1】:

dlpyr 包中的full_joinmerge 快一点。可重现的示例如下:

> set.seed(123)
> library(dplyr)
> d = data.frame(id=1:100,Pos=1:100,val1=runif(100))
> f1 = d[sample(100,80),]
> f2 = d[sample(100,80),]
> f3 = d[sample(100,80),]
> names(f2)[3]="val2"
> names(f3)[3]="val3"
> head(f1)
   id Pos      val1
60 60  60 0.3744628
33 33  33 0.6907053
48 48  48 0.4659625
93 93  93 0.3435165
47 47  47 0.2330341
85 85  85 0.1028646
> head(f2)
   id Pos      val2
84 84  84 0.7881958
31 31  31 0.9630242
70 70  70 0.4398317
26 26  26 0.7085305
58 58  58 0.7533079

f3 也是如此。

要使用dplyr 进行合并,其:

> jd = Reduce(full_join, list(f1,f2,f3))
Joining, by = c("id", "Pos")
Joining, by = c("id", "Pos")

给予:

> head(jd %>% arrange(id))
  id Pos      val1      val2      val3
1  1   1 0.2875775        NA 0.2875775
2  2   2        NA        NA 0.7883051
3  3   3        NA 0.4089769 0.4089769
4  4   4        NA 0.8830174 0.8830174
5  5   5 0.9404673 0.9404673 0.9404673
6  6   6 0.0455565        NA 0.0455565

与您的相同:

> head(Reduce(function(df1,df2) merge(df1,df2,by=c("id", "Pos"),all=T),list(f1,f2,f3)))
  id Pos      val1      val2      val3
1  1   1 0.2875775        NA 0.2875775
2  2   2        NA        NA 0.7883051
3  3   3        NA 0.4089769 0.4089769
4  4   4        NA 0.8830174 0.8830174
5  5   5 0.9404673 0.9404673 0.9404673
6  6   6 0.0455565        NA 0.0455565

除了不按id排序(因此是arrange)。

要进行基准测试,首先我们需要一个 full_join 包装函数来指定列,以便在我们对其进行基准测试时它不会花费所有时间来尖叫消息:

> fj = function(a,b){full_join(a,b,by=c("id","Pos"))}

现在我们可以在使用library(microbenchmark) 之后运行基准测试:

> microbenchmark(Reduce(fj,list(f1,f2,f3)),Reduce(function(df1,df2) merge(df1,df2,by=c("id", "Pos"),all=T),list(f1,f2,f3)))
Unit: microseconds
                                                                                            expr
                                                                    Reduce(fj, list(f1, f2, f3))
 Reduce(function(df1, df2) merge(df1, df2, by = c("id", "Pos"),      all = T), list(f1, f2, f3))
      min       lq     mean    median       uq       max neval
  860.491  901.746 1108.901  936.0205 1016.623  6951.609   100
 3133.837 3245.754 4092.630 3291.7825 3616.122 15828.191   100

您的实际加速(或减速)可能取决于匹配的稀疏程度、行数、列数、数据帧数等。

【讨论】:

    【解决方案2】:

    不确定 SQL 处理该大文件的能力,但如果您使用 SQL Server,则使用 if-then-when 命令进行连接可能会有所帮助。

    【讨论】:

      【解决方案3】:

      使用 data.table 包更快(可能工作)

      library(data.table)
      df1=data.table(df1)
      df2=data.table(df2)
      df3=data.table(df3)
      
      setkey(df1, id, PositionX)
      setkey(df2, id, PositionX)
      setkey(df2, id, PositionX)
      
      j1=df1[df2, alpha := i.alpha]
      j2=df3[j1, alpha := i.alpha]
      

      在基础 R 中这绝对有效

      > df1
        id PositionX val1
      1  1         5  4.2
      2  2         8  4.3
      > df2
        id PositionX val2
      1  1         5  6.3
      2  2         8  9.3
      > df3
        id PositionX val3
      1  0         5  6.2
      2  2         8  9.3
      > merge(df1,df2,by=c("id","PositionX"))
        id PositionX val1 val2
      1  1         5  4.2  6.3
      2  2         8  4.3  9.3
      > j1=merge(df1,df2,by=c("id","PositionX"))
      > j1
        id PositionX val1 val2
      1  1         5  4.2  6.3
      2  2         8  4.3  9.3
      > merge(j1,df3,by=c("id","PositionX"))
        id PositionX val1 val2 val3
      1  2         8  4.3  9.3  9.3
      > merge(j1,df3,by=c("id","PositionX"),all=T)
        id PositionX val1 val2 val3
      1  0         5   NA   NA  6.2
      2  1         5  4.2  6.3   NA
      3  2         8  4.3  9.3  9.3
      

      dplyr 会在 data.table 格式上运行得更快 http://stat545.com/bit001_dplyr-cheatsheet.html#full_joinsuperheroes-publishers

      【讨论】:

      • 请阅读更新后的问题,不要跳入不清楚的问题。
      • 船长!
      猜你喜欢
      • 2021-05-04
      • 2015-04-01
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-06
      • 2016-04-09
      • 1970-01-01
      相关资源
      最近更新 更多