【问题标题】:generic data frame update function with tidyverse dplyr like sql-update具有 tidyverse dplyr 的通用数据框更新功能,如 sql-update
【发布时间】:2017-11-16 14:48:11
【问题描述】:

我搜索了一个通用数据框更新函数,例如 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
> 

【问题讨论】:

  • 我什么都不知道。但是,dplyr::db_write_table 有一个参数来创建一个临时表,DBI::dbExecute 可以用来使用新创建的临时表执行更新。
  • 我也发现了一个类似的问题stackoverflow.com/questions/45217477/… 有一个使用data.table的答案
  • 啊,我误读了您的问题,是在询问有关在 SQL 数据库中进行更新的问题——您只是想编辑本地数据框对象,对吧?

标签: r if-statement tidyverse dplyr


【解决方案1】:

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 使用this SO post 中定义的mutate_cond,我们可以编写以下代码。

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

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

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

【讨论】:

    猜你喜欢
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多