Tidyverse:用最新的非 NA 值替换 NA *使用 tidyverse 工具*
Tidyverse: Replacing NAs with latest non-NA values *using tidyverse tools*
我的问题在使用zoo::
和data.table::
之前已经得到解答;我很好奇 tidyverse/dplyr 的最佳解决方案是什么。
以前的答案(非 tidyverse):
Replacing NAs with latest non-NA value
我的数据是这样的,其中每个国家(美国,澳大利亚)最早的两年(2015年,2016年)都有缺失数据(底部数据输入代码):
#> country year value
#> 1 usa 2015 NA
#> 2 usa 2016 NA
#> 3 usa 2017 100
#> 4 usa 2018 NA
#> 5 aus 2015 NA
#> 6 aus 2016 NA
#> 7 aus 2017 50
#> 8 aus 2018 60
我想用 2017 年可用的值填充每个国家/地区内的缺失值。
我希望只填写 2017 年之前的年份——因此 2018 年的 NA 不应填写任何内容。它应该保持 NA。
所以我想要的输出是:
#> country year value
#> 1 usa 2015 100
#> 2 usa 2016 100
#> 3 usa 2017 100
#> 4 usa 2018 NA
#> 5 aus 2015 50
#> 6 aus 2016 50
#> 7 aus 2017 50
#> 8 aus 2018 60
我尝试了 group_by(country)
然后我怀疑我打算使用 coalesce()
,但我通常跨矢量使用 coalesce
,而不是沿矢量使用。
library(tidyverse)
df %>% group_by(country) %>%
使用 tidyverse 工具最简单的方法是什么?
数据输入代码:
#install.packages("datapasta")
df <- data.frame(
stringsAsFactors = FALSE,
country = c("usa", "usa", "usa", "usa", "aus", "aus", "aus", "aus"),
year = c(2015L, 2016L, 2017L, 2018L, 2015L, 2016L, 2017L, 2018L),
value = c(NA, NA, 100L, NA, NA, NA, 50L, 60L)
)
df
我们可以 replace
2017 年之前的 NA
和每个 country
.
在 2017 年可用的值
library(dplyr)
df %>%
group_by(country) %>%
mutate(value = replace(value, is.na(value) & year < 2017, value[year == 2017]))
#Similarly with ifelse
#mutate(value = ifelse(is.na(value) & year < 2017, value[year == 2017], value))
# country year value
# <chr> <int> <int>
#1 usa 2015 100
#2 usa 2016 100
#3 usa 2017 100
#4 usa 2018 NA
#5 aus 2015 50
#6 aus 2016 50
#7 aus 2017 50
#8 aus 2018 60
# Tidyverse solution
library(tidyverse)
df %>%
group_by(country) %>%
arrange(year) %>%
fill(value, .direction = 'up') %>%
ungroup() %>%
arrange(country, year)
# Base R solution:
data.frame(do.call("rbind", lapply(split(df, df$country), function(x){
x$value[which(is.na(x$value) & x$year < 2017)] <- x$value[which(x$year == 2017)]
return(x)
}
)
),
row.names = NULL
)
我的问题在使用zoo::
和data.table::
之前已经得到解答;我很好奇 tidyverse/dplyr 的最佳解决方案是什么。
以前的答案(非 tidyverse):
我的数据是这样的,其中每个国家(美国,澳大利亚)最早的两年(2015年,2016年)都有缺失数据(底部数据输入代码):
#> country year value
#> 1 usa 2015 NA
#> 2 usa 2016 NA
#> 3 usa 2017 100
#> 4 usa 2018 NA
#> 5 aus 2015 NA
#> 6 aus 2016 NA
#> 7 aus 2017 50
#> 8 aus 2018 60
我想用 2017 年可用的值填充每个国家/地区内的缺失值。
我希望只填写 2017 年之前的年份——因此 2018 年的 NA 不应填写任何内容。它应该保持 NA。
所以我想要的输出是:
#> country year value
#> 1 usa 2015 100
#> 2 usa 2016 100
#> 3 usa 2017 100
#> 4 usa 2018 NA
#> 5 aus 2015 50
#> 6 aus 2016 50
#> 7 aus 2017 50
#> 8 aus 2018 60
我尝试了 group_by(country)
然后我怀疑我打算使用 coalesce()
,但我通常跨矢量使用 coalesce
,而不是沿矢量使用。
library(tidyverse)
df %>% group_by(country) %>%
使用 tidyverse 工具最简单的方法是什么?
数据输入代码:
#install.packages("datapasta")
df <- data.frame(
stringsAsFactors = FALSE,
country = c("usa", "usa", "usa", "usa", "aus", "aus", "aus", "aus"),
year = c(2015L, 2016L, 2017L, 2018L, 2015L, 2016L, 2017L, 2018L),
value = c(NA, NA, 100L, NA, NA, NA, 50L, 60L)
)
df
我们可以 replace
2017 年之前的 NA
和每个 country
.
library(dplyr)
df %>%
group_by(country) %>%
mutate(value = replace(value, is.na(value) & year < 2017, value[year == 2017]))
#Similarly with ifelse
#mutate(value = ifelse(is.na(value) & year < 2017, value[year == 2017], value))
# country year value
# <chr> <int> <int>
#1 usa 2015 100
#2 usa 2016 100
#3 usa 2017 100
#4 usa 2018 NA
#5 aus 2015 50
#6 aus 2016 50
#7 aus 2017 50
#8 aus 2018 60
# Tidyverse solution
library(tidyverse)
df %>%
group_by(country) %>%
arrange(year) %>%
fill(value, .direction = 'up') %>%
ungroup() %>%
arrange(country, year)
# Base R solution:
data.frame(do.call("rbind", lapply(split(df, df$country), function(x){
x$value[which(is.na(x$value) & x$year < 2017)] <- x$value[which(x$year == 2017)]
return(x)
}
)
),
row.names = NULL
)