2015-10-20 30 views
2

采取一些简单的数据比赛以data.frame跨越一个以上的变量

A <- 1:10 
B <- 100:109 
C <- 222:231 
df1 <- data.frame(A,B,C) 
df1$Z <- 1:length(A) 

D <- c(2,3,4,6) 
E <- c(101,202,104,105) 
Ff <- c(223,999,225,227) 
df2 <- data.frame(D,E,Ff) 

现在我想创建df2$Z其分配DF1 $ d值时== d和B == E和C == FF,否则申请的NA

我试试这个代码,但是有不正确的语法:

df2$Z <- df1$Z[match(df1$A & df2$D & df1$B & df2$E & df1$C & df2$Ff)] 

回答

2

使用data.table我会做类似

library(data.table) 
setkey(setDT(df2))[df1, Z := i.Z] 
df2 
# D E Ff Z 
# 1: 2 101 223 2 
# 2: 3 202 999 NA 
# 3: 4 104 225 NA 
# 4: 6 105 227 6 

请注意,我们还没有设定关键列df1,因此连接在df2的键列与df1的前3列之间执行(即,按位置)。如果不能始终保证列顺序,请在相应的列上设置df1的键。


完全另一种方法,它不需要设定键(这需要重新排序,这并不总是可取的data.tables)是使用新实施on=说法(关于CRAN的最新版本 - v 1.9 .6):

library(data.table) # V 1.9.6+ 
setDT(df2)[df1, Z := i.Z, on = c(D = "A", E = "B", Ff = "C")] 
df2 
# D E Ff Z 
# 1: 2 101 223 2 
# 2: 3 202 999 NA 
# 3: 4 104 225 NA 
# 4: 6 105 227 6 
1

这很容易与左连接

library(dplyr) 
final <- df2 %>% 
    left_join(df1, by = c("D" = "A", "E" = "B", "Ff" = "C")) %>% 
    select(-D, D = D.y) 

tmp将包含D它来自原始df2D.y来自df1select(-D)删除D, select(D = D.y)D.y更改为Dselect(-D, D = D.y)首先删除D,然后D.yD,提供所需的结果。

tmp <- df2 %>% 
    left_join(df1, by = c("D" = "A", "E" = "B", "Ff" = "C")) 
+0

你可以请更新,我注意到答案中有2个D,所以我改变了一个,以避免混淆 – lukeg

1

基地R你可以做 - 列必须以相同的顺序:

x = apply(df2,1,paste0, collapse='') 
y = apply(df1[1:3],1, paste0, collapse='') 

df2$Z = df1$Z[match(x,y)] 

# D E Ff Z 
#1 2 101 223 2 
#2 3 202 999 NA 
#3 4 104 225 NA 
#4 6 105 227 6