【问题标题】:Updating Values in New Data with Old Data用旧数据更新新数据中的值
【发布时间】:2021-12-29 04:23:09
【问题描述】:

我有以下数据框:

library(dplyr)

old_data = data.frame(id = c(1,2,3), var1 = c(11,12,13))

> old_data

  id var1
1  1   11
2  2   12
3  3   13

我想用“new_data”中的数据替换“old_data”第二行中的值(即“old_data”中id变量匹配的行):

new_data = data.frame(id = c(4,2,5), var1 = c(11,15,13))

> new_data

  id var1
1  4   11
2  2   15
3  5   13

使用此处找到的答案 (Update rows of data frame in R),我尝试使用“dplyr”库来做到这一点:

update =  old_data %>%
     rows_update(new_data, by = "id")

但这给了我以下错误:

Error: Attempting to update missing rows.
Run `rlang::last_error()` to see where the error occurred.

这就是我想要得到的:

   id var1
    1  1   11
    2  2   15
    3  3   13

谁能告诉我我做错了什么?

谢谢!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    有点乱,但这有效(至少在这个示例数据上)

    old_data %>% 
      left_join(new_data,by="id") %>% 
      mutate(var1 = if_else(!is.na(var1.y),var1.y,var1.x)) %>% 
      select(id,var1)
    
    #  id var1
    #1  1   11
    #2  2   15
    #3  3   13
    

    【讨论】:

    • @马丁:非常感谢!这有效!
    • 我很高兴!请尽可能考虑将其标记为已接受。谢谢!
    【解决方案2】:

    使用match 的基本 R 方法 -

    inds <- match(old_data$id, new_data$id)
    old_data$var1[!is.na(inds)] <- na.omit(new_data$var1[inds])
    old_data
    
    #  id var1
    #1  1   11
    #2  2   15
    #3  3   13
    

    【讨论】:

      【解决方案3】:

      data.table 方法(将数据表转回数据框):

      library(data.table)
      
      as.data.frame(setDT(old_data)[new_data, var1 := .(i.var1), on = "id"])
      

      输出

        id var1
      1  1   11
      2  2   15
      3  3   13
      

      使用rows_update 的替代tidyverse 选项。您可以过滤new_data 以仅在old_data 中出现ids。然后,您可以更新这些值,就像您之前尝试过的那样。本质上,new_data 只能有出现在old_data 中的id 值。

      library(tidyverse)
      
      old_data %>% 
        rows_update(., new_data %>% filter(id %in% old_data$id), by = "id")
      

      数据

      old_data <-
        structure(list(id = c(1, 2, 3), var1 = c(11, 12, 13)),
                  class = "data.frame",
                  row.names = c(NA,-3L))
      new_data <-
        structure(list(id = c(4, 2, 5), var1 = c(11, 15, 13)),
                  class = "data.frame",
                  row.names = c(NA,-3L))
      

      【讨论】:

        【解决方案4】:

        如果我们首先在new_data 上使用semi_join 来仅过滤包含在old_data 中的ids,我们可以使用dplyr::rows_update

        library(dplyr)
        
        old_data %>% 
          rows_update(new_data %>%
                        semi_join(old_data, by = "id"),
                      by = "id")
        
        #>   id var1
        #> 1  1   11
        #> 2  2   15
        #> 3  3   13
        

        reprex package (v0.3.0) 于 2021 年 12 月 29 日创建

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-07-03
          • 1970-01-01
          • 1970-01-01
          • 2018-12-02
          • 1970-01-01
          • 2013-02-02
          • 2021-09-04
          相关资源
          最近更新 更多