【问题标题】:Replacing values by values of a different dataframe in R用R中不同数据框的值替换值
【发布时间】:2021-09-17 15:49:07
【问题描述】:

我有这种数据框(df1):

     Code    ID_CODE     value_1   value_2    value_3
     HA09U    98_ 10      57.80      NA          NA
     HA09U    98_ 11      57.80      NA          NA
     HA09U    98_ 12      57.80      NA          NA 
     MB03L    99_ 10        NA      90.77        NA
     MB03L    99_ 11        NA      90.77        NA
     MB03L    99_ 12        NA      90.77        NA
     KE17P    100_ 10      68.44    76.05        72.01
     KE17P    100_ 11      68.44    76.05        72.01
     KE17P    100_ 12      68.44    76.05        72.01

我想通过添加我的第二个数据帧 (df2) 中的值来替换包含 NA 的人的所有变量(value_1、value_2 和 value_3)的值:

     Code    value_1   value_2    value_3
    HA09U     90.35     89.84      90.07
    MB03L     66.94     79.62      73.77

结果应该是:

      Code    ID_CODE     value_1    value_2    value_3
     HA09U    98_ 10       90.35      89.84      90.07
     HA09U    98_ 11       90.35      89.84      90.07
     HA09U    98_ 12       90.35      89.84      90.07 
     MB03L    99_ 10       66.94      79.62      73.77
     MB03L    99_ 11       66.94      79.62      73.77
     MB03L    99_ 12       66.94      79.62      73.77
     KE17P    100_ 10      68.44      76.05      72.01
     KE17P    100_ 11      68.44      76.05      72.01
     KE17P    100_ 12      68.44      76.05      72.01

我尝试使用一些 merge 和 bind_rows 函数,这个最接近我:

df1$value_1[df1$Code == df2$Code] <- df2$value_1

但它不起作用,并且以某种方式弄乱了数据框。

使用此代码

d1 <- left_join(df1, df2, by = "Code" )

用 df2 的值添加三个新列,但缺少 KE17P(已经拥有完整数据的人)的值。所以我真的在寻找替代功能。

【问题讨论】:

  • left_join() from dplyr 会给你你想要的。
  • 我尝试了df3&lt;- left_join(df1, df2, by = "Code" ),到目前为止它一直有效......但是通过添加三个新列而不是替换原始列中的旧值来添加 df2 中的值
  • 所以在你做left_join之前从df1删除原始列...
  • 是的,但是原始数据帧要复杂得多,并且有多个 df2 中不存在的 ID 和行。因此,如果我删除它们,它们就会丢失,因为在新列中它们都有 NAs
  • 然后重写你的问题,使其包含问题的所有显着特征。

标签: r dataframe replace


【解决方案1】:

我们可以在data.table 中使用连接(这里,我们假设NA 列是numeric 类而不是logical

library(data.table)
nm1 <- grep('^value_\\d+$', names(df1), value = TRUE)
setDT(df1)[df2, (nm1) := mget(paste0('i.', nm1)), on = .(Code)]

-输出

df1
#    Code ID_CODE value_1 value_2 value_3
#1: MB03L  99_ 10   66.94   79.62   73.77
#2: MB03L  99_ 11   66.94   79.62   73.77
#3: MB03L  99_ 12   66.94   79.62   73.77
#4: MB03L  99_ 13   66.94   79.62   73.77
#5: MB03L  99_ 14   66.94   79.62   73.77
#6: MB03L  99_ 15   66.94   79.62   73.77

或使用tidyverse

library(dplyr)
library(stringr)
left_join(df1, df2, by = 'Code') %>%
  transmute(Code, ID_CODE, across(ends_with('.x'), ~ 
     coalesce(get(str_replace(cur_column(),"\\.x", ".y")), .))) %>% 
  rename_with(~ str_remove(., '\\.x'), starts_with('value_'))

-输出

#    Code ID_CODE value_1 value_2 value_3
#1 MB03L  99_ 10   66.94   79.62   73.77
#2 MB03L  99_ 11   66.94   79.62   73.77
#3 MB03L  99_ 12   66.94   79.62   73.77
#4 MB03L  99_ 13   66.94   79.62   73.77
#5 MB03L  99_ 14   66.94   79.62   73.77
#6 MB03L  99_ 15   66.94   79.62   73.77

数据

df1 <- structure(list(Code = c("MB03L", "MB03L", "MB03L", "MB03L", "MB03L", 
"MB03L"), ID_CODE = c("99_ 10", "99_ 11", "99_ 12", "99_ 13", 
"99_ 14", "99_ 15"), value_1 = c(NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_), value_2 = c(90.77, 90.77, 90.77, 
90.77, 90.77, 90.77), value_3 = c(NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_)), row.names = c(NA, -6L), class = "data.frame")


df2 <- structure(list(Code = c("HA09U", "MB03L"), value_1 = c(90.35, 
66.94), value_2 = c(89.84, 79.62), value_3 = c(90.07, 73.77)),
class = "data.frame", row.names = c(NA, 
-2L))

【讨论】:

  • @psycho95 因为 'df1' 和 df2' 中的列名相同,所以 df2 列用前缀 i.values_1、i.values_2 等标识。
  • 我收到value for ‘i.’ not found
  • @psycho95 你加载了library(data.table) 。请使用我帖子中的数据,然后再试一次。谢谢
  • 我使用了您的数据,但不知何故没有使用我的数据框
  • 我重启了R,又试了,现在成功了,不知道为什么之前没有...非常感谢!
猜你喜欢
  • 1970-01-01
  • 2014-12-15
  • 1970-01-01
  • 2016-02-10
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
相关资源
最近更新 更多