【问题标题】:Replace values in dataframe based on multiple rows from other dataframes根据来自其他数据帧的多行替换数据帧中的值
【发布时间】:2020-01-24 03:45:44
【问题描述】:

我有 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

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    我们可以使用intersect 找到常用列。重复df2 和df3 的行并将它们与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
    

    如果我们要填充df1中剩余的值,而df2和df3中不存在,则基于cmets,我们可以找出不匹配的索引并使用paste0将值粘贴在一起。

    temp_df2 <- df2[rep(seq_len(nrow(df2)), nrow(df1)), ]
    temp_df3 <- df3[rep(seq_len(nrow(df2)), nrow(df1)), ]
    df1[cols][df1[cols] == temp_df2] <- 1
    df1[cols][df1[cols] == temp_df3] <- 2
    inds <- (df1[cols] != 1) & (df1[cols] != 2)
    df1[cols][inds] <- paste0(df1[cols][inds], temp_df2[inds], temp_df3[inds])
    
    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 ytt
    #2  q  e  r  t  2   2 eqq rwt  1   2   2 ytt
    #3  w  e  r  t  2 tyq   1   1  1   2   1   1
    

    【讨论】:

    • 非常感谢您的回复。这解决了问题。我只是有另一个问题 - 不是用“-”替换没有 1 或 2 的单元格,是否可以应用函数。例如,在输出中,而不是“-”,只需使用 df1、df2 和 df3 的连接字符串填充它们?
    • @Victor 连接值是什么意思?你能用一个例子解释一下吗?所以c6 中的- 将被替换为?
    • c6 中的“-”将被 df2 的 c6 和 df3 中的 tyq、y 和 q 替换,df1 的 c6 的第 3 行中的 t。
    【解决方案2】:

    我们可以通过复制“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))
    

    【讨论】:

    • 非常感谢您的回复。我敢肯定,这个输出几乎和我问的一样。输出也可以是一个字符。我指定了“-”,因为原始数据中已经存在缺失值,并且我不想将具有不同值的单元格填充为缺失值。我还有另一个问题 - 不是用 NA 替换单元格,而是可以应用一个函数。例如,在输出中,而不是 NA,只需用 df1、df2 和 df3 的连接字符串填充它们?
    • @Victor 这很容易解决。但我也解释了为什么它不应该在那里
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多