R:将1个数据帧与不同长度的另外两个数据帧进行比较

时间:2016-12-06 13:28:20

标签: r

我有3个未知长度的数据框。

数据框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 个答案:

答案 0 :(得分:2)

这是一个想法。我们首先merge前两个数据帧。在我们merge之后,我们现在可以通过stack所有列(n除外)创建新的数据框。通过创建此新数据框(我们的情况为df5),我们现在可以match粘贴n - value来自df5并粘贴n } - 来自您的第三个数据框的C1(在我们的例子中为df4)。然后,简单的gsub操作只从匹配的值中提取字母。最后一步,我们将NAs设置为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"

答案 1 :(得分:2)

另一种略有不同的方法是首先将AB外部联接到C,然后找到由等于{{1}的联接添加的列}:

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