2016-12-06 73 views
1

我有3个未知长度的数据帧。R:比较1个数据帧和另外两个不同长度的数据帧

数据帧A看起来像这样:

A1 A2 n 
1 1 2 1 
2 3 2 2 
3 2 4 3 

以类似的方式,数据帧B看起来像这样:

B1 B2 n 
1 3 4 1 
2 4 1 2 
3 1 3 3 

注意,对于每一行A1,A2,B1,B3是全部不同并且包含从1到4的数字。

最后,我有数据帧C

n C1 
1 1 3 
2 1 1 
3 1 4 
4 2 0 
5 2 2 
6 2 3 
7 3 3 
8 3 0 
9 3 1 

注意,C1的值全部为0至4。

n柱连接的所有数据帧。我想要做的是检查C1的值是否位于A数据帧或B中,并且这是为每个n。并在C1中直接替换它。如果值为0,它应该保持为0.这是我期待的结果:

n C1 
1 1 B 
2 1 A 
3 1 B 
4 2 0 
5 2 A 
6 2 A 
7 3 B 
8 3 0 
9 3 B 

我该如何做到这一点?感谢您的输入。

回答

2

这是一个想法。我们首先merge前两个数据帧。一旦我们merge,我们现在可以创建一个新的数据帧stack所有列(n除外)。通过(在我们的例子df5)创造这个新的数据帧,我们现在可以match粘贴n - 从df5与粘贴nvalue - 从你的第三个数据帧C1(在我们的例子df4)。一个简单的gsub操作然后只提取匹配值中的字母。作为最后一步,我们设置来港为0

df_all <- merge(df2, df3, by = 'n') 
# n A1 A2 B1 B2 
#1 1 1 2 3 4 
#2 2 3 2 4 1 
#3 3 2 4 1 3 

df5 <- data.frame(n = 1:nrow(df_all), stack(df_all[-1]), stringsAsFactors = FALSE) 
#head(df5) 
# n values ind 
#1 1  1 A1 
#2 2  3 A1 
#3 3  2 A1 
#4 1  2 A2 
#5 2  2 A2 
#6 3  4 A2 
ind <- gsub('\\d+', '', df5$ind)[match(do.call(paste, df4), do.call(paste, df5[-3]))] 
ind[is.na(ind)] <- 0 
ind 
#[1] "B" "A" "B" "0" "A" "A" "B" "0" "B" 
2

另外,略有不同,方法是左外连接两者ABC第一,然后找到该连接将添加的列等于C1

## Do the left outer joins with merge by n and all.x=TRUE 
out <- merge(merge(C,A,by="n",all.x=TRUE),B,by="n",all.x=TRUE) 
## Loop over rows and extract the name of the column whose value matches C1 
## first define a function to do so 
extract.name <- function(i,out) { 
    j <- which(out$C1[i]==out[i,3:ncol(out)]) 
    if (length(j)==0) return("0") else return(substr(colnames(out)[j[1]+2],1,1))      
} 
## Then, apply it to all rows 
out$C1 <- sapply(1:nrow(out),extract.name,out) 
## Keep only the n and C1 columns as output 
out <- out[,1:2] 
## n C1 
##1 1 B 
##2 1 A 
##3 1 B 
##4 2 0 
##5 2 A 
##6 2 A 
##7 3 B 
##8 3 0 
##9 3 B 

数据:

A <- structure(list(A1 = c(1L, 3L, 2L), A2 = c(2L, 2L, 4L), n = 1:3), .Names = c("A1", 
"A2", "n"), class = "data.frame", row.names = c("1", "2", "3" 
)) 
## A1 A2 n 
##1 1 2 1 
##2 3 2 2 
##3 2 4 3 

B <- structure(list(B1 = c(3L, 4L, 1L), B2 = c(4L, 1L, 3L), n = 1:3), .Names = c("B1", 
"B2", "n"), class = "data.frame", row.names = c("1", "2", "3" 
)) 
## B1 B2 n 
##1 3 4 1 
##2 4 1 2 
##3 1 3 3 

C <- structure(list(n = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), C1 = c(3L, 
1L, 4L, 0L, 2L, 3L, 3L, 0L, 1L)), .Names = c("n", "C1"), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9")) 
## n C1 
##1 1 3 
##2 1 1 
##3 1 4 
##4 2 0 
##5 2 2 
##6 2 3 
##7 3 3 
##8 3 0 
##9 3 1 
相关问题