2017-04-12 62 views
0

合併dataframes我怎樣才能,從以下兩個數據幀:與NA的有效

DF1:

cat1  cat2 
a   NA 
b   NA 
c   NA 
d   NA 
e   NA 

DF2:

cat1  cat2 
c   1 
d   2 

產生如下結果儘可能高效

cat1  cat2 
a   NA 
b   NA 
c   1 
d   2 
e   NA 

當我這樣做:

df3 <- rbind(df2,df1[!(df1$cat1 %in% df2$cat1),]) 
merge(df1,df3,all.y=TRUE) 

我得到想要的數據幀。但是,是不是一個整潔,也許更有效的方式來做到這一點? (這只是虛擬數據 - 我有700K行數據在現實中)

+1

您應該編寫代碼來生成一個足夠大的示例,可能是行數或類似函數的函數,並考慮cat1值是否唯一。 – Frank

+0

Fwiw,這可能是最快的方法:http://stackoverflow.com/q/14720923/如果可行,我們可以關閉這個問題。 – Frank

回答

1

如何:

df1 <-read.table(text="cat1  cat2 
a   NA 
b   NA 
c   NA 
d   NA 
e   NA",header=TRUE,stringsAsFactors=FALSE) 

df2<-read.table(text="cat1  cat2 
c   1 
d   2",header=TRUE, stringsAsFactors=FALSE) 

df1[df1$cat1%in%df2$cat1,] <-df2 

    cat1 cat2 
1 a NA 
2 b NA 
3 c 1 
4 d 2 
5 e NA 

編輯

我跑在你的解決方案microbenchmark,我的解決辦法而解決方案data.table在另一個答案中是我最快的。

df1[df1$cat1%in%df2$cat1,] <-df2 1000次計算的平均時間爲80微秒。這與data.table解決方案的690微秒相比,您的解決方案總共爲1062微秒。如此有效,我的解決方案速度要快一個數量級。

library(microbenchmark) 
res <- microbenchmark(
rbind(df2,df1[!(df1$cat1 %in% df2$cat1),]), 
merge(df1,df3,all.y=TRUE), 
df1[df1$cat1%in%df2$cat1,] <-df2, 
dat1[dat][,1:2,with=T], 
times=1000L) 

> print(res) 
Unit: microseconds 
             expr  min  lq *mean* median  uq  max neval 
rbind(df2, df1[!(df1$cat1 %in% df2$cat1), ]) 242.395 260.3555 279.3699 268.3550 277.5615 2817.263 1000 
       merge(df1, df3, all.y = TRUE) 679.488 724.1640 783.2416 740.1625 761.5940 6756.541 1000 
     df1[df1$cat1 %in% df2$cat1, ] <- df2 63.392 72.1450 80.0050 75.1640 80.5975 2017.334 1000 
        dat1[dat][, 1:2, with = T] 602.816 649.6040 690.9846 665.3010 691.2615 3264.319 1000 

EDIT2

另一個microbenchmark 100,000數據點和包括setkeyv步驟data.table。基礎索引(df[df$cat1 %in% df1$cat1, ] <- df)比data.table(7.4毫秒)的總步驟稍快(平均7毫秒),但不多。效率將取決於OP的實際數據集。

library(data.table) 
dat <- data.table(cat1=c(paste0("a",1:100000)),cat2=rep(NA,100000)) 
dat1 <- data.table(cat1=c(paste0("a",sample(1:100000,10001))),cat2=1:10001) 
setkeyv(dat,"cat1") 
setkeyv(dat1,"cat1") 
df <- data.frame(dat) 
df1 <- data.frame(dat1) 

library(microbenchmark) 
res <- microbenchmark(
    merge(df,df1,all.y=TRUE), 
    df[df$cat1 %in% df1$cat1, ] <- df1, 
    setkeyv(dat,"cat1"), 
    setkeyv(dat1,"cat1"), 
    dat1[dat][,1:2,with=T], 
    times=100L) 
print(res) 
Unit: microseconds 
           expr  min  lq  mean median   uq  max neval cld 
     merge(df, df1, all.y = TRUE) 96573.600 98317.435 115509.544 102872.81 130325.979 195910.42 100 d 
df[df$cat1 %in% df1$cat1, ] <- df1 4329.293 4785.601 7059.100 5054.74 5632.501 40521.16 100 c 
       setkeyv(dat, "cat1") 1166.073 1568.211 1928.071 1766.36 1913.329 14256.59 100 ab 
       setkeyv(dat1, "cat1") 215.253 296.935 434.589 443.05 506.629 1279.54 100 a 
     dat1[dat][, 1:2, with = T] 3531.004 4020.242 5024.882 4195.72 4587.026 34787.45 100 bc 
+1

如果您在此處顯示的小數據集上進行了基準測試,則不一定有意義。 – Frank

+0

@Frank你是對的。我添加了另一個編輯,其中包含100,000個數據點的microbenchmark,幷包含'data.table'開銷'setkeyv'步驟。在這種情況下,基於df [df $ cat1%的%df1 $ cat1,] < - df1'索引仍然更快,但僅稍微如此。這將取決於OP的實際數據集。 –

+0

好的,謝謝。我已經把data.table的基準測試更新加入到了聊天中:http://chat.stackoverflow.com/transcript/message/36605566#36605566它不需要排序/鍵控,並且會正確處理在'df1 $ cat1'不會出現在'df $ cat1'中,出現多次,等等。 – Frank