Расширьте последние наблюдаемые значения, используя na.locf для указанных c пар страна / переменная - PullRequest
2 голосов
/ 27 января 2020

Мне нужно использовать na.locf из пакета zoo, чтобы заменить значения NA последним наблюдаемым значением. Тем не менее, мне нужно сделать это только для конкретных c страна и переменные пары. Эти пары определяются логически с использованием отдельного фрейма данных, пример которого показан ниже.

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

Для обоих примеров наборов данных результат выполнения функции na.locf в df2 для пар страна / переменная обозначен df1 должно выглядеть так:

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

Реальное приложение - это намного больший набор данных, поэтому «вызовы» должны быть обобщены. Спасибо.

Ответы [ 3 ]

2 голосов
/ 27 января 2020

Один из вариантов - объединение с data.table on столбцом 'Страна', затем используйте 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
0 голосов
/ 27 января 2020

Соединение слева от df2 до df1 в стране, а затем группировка по Country создает соответствующее значение для каждого столбца чисел c. Обратите внимание, что мы используем na.locf0, что гарантирует, что результат будет иметь ту же длину, что и входные данные. Наконец, выберите соответствующие столбцы.

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
0 голосов
/ 27 января 2020

Один 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
...