我的数据格式如下:
#> country year value
#> 1 AUS 2019 100
#> 2 USA 2019 120
#> 3 AUS 2018 90
df <- data.frame(stringsAsFactors=FALSE,
country = c("AUS", "USA", "AUS"),
year = c(2019, 2019, 2018),
value = c(100, 120, 90)
)
我有一个单行数据帧,它表示应覆盖数据中现有记录的修订。
#> country year value
#> 1 AUS 2019 500
df2 <- data.frame(stringsAsFactors=FALSE,
country = c("AUS"),
year = c(2018),
value = c(500)
)
我想要的输出是:
#> country year value
#> 1 AUS 2019 100
#> 2 USA 2019 120
#> 3 AUS 2018 500
我知道如何找到要覆盖的行:
library(tidyverse)
df %>% filter(country == overwrite$country & year == overwrite$year) %>%
mutate(value = overwrite$value)
但是如何将其放回原始数据帧中呢?
整洁的答案对我来说更容易使用,但我对任何解决方案都持开放态度。
使用mutate
和if_else
:
library(tidyverse)
df %>%
mutate(value = if_else(country %in% df2$country & year %in% df2$year, df2$value, value))
结果:
country year value
1 AUS 2019 100
2 USA 2019 120
3 AUS 2018 500
在这里,一种有效的方法是将on
与data.table
连接起来。 将"data.frame"转换为"data.table"(setDT(df)
(,将on
与"国家"上的"df2"连接,"年份"分配(:=
(第二个数据集(i.value
(中的"值"列以替换原始数据集中的"值">
library(data.table)
setDT(df)[df2, value := i.value, on = .(country, year)]
df
# country year value
#1: AUS 2019 100
#2: USA 2019 120
#3: AUS 2018 500
一种可能的整理方法,使用1(。anti_join
从将要替换的行中删除df
和 2(。bind_rows
添加df2
中的替换行:
library(dplyr)
anti_join(df, df2, by = c("country", "year")) %>% bind_rows(df2)
#> country year value
#> 1 AUS 2019 100
#> 2 USA 2019 120
#> 3 AUS 2018 500
或者,另一个使用 1(。right_join
连接新旧值和 2(。coalesce
仅保留新值:
right_join(df2, df, by = c("country", "year")) %>%
transmute(country, year, value = coalesce(value.x, value.y))
#> country year value
#> 1 AUS 2019 100
#> 2 USA 2019 120
#> 3 AUS 2018 500