2017-04-21 192 views
5

在df1中,我需要用df2中的相應值替換msec的值。根據條件集,用其他數據幀中的值替換數據幀中的值

df1 <- data.frame(ID=c('rs', 'rs', 'rs', 'tr','tr','tr'), cond=c(1,1,2,1,1,2), 
block=c(2,2,4,2,2,4), correct=c(1,0,1,1,1,0), msec=c(456,678,756,654,625,645)) 

df2 <- data.frame(ID=c('rs', 'rs', 'tr','tr'), cond=c(1,2,1,2), 
block=c(2,4,2,4), mean=c(545,664,703,765)) 

在DF1,如果correct==0,然後引用df2IDcondblock匹配值。將df1中的msec的值替換爲df2mean的相應值。

例如,df1中的第二行有correct==0。因此,在df2找到相應的行,其中ID=='rs',cond==1,block==2並使用平均值(mean=545)替換msec的值(msec=678)。請注意,在df1 ID,block和cond的組合中,可以重複,但每個組合在df2中只出現一次。

回答

3

使用data.table包:

# load the 'data.table' package 
library(data.table) 

# convert the data.frame's to data.table's 
setDT(df1) 
setDT(df2) 

# update df1 by reference with a join with df2 
df1[df2[, correct := 0], on = .(ID, cond, block, correct), msec := i.mean] 

這給:

> df1 
    ID cond block correct msec 
1: rs 1  2  1 456 
2: rs 1  2  0 545 
3: rs 2  4  1 756 
4: tr 1  2  1 654 
5: tr 1  2  1 625 
6: tr 2  4  0 765 

注:上面的代碼將更新df1代替創建一個新的數據幀,這是更高效的內存。

+0

'df1 [c(list(correct = 0),df2),on =。(correct,ID,cond,block),msec:= i.mean]'?我想這幾乎是一樣的。也許值得一提的是,這個更新df1而不是製作一個新表格(如dplyr變體)。 – Frank

+0

這太好了。謝謝! – rds

2

一種選擇是使用基數R與interaction()match()。如何:

df1[which(df1$correct==0),"msec"] <- df2[match(interaction(df1[which(df1$correct==0),c("ID","cond","block")]), 
               interaction(df2[,c("ID","cond", "block")])), 
             "mean"] 

df1 
#  ID cond block correct msec 
#1 rs 1  2  1 456 
#2 rs 1  2  0 545 
#3 rs 2  4  1 756 
#4 tr 1  2  1 654 
#5 tr 1  2  1 625 
#6 tr 2  4  0 765 

我們覆蓋correct == 0列與其匹配的行中df2$mean

編輯:另一種選擇將是一個SQL合併,這可能是這樣的:

library(sqldf) 
merged <- sqldf('SELECT l.ID, l.cond, l.block, l.correct, 
         case when l.correct == 0 then r.mean else l.msec end as msec 
       FROM df1 as l 
       LEFT JOIN df2 as r 
       ON l.ID = r.ID AND l.cond = r.cond AND l.block = r.block') 


merged 
    ID cond block correct msec 
1 rs 1  2  1 456 
2 rs 1  2  0 545 
3 rs 2  4  1 756 
4 tr 1  2  1 654 
5 tr 1  2  1 625 
6 tr 2  4  0 765 
1

隨着dplyr 。該解決方案left_join所有列和mutate當正確0

library(dplyr) 
left_join(df1,df2)%>% 
mutate(msec=ifelse(correct==0,mean,msec))%>% 
select(-mean) 

    ID cond block correct msec 
1 rs 1  2  1 456 
2 rs 1  2  0 545 
3 rs 2  4  1 756 
4 tr 1  2  1 654 
5 tr 1  2  1 625 
6 tr 2  4  0 765 
相關問題