带有 tidyverse dplyr 的通用数据框更新功能,如 sql-update

generic data frame update function with tidyverse dplyr like sql-update

我搜索了一个通用的数据框更新函数,例如 sql-update,它更新第一个数据框中的值,以防键与第二个数据框中的键匹配。是否有像我的示例中那样更通用的方法,也许还可以考虑值名称?像通用的 dplyr::update(df1, df2, by = "key") 函数?

library(tidyverse)
# example data frame
df1 <- as_data_frame(list(key = c(1,2,3,4,5,6,7,8,9),
                          v1 = c(11,12,13,14,15,16,17,18,19),
                          v2 = c(21,22,23,24,25,26,27,28,29),
                          v3 = c(31,32,33,34,35,36,37,38,39),
                          v4 = c(41,42,43,44,45,46,47,48,49)))
df2 <- as_data_frame(list(key = c(3,5,9),
                          v2 = c(231,252,293),
                          v4 = c(424,455,496)))

# update df1 with values from df2 where key match
org_names <- df1 %>% names()
df1 <- df1 %>% 
  left_join(df2, by = "key") %>% 
  mutate(v2 = ifelse(is.na(v2.y), v2.x, v2.y),
         v4 = ifelse(is.na(v4.y), v4.x, v4.y)) %>% 
  select(org_names)

> df1
# A tibble: 9 x 5
key    v1    v2    v3    v4
<dbl> <dbl> <dbl> <dbl> <dbl>
1     1    11    21    31    41
2     2    12    22    32    42
3     3    13   231    33   424
4     4    14    24    34    44
5     5    15   252    35   455
6     6    16    26    36    46
7     7    17    27    37    47
8     8    18    28    38    48
9     9    19   293    39   496
> 

1) %<>% Magrittr 有复合赋值管道:

library(magrittr)

df1 %>% 
    { keys <- intersect(.$key, df2$key)
    .[match(keys, .$key), names(df2)] %<>% { df2[match(keys, df2$key), ] }
    .
}

对于正在考虑的问题,可以简化为这个,因为 df2 中的所有键都在 df1 中:

df1 %>% { .[match(df2$key, .$key), names(df2)]  %<>% { df2 }; . }

2) <- 基本的 R 赋值运算符也可以以大致相同的方式使用,事实上,代码比 (1):

df1 %>% 
    { keys <- intersect(.$key, df2$key)
    .[match(keys, .$key), names(df2)] <- df2[match(keys, df2$key), ]
    .
}

然而,对于正在考虑的问题,df2 中的所有键都在 df1 中,因此它简化为:

df1 %>% { .[match(df2$key, .$key), names(df2)] <- df2; . }

3) mutate_cond 使用 中定义的 mutate_cond 我们可以编写以下内容。

df1 %>% mutate_cond(.$key %in% df2$key, v2 = df2$v2, v4 = df2$v4)

注意: 如果 df1df2 中的键都是唯一的,则前两种方法有效。第三个还要求键的顺序相同,并且 df2 中的每个键都在 df1 中。问题中的问题满足这些。

更新: 对 (1) 和 (2) 中的代码进行了一些概括。