Интерполирование NA по группам с использованием dplyr на нескольких столбцах

Если входные номера всегда содержат 7 или 8 цифр, вы также можете использовать

$str = ($input < 10000000) ? 0 . $input : $input;

Я провел несколько тестов и понял, что это будет удвоено так же быстро, как str_pad или sprintf. Если вход может иметь любую длину, вы также можете использовать

$str = substr('00000000' . $input, -8);

. Это не так быстро, как у другого, но также должно быть немного быстрее, чем str_pad и sprintf.

Btw: Мой тест также сказал, что sprintf немного быстрее, чем str_pad. Я сделал все тесты с PHP 5.6.

1
задан Alexander91 13 July 2018 в 18:47
поделиться

4 ответа

Вы можете переписать свой код с помощью mutate_at, чтобы преобразование можно было сделать за один раз, как:

library(dplyr)
library(zoo)


df %>% 
  group_by(iso) %>%
  mutate_at(vars(starts_with("var")), 
            funs(na.locf(na.locf(na.approx(., na.rm = FALSE, rule = 1),na.rm=FALSE),
                                                              fromLast=TRUE)))


# # A tibble: 6 x 5
# # Groups: iso [2]
# iso    year  var1   var2  var3
# <chr> <int> <dbl>  <dbl> <dbl>
# 1 XXX    2005   165  29.0   2151
# 2 XXX    2006   160  21.0   2139
# 3 XXX    2007   172  15.0   2890
# 4 XXX    2008   184   9.00  3640
# 5 XXX    2009   184   9.00  3640
# 6 YYY    2005   206 461     8049
# 

Данные:

df <- read.table(text=
"iso year var1 var2 var3
1 XXX 2005  165   29 2151
2 XXX 2006  160   21 2139
3 XXX 2007   NA   NA   NA
4 XXX 2008  184    9 3640
5 XXX 2009   NA   NA   NA
6 YYY 2005  206  461 8049",
header = TRUE, stringsAsFactors = FALSE)
1
ответ дан MKR 17 August 2018 в 12:14
поделиться
  • 1
    – Moody_Mudskipper 13 July 2018 в 21:18
  • 2
    @Moody_Mudskipper Нет проблемы. Собственно, это дает мне возможность исправить mutate_at :-) – MKR 13 July 2018 в 21:27
  • 3
    @Moody_Mudskipper Кстати, у вас есть хороший ответ. – MKR 13 July 2018 в 21:28
  • 4
    Прошу прощения, если я не был ясен, но мои фактические имена столбцов не являются var1, var2 и т. Д., Поэтому я не могу ссылаться на них, как вы предлагали. Использование ссылки @www var и вложенность функций заставили ее работать. Благодаря! – Alexander91 13 July 2018 в 21:55

Используйте na.approx с method = "constant" (так же, как na.locf) и rule = 2 (это означает, что ближайшее приближение к ведущим и конечным NA). Если вы хотите, чтобы NAs были линейно интерполированы, удалите аргумент method="constant".

df1 %>%
  group_by(iso) %>%
  mutate_at(vars(-iso), funs(na.approx(., method = "constant", rule = 2))) %>%
  ungroup

, давая:

# A tibble: 6 x 5
  iso    year  var1  var2  var3
  <fct> <dbl> <dbl> <dbl> <dbl>
1 XXX    2005   165    29  2151
2 XXX    2006   160    21  2139
3 XXX    2007   160    21  2139
4 XXX    2008   184     9  3640
5 XXX    2009   184     9  3640
6 YYY    2005   206   461  8049

Примечание

df1 в воспроизводимой форме:

df1 <- 
structure(list(iso = structure(c(1L, 1L, 1L, 1L, 1L, 2L), .Label = c("XXX", 
"YYY"), class = "factor"), year = c(2005L, 2006L, 2007L, 2008L, 
2009L, 2005L), var1 = c(165L, 160L, NA, 184L, NA, 206L), var2 = c(29L, 
21L, NA, 9L, NA, 461L), var3 = c(2151L, 2139L, NA, 3640L, NA, 
8049L)), class = "data.frame", row.names = c("1", "2", "3", "4", 
"5", "6"))
2
ответ дан G. Grothendieck 17 August 2018 в 12:14
поделиться
  • 1
    Поэтому, если я правильно понимаю, это интерполирует данные за 2007 год для XXX в среднем за 2006 и 2008 годы, но применяет данные за 2008 год к 2009 году? – Alexander91 14 July 2018 в 15:56
  • 2
    Нет. Как объяснялось в ответе wth method="constant", оно работает как na.locf. Он заполняет НС самым последним предыдущим не-NA, как na.locf, но также он заполняет ведущие NA с первым не-NA. Я добавил результат в ответ. Посмотрите на ?na.approx, а для аргументов method и rule смотрите ?approx. – G. Grothendieck 14 July 2018 в 16:26
  • 3
    – Alexander91 14 July 2018 в 16:31
  • 4
    В вопросе используется na.locf, предполагая, что эта функция была тем, что вы хотели использовать. но если вы хотите, чтобы линейная интерполяция окружающих точек удаляла аргумент method = "constant", по умолчанию для na.approx используется линейная интерполяция. – G. Grothendieck 14 July 2018 в 16:34

Вот базовое решение:

ave(df,df$iso, FUN =function(y){
  if(nrow(y) > 1) y[3:5] <- lapply(y[3:5], function(x) approx(y$year,x,y$year,rule=2)$y)
  y
})

#   iso year var1 var2   var3
# 1 XXX 2005  165   29 2151.0
# 2 XXX 2006  160   21 2139.0
# 3 XXX 2007  172   15 2889.5
# 4 XXX 2008  184    9 3640.0
# 5 XXX 2009  184    9 3640.0
# 6 YYY 2005  206  461 8049.0
2
ответ дан Moody_Mudskipper 17 August 2018 в 12:14
поделиться

Мы можем использовать mutate_at. Ключ должен указать правильные столбцы в аргументе vars, который использует то же правило, что и функция select. Поэтому в этом случае vars(starts_with("var")) также будет работать.

library(dplyr)
library(zoo)

df1 %>% 
  group_by(iso) %>%
  mutate_at(vars(-iso, -year), funs(na.approx(., na.rm = FALSE, rule = 1))) %>%
  mutate_at(vars(-iso, -year), funs(na.locf(., na.rm = FALSE))) %>%
  mutate_at(vars(-iso, -year), funs(na.locf(., na.rm = FALSE, fromLast = TRUE)))
# # A tibble: 6 x 5
# # Groups:   iso [2]
#   iso    year  var1  var2  var3
#   <chr> <int> <dbl> <dbl> <dbl>
# 1 XXX    2005   165    29 2151 
# 2 XXX    2006   160    21 2139 
# 3 XXX    2007   172    15 2890.
# 4 XXX    2008   184     9 3640 
# 5 XXX    2009   184     9 3640 
# 6 YYY    2005   206   461 8049 

DATA

df1 <- read.table(text = "  iso year var1 var2 var3
1 XXX 2005  165   29 2151
2 XXX 2006  160   21 2139
3 XXX 2007   NA   NA   NA
4 XXX 2008  184    9 3640
5 XXX 2009   NA   NA   NA
6 YYY 2005  206  461 8049 ",
                 header = TRUE, stringsAsFactors = FALSE)
1
ответ дан www 17 August 2018 в 12:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: