带有 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)
注意: 如果 df1
和 df2
中的键都是唯一的,则前两种方法有效。第三个还要求键的顺序相同,并且 df2 中的每个键都在 df1 中。问题中的问题满足这些。
更新: 对 (1) 和 (2) 中的代码进行了一些概括。
我搜索了一个通用的数据框更新函数,例如 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)
注意: 如果 df1
和 df2
中的键都是唯一的,则前两种方法有效。第三个还要求键的顺序相同,并且 df2 中的每个键都在 df1 中。问题中的问题满足这些。
更新: 对 (1) 和 (2) 中的代码进行了一些概括。