我有几个csv文件,每个文件大约有50,000行。所有文件都有名为id
和PositionX
的列。只有当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
...
有没有办法快速完成?
答案 0 :(得分:1)
不确定SQL处理该大文件的能力,但使用if-then-when命令的连接可能会有所帮助 - 如果您使用SQL服务器。
答案 1 :(得分:1)
使用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
答案 2 :(得分:1)
full_join
包的 dlpyr
比merge
快一点。可重复的例子如下:
> 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
您的实际加速(或减速)可能取决于匹配的稀疏程度,行数,列数,数据框数等。