Как интерполировать / экстраполировать, используя функцию na.approx в отдельных группах в R

У меня есть набор данных панели с 10 переменными для 60 стран за 18 лет (2000-2017), и у меня много пропущенных данных.

Country Year    Broadband

Albania 2000    NA
Albania 2001    NA
Albania 2002    NA
Albania 2003    NA
Albania 2004    NA
Albania 2005    272
Albania 2006    NA
Albania 2007    10000
Albania 2008    64000
Albania 2009    92000
Albania 2010    105539
Albania 2011    128210
Albania 2012    160088
Albania 2013    182556
Albania 2014    207931
Albania 2015    242870
Albania 2016    263874
Albania 2017    NA
Algeria 2000    NA
Algeria 2001    NA
Algeria 2002    NA
Algeria 2003    18000
Algeria 2004    36000

Я хотел бы интерполировать, используя функцию na.approx в R (и экстраполировать, используя правило = 2), но только внутри каждой страны. Например, в этом примере набора данных я хочу интерполировать значение для Албании 2006 и экстраполировать для Албании 2000-2004 и 2017 гг. Но я хочу убедиться, что значение для Албании 2017 не интерполируется с использованием Албании 2016 и Алжира 2003. Для Алжира 2000-2002 гг. Я хочу, чтобы значения были экстраполированы с использованием данных для Алжира 2003 и 2004 гг. Я попробовал следующий код:

data <- group_by(data, country)
data$broadband <- na.approx(data$broadband, maxgap = Inf, rule = 2)
data <- as.data.frame(data)

и пробовал разные значения для maxgap, но, похоже, ни одно из них не решило мою проблему. Я предполагал, что с помощью функции group_by это будет работать правильно, но это не так. Кто-нибудь знает какие-либо решения?

РЕДАКТИРОВАТЬ: Единственный способ сделать то, что мне нужно, - разделить набор данных на отдельный набор данных для каждой уникальной страны, используя следующий код:

mylist <- split(data, data$country)

alb <- mylist[1]
alb <- as_data_frame(alb)
alg <- mylist[2]
alg <- as_data_frame(alg)
ang <- mylist[3]
ang <- as_data_frame(ang)

и затем используйте функцию na.approx для отдельных наборов данных по одному.

РЕДАКТИРОВАТЬ 2:

Я попробовал решение, предложенное Маркусом ниже, и оно, похоже, не работает. Это результат использования предложенного кода для значений для Анголы:

Country Year    Broadband   Broadband_imp

Algeria 2014    1599692 1599692
Algeria 2015    2269348 2269348
Algeria 2016    2858906 2858906
Angola  2000    NA  2451556.286
Angola  2001    NA  2044206.571
Angola  2002    NA  1636856.857
Angola  2003    NA  1229507.143
Angola  2004    NA  822157.429
Angola  2005    NA  414807.714
Angola  2006    7458    7458
Angola  2007    11700   11700

Как вы можете видеть, вмененные значения для Анголы 2000-2005 гг., По-видимому, были рассчитаны с использованием значений из Алжира, поскольку вмененные значения намного выше, чем они должны быть даны для значения Анголы 2006 года в 7458.

РЕДАКТИРОВАТЬ 3: Это полный код, который я использовал -

data <- read_excel("~/Documents/data.xlsx")

> dput(head(data))
structure(list(continent = c("Europe", "Europe", "Europe", "Europe", 
"Europe", "Europe"), country = c("Albania", "Albania", "Albania", 
"Albania", "Albania", "Albania"), Year = c(2000, 2001, 2002, 
2003, 2004, 2005), `Individuals Using Internet, %, WB` = c(0.114097347, 
0.325798377, 0.390081273, 0.971900415, 2.420387798, 6.043890864
), `Secure Internet Servers, WB` = c(NA, 1, NA, 1, 2, 1), `Mobile Cellular 
Subscriptions, WB` = c(29791, 
392650, 851000, 1100000, 1259590, 1530244), `Fixed Broadband Subscriptions, 
WB` = c(NA, 
NA, NA, NA, NA, 272), `Trade, % GDP, WB` = c(55.9204287230026, 
57.4303612453301, 63.9342407411882, 65.4406219482911, 66.3578254370479, 
70.2953012017195), `Air transport, freight (million ton-km)` = c(0.003, 
0.003, 0.144, 0.088, 0.099, 0.1), `Air Transport, registered carrier 
departures worldwide, WB` = c(3885, 
3974, 3762, 3800, 4104, 4309), `FDI, net, inflows, % GDP, WB` = 
c(3.93717707227928, 
5.10495722596557, 3.04391445388559, 3.09793068135411, 4.66563777108359, 
3.21722676118428), `Number of Airports, WFB` = c(10, 11, 11, 
11, 11, 11), `Currently under EU Arms Sanctions` = c(0, 0, 0, 
0, 0, 0), `Currently under EU Economic Sanctions` = c(0, 0, 0, 
0, 0, 0), `Currently under UN Arms Sanctions` = c(0, 0, 0, 0, 
0, 0), `Currently under UN Economic Sanctions` = c(0, 0, 0, 0, 
0, 0), `Currently under US Arms Embargo` = c(0, 0, 0, 0, 0, 0
), `Currently under US Economic Sanctions` = c(0, 0, 0, 0, 0, 
0)), .Names = c("continent", "country", "Year", "Individuals Using Internet, 
%, WB", 
"Secure Internet Servers, WB", "Mobile Cellular Subscriptions, WB", 
"Fixed Broadband Subscriptions, WB", "Trade, % GDP, WB", "Air transport, 
freight (million ton-km)", 
"Air Transport, registered carrier departures worldwide, WB", 
"FDI, net, inflows, % GDP, WB", "Number of Airports, WFB", "Currently under EU 
 Arms Sanctions", 
"Currently under EU Economic Sanctions", "Currently under UN Arms Sanctions", 
"Currently under UN Economic Sanctions", "Currently under US Arms Embargo", 
"Currently under US Economic Sanctions"), row.names = c(NA, -6L
), class = c("tbl_df", "tbl", "data.frame"))

 data_imputed <- data %>% 
group_by(country) %>% 
mutate(broadband_imp = na.approx(broadband, maxgap=Inf, rule = 2))

1 ответ

Ты можешь использовать group_by а также mutate:

library(tidyverse)
library(zoo)

df_imputed <- df %>% 
group_by(Country) %>% 
mutate(Broadband_imputed = na.approx(Broadband, maxgap = Inf, rule = 2))

Который дает

> head(df_imputed)
# A tibble: 6 x 4
# Groups:   Country [1]
  Country  Year Broadband Broadband_imputed
   <fctr> <int>     <int>             <dbl>
1 Albania  2000        NA               272
2 Albania  2001        NA               272
3 Albania  2002        NA               272
4 Albania  2003        NA               272
5 Albania  2004        NA               272
6 Albania  2005       272               272

а также

> df_imputed %>% filter(Country == 'Algeria')
# A tibble: 5 x 4
# Groups:   Country [1]
  Country  Year Broadband Broadband_imputed
   <fctr> <int>     <int>             <dbl>
1 Algeria  2000        NA             18000
2 Algeria  2001        NA             18000
3 Algeria  2002        NA             18000
4 Algeria  2003     18000             18000
5 Algeria  2004     36000             36000

ДАННЫЕ

df <- read.table(text = "Country Year    Broadband
Albania 2000    NA
Albania 2001    NA
Albania 2002    NA
Albania 2003    NA
Albania 2004    NA
Albania 2005    272
Albania 2006    NA
Albania 2007    10000
Albania 2008    64000
Albania 2009    92000
Albania 2010    105539
Albania 2011    128210
Albania 2012    160088
Albania 2013    182556
Albania 2014    207931
Albania 2015    242870
Albania 2016    263874
Albania 2017    NA
Algeria 2000    NA
Algeria 2001    NA
Algeria 2002    NA
Algeria 2003    18000
Algeria 2004    36000", header = TRUE)
Другие вопросы по тегам