使用 na.locf 为特定 country/variable 对扩展最后观察到的值
Extend last observed values using na.locf for specific country/variable pairs
我需要使用 zoo
包中的 na.locf
将 NA 值替换为最后观察到的值。但是,我只需要针对特定国家/地区和变量对执行此操作。这些对是使用单独的数据框在逻辑上指定的,示例如下所示。
Country <- c("FRA", "DEU", "CHE")
acctm <- c(0, 0, 1)
acctf <- c(1, 1, 0)
df1 <- data.frame(Country, acctm, acctf)
Country acctm acctf
1 FRA 0 1
2 DEU 0 1
3 CHE 1 0
a 1
表示对这对使用 na.locf
。下面显示了需要替换的数据集示例。
Country <- c("FRA", "FRA", "DEU", "DEU", "CHE", "CHE")
Year <- c(2010, 2020, 2010, 2020, 2010, 2020)
acctm <- c(20, 30, 10, NA, 20, NA)
acctf <- c(20, NA, 15, NA, 40, NA)
df2 <- data.frame(Country, Year, acctm, acctf)
Country Year acctm acctf
1 FRA 2010 20 20
2 FRA 2020 30 NA
3 DEU 2010 10 15
4 DEU 2020 NA NA
5 CHE 2010 20 40
6 CHE 2020 NA NA
给定两个示例数据集,函数在 df2 上针对 df1
指示的 country/variable 对执行 na.locf 的结果应如下所示:
acctm <- c(20, 30, 10, NA, 20, 20)
acctf <- c(20, 20, 15, 15, 40, NA)
df3 <- data.frame(Country, Year, acctm, acctf)
Country2 Year acctm acctf
1 FRA 2010 20 20
2 FRA 2020 30 20
3 DEU 2010 10 15
4 DEU 2020 NA 15
5 CHE 2010 20 40
6 CHE 2020 20 NA
真正的应用是一个更大的数据集,所以"calls"应该被泛化。谢谢。
一个dplyr
和tidyr
选项可以是:
df2 %>%
pivot_longer(-c(Country, Year)) %>%
left_join(df1 %>%
pivot_longer(names_to = "cond_names",
values_to = "cond_values", -Country),
by = c("Country" = "Country",
"name" = "cond_names")) %>%
group_by(Country, name) %>%
mutate(value = if_else(cond_values == 1, na.locf(value), value)) %>%
select(-cond_values) %>%
pivot_wider()
Country Year acctm acctf
<fct> <dbl> <dbl> <dbl>
1 FRA 2010 20 20
2 FRA 2020 30 20
3 DEU 2010 10 15
4 DEU 2020 NA 15
5 CHE 2010 20 40
6 CHE 2020 20 NA
一个选项是与 data.table
on
连接 'Country' 列,然后使用 Map
将 na.locf
应用于第二个数据集列( 'nm1') 基于第一个数据集对应列的值并将输出分配 (:=
) 回列
library(zoo)
library(data.table)
nm1 <- c('acctm', 'acctf')
nm2 <- paste0("i.", nm1)
setDT(df2)[df1, (nm1) := Map(function(x, y) if(y == 1) na.locf0(x)
else x, mget(nm1), mget(nm2)), on = .(Country), by = .EACHI]
df2
# Country Year acctm acctf
#1: FRA 2010 20 20
#2: FRA 2020 30 20
#3: DEU 2010 10 15
#4: DEU 2020 NA 15
#5: CHE 2010 20 40
#6: CHE 2020 20 NA
Left join df2 to df1 on Country 然后按 Country
分组为每个数字列生成适当的值。请注意,我们使用 na.locf0
确保结果与输入具有相同的长度。最后 select 适当的列。
library(dplyr)
library(zoo)
df2 %>%
left_join(df1, by = "Country") %>%
group_by(Country) %>%
mutate(acctm = if (first(acctm.y)) na.locf0(acctm.x) else acctm.x,
acctf = if (first(acctf.y)) na.locf0(acctf.x) else acctf.x) %>%
ungroup %>%
select(names(df2))
给予:
# A tibble: 6 x 4
Country Year acctm acctf
<fct> <dbl> <dbl> <dbl>
1 FRA 2010 20 20
2 FRA 2020 30 20
3 DEU 2010 10 15
4 DEU 2020 NA 15
5 CHE 2010 20 40
6 CHE 2020 20 NA
我需要使用 zoo
包中的 na.locf
将 NA 值替换为最后观察到的值。但是,我只需要针对特定国家/地区和变量对执行此操作。这些对是使用单独的数据框在逻辑上指定的,示例如下所示。
Country <- c("FRA", "DEU", "CHE")
acctm <- c(0, 0, 1)
acctf <- c(1, 1, 0)
df1 <- data.frame(Country, acctm, acctf)
Country acctm acctf
1 FRA 0 1
2 DEU 0 1
3 CHE 1 0
a 1
表示对这对使用 na.locf
。下面显示了需要替换的数据集示例。
Country <- c("FRA", "FRA", "DEU", "DEU", "CHE", "CHE")
Year <- c(2010, 2020, 2010, 2020, 2010, 2020)
acctm <- c(20, 30, 10, NA, 20, NA)
acctf <- c(20, NA, 15, NA, 40, NA)
df2 <- data.frame(Country, Year, acctm, acctf)
Country Year acctm acctf
1 FRA 2010 20 20
2 FRA 2020 30 NA
3 DEU 2010 10 15
4 DEU 2020 NA NA
5 CHE 2010 20 40
6 CHE 2020 NA NA
给定两个示例数据集,函数在 df2 上针对 df1
指示的 country/variable 对执行 na.locf 的结果应如下所示:
acctm <- c(20, 30, 10, NA, 20, 20)
acctf <- c(20, 20, 15, 15, 40, NA)
df3 <- data.frame(Country, Year, acctm, acctf)
Country2 Year acctm acctf
1 FRA 2010 20 20
2 FRA 2020 30 20
3 DEU 2010 10 15
4 DEU 2020 NA 15
5 CHE 2010 20 40
6 CHE 2020 20 NA
真正的应用是一个更大的数据集,所以"calls"应该被泛化。谢谢。
一个dplyr
和tidyr
选项可以是:
df2 %>%
pivot_longer(-c(Country, Year)) %>%
left_join(df1 %>%
pivot_longer(names_to = "cond_names",
values_to = "cond_values", -Country),
by = c("Country" = "Country",
"name" = "cond_names")) %>%
group_by(Country, name) %>%
mutate(value = if_else(cond_values == 1, na.locf(value), value)) %>%
select(-cond_values) %>%
pivot_wider()
Country Year acctm acctf
<fct> <dbl> <dbl> <dbl>
1 FRA 2010 20 20
2 FRA 2020 30 20
3 DEU 2010 10 15
4 DEU 2020 NA 15
5 CHE 2010 20 40
6 CHE 2020 20 NA
一个选项是与 data.table
on
连接 'Country' 列,然后使用 Map
将 na.locf
应用于第二个数据集列( 'nm1') 基于第一个数据集对应列的值并将输出分配 (:=
) 回列
library(zoo)
library(data.table)
nm1 <- c('acctm', 'acctf')
nm2 <- paste0("i.", nm1)
setDT(df2)[df1, (nm1) := Map(function(x, y) if(y == 1) na.locf0(x)
else x, mget(nm1), mget(nm2)), on = .(Country), by = .EACHI]
df2
# Country Year acctm acctf
#1: FRA 2010 20 20
#2: FRA 2020 30 20
#3: DEU 2010 10 15
#4: DEU 2020 NA 15
#5: CHE 2010 20 40
#6: CHE 2020 20 NA
Left join df2 to df1 on Country 然后按 Country
分组为每个数字列生成适当的值。请注意,我们使用 na.locf0
确保结果与输入具有相同的长度。最后 select 适当的列。
library(dplyr)
library(zoo)
df2 %>%
left_join(df1, by = "Country") %>%
group_by(Country) %>%
mutate(acctm = if (first(acctm.y)) na.locf0(acctm.x) else acctm.x,
acctf = if (first(acctf.y)) na.locf0(acctf.x) else acctf.x) %>%
ungroup %>%
select(names(df2))
给予:
# A tibble: 6 x 4
Country Year acctm acctf
<fct> <dbl> <dbl> <dbl>
1 FRA 2010 20 20
2 FRA 2020 30 20
3 DEU 2010 10 15
4 DEU 2020 NA 15
5 CHE 2010 20 40
6 CHE 2020 20 NA