Tidyverse: замена NA на последние значения не-NA * с использованием инструментов Tidyverse * - PullRequest
0 голосов
/ 05 марта 2020

На мой вопрос был дан ответ перед использованием zoo:: и data.table::; Мне любопытно, каково было бы лучшее решение с tidyverse / dplyr.

Предыдущие ответы (без tidyverse): Прямой и обратный кадр данных заполнения в R Замена NA с последним значением, отличным от NA

Мои данные выглядят так: первые два года (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.

Таким образом, мой желаемый вывод:

#>   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

Ответы [ 2 ]

3 голосов
/ 05 марта 2020
# 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
)
3 голосов
/ 05 марта 2020

Мы можем replace NA с до 2017 года со значением, доступным в 2017 году для каждого 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
...