根据其他数据框中的多行替换数据框中的值

时间:2019-09-24 04:37:19

标签: r dataframe

我有3个数据帧。第一个数据帧(例如df1)具有多个行和列。第二个数据帧和第三个数据帧(例如df2和df3)只有一行,并且只有df1的列子集。 df2和df3中的列名称相同。所以我想做的是将df1中的每一行与df2和df3中的单行进行比较。如果来自df1的单元格的值与df2的单元格内容匹配,则将df1中的单元格的值替换为1,如果来自df1的单元格的值与df3匹配,则将df1中的单元格的值替换为2和如果df2的单元格内容与df2或df3不匹配,请用-替换df1中的单元格值。我编写了一个循环来执行此操作,但是速度很慢。我想知道是否有任何优化的方法来做到这一点。谢谢。

以下是示例数据帧和预期的输出:

df1
c1  c2  c3  c4  c5  c6  c7  c8  c9  c10 c11 c12
 q  w   e   r   t   y   q   w   e   r   t   y
 q  e   r   t   y   q   e   r   e   r   t   y
 w  e   r   t   y   t   q   w   e   r   w   t

df2
                c5  c6  c7  c8  c9  c10 c11 c12
                t   y   q   w   e   t   w   t

df3             
                c5  c6  c7  c8  c9  c10 c11 c12
                y   q   q   t   e   r   t   t

Expected output:                
c1  c2  c3  c4  c5  c6  c7  c8  c9  c10 c11 c12
q   w   e   r   1   1   1   1   1   2   2   -
q   e   r   t   2   2   -   -   1   2   2   -
w   e   r   t   2   -   1   1   1   2   1   1

2 个答案:

答案 0 :(得分:0)

我们可以通过复制'df2'和'df3'的行来创建一对逻辑矩阵,同时仅选择与'df2'或'df3'相同的df1列,然后将值组合为一个逐步进行逻辑比较

i1 <- df1[names(df2)] == df2[rep(1, nrow(df1)),]
i2 <- df1[names(df3)] == df3[rep(1, nrow(df1)),]
df1[names(df3)] <- ((!i1 & i2) + 1) * NA^(!i1 & !i2)
df1
#   c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12
#1  q  w  e  r  1  1  1  1  1   2   2  NA
#2  q  e  r  t  2  2 NA NA  1   2   2  NA
#3  w  e  r  t  2 NA  1  1  1   2   1   1

最好使用NA而不是-,因为-可以将列类型从numeric更改为character

数据

df1 <- structure(list(c1 = c("q", "q", "w"), c2 = c("w", "e", "e"), 
    c3 = c("e", "r", "r"), c4 = c("r", "t", "t"), c5 = c("t", 
    "y", "y"), c6 = c("y", "q", "t"), c7 = c("q", "e", "q"), 
    c8 = c("w", "r", "w"), c9 = c("e", "e", "e"), c10 = c("r", 
    "r", "r"), c11 = c("t", "t", "w"), c12 = c("y", "y", "t")), class = "data.frame", row.names = c(NA, 
-3L))

df2 <- structure(list(c5 = "t", c6 = "y", c7 = "q", c8 = "w", c9 = "e", 
    c10 = "t", c11 = "w", c12 = "t"), class = "data.frame", row.names = c(NA, 
-1L))

df3 <- structure(list(c5 = "y", c6 = "q", c7 = "q", c8 = "t", c9 = "e", 
    c10 = "r", c11 = "t", c12 = "t"), class = "data.frame", row.names = c(NA, 
-1L))

答案 1 :(得分:0)

我们可以使用intersect找到常见的列。重复df2df3的行,并将其与df1进行比较,并将df1中的匹配值替换为1,将df2的匹配值替换为2,并替换所有其他值由"-"

cols <- intersect(names(df1), names(df2))
df1[cols][df1[cols] == df2[rep(seq_len(nrow(df2)), nrow(df1)), ]] <- 1
df1[cols][df1[cols] == df3[rep(seq_len(nrow(df3)), nrow(df1)), ]] <- 2
df1[cols][(df1[cols] != 1) & (df1[cols] != 2)] <- "-"


df1
#  c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12
#1  q  w  e  r  1  1  1  1  1   2   2   -
#2  q  e  r  t  2  2  -  -  1   2   2   -
#3  w  e  r  t  2  -  1  1  1   2   1   1

基于注释,如果我们要填充df1df2中不存在的df3中的剩余值,我们可以找出不匹配的索引并使用{{1} }将值粘贴在一起。

paste0