【问题标题】:Overwrite values from selected columns and matching rows from one data frame into another, R将选定列中的值和匹配行从一个数据帧覆盖到另一个数据帧中,R
【发布时间】:2021-11-09 21:48:11
【问题描述】:

我有 2 个数据框,df1 和 df2。两个数据框中的列名相同,并且列“field_name”是唯一标识符(每行都有一个唯一的字段名)。 df2 的行数没有 df1 多。

df2 中的某些值与 df1 中的值不同,我想将这些值导入 df1,以便 df1 中的原始值被 df2 中的值覆盖。

我想要提取到 df1 中的“不同”值将始终在 df2 的列中找到,其中包含字符串“4”(肯定是字符串,在数字前有文本)或字符串“tgp”。对于这些列,我想将 df1 中的值替换为 df2 中的值。但是,这不适用于每一行:df2 小于 df1,因此我需要在行上进行匹配,以便仅在 df2 中也存在的 df1 行中替换值。

这里的代码显示了我所追求的:

df1 <- data.frame(list(field_name = c("a", "b", "c", "d"),  A3=c("23", "35", "2", "5"), A4=c("94", "120", "67", "5"), B3=c("35", "64", "87", "70"), B4=c("99", "76", "22", "83"), tgp=c("1000", "1542", "758", "964")))

df2 <- data.frame(list(field_name = c("a", "b", "d"),       A3=c("13", "28", "10"),      A4=c("56", "11", "16"),       B3=c("42", "58", "91"),       B4=c("13", "64", "12"),       tgp=c("1154", "1200", "900")))

df_result <- data.frame(list(field_name = c("a", "b", "c", "d"), A3=c("23", "35", "2", "5"), A4=c("56", "11", "67", "16"), B3=c("35", "64", "87", "70"), B4=c("13", "64", "22", "12"), tgp=c("1154", "1200", "758", "900")))

在此示例中,我从 df2 中获取字段名称“a”、“b”和“d”的值,从列“A4”、“B4”和“tgp”,并覆盖相同的值df1 中的位置。对于这个小例子,我可以通过索引手动完成,但我有很多包含所需字符串的列和很多行。

我做到了这一点(在帮助下!),但由于两个数据帧中的行数不相等,它不起作用:

columns <- which(grepl(colnames(df1), pattern = "4|tgp"))
rows <- which(apply(df1, 1, function(x) which(x %in% intersect(df1$field_name, df2$field_name)))==T)
 

new_df <- df1
for(col in columns){
  for (r in rows){
  new_df[r,col] <- df2[r,col]
  }
}

如果可能的话,我希望采用矢量化解决方案。我试过玩“mutate_at”和“replace”,但到目前为止还没有得到任何有用的东西。以下...

df1 %>%
  left_join(df2, by = "field_name")

...来自this post 看起来很有希望,但我还没有设法使“转化”工作。

非常感谢。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    实验函数rows_update(在dplyr 1.0 版中引入)可以很好地满足您的需求:

    rows_update(
      df1,
      ## use only the columns from df2 that you want to update
      ## plus the joining column
      select(df2, field_name, tgp, ends_with("4")),
      by = "field_name"
    )
    #   field_name A3 A4 B3 B4  tgp
    # 1          a 23 56 35 13 1154
    # 2          b 35 11 64 64 1200
    # 3          c  2 67 87 22  758
    # 4          d  5 16 70 12  900
    

    详情请见?rows_update。还有 rows_insert 添加新行,rows_upsert 添加新行并更新现有行,以及其他几个选项。

    【讨论】:

    • 这是完美的 - 谢谢!
    猜你喜欢
    • 2013-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 2021-04-03
    • 1970-01-01
    • 2020-09-20
    • 2021-03-21
    相关资源
    最近更新 更多