Существует ли более быстрый способ обработки суммы более чем на один уровень фактора в R? - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть фрейм данных, состоящий из четырех столбцов: состояние A; состояние B; импорт государства B из государства A; и год. Имеет 594473 строки.

Для каждого государства B необходимо рассчитать общий объем импорта B со всеми возможными партнерами в данном году и за 4 года до этого.

Для этого я создал следующий цикл for, где «j» - страна B в данной строке, year - год этой строки, а z [, 5] - импорт страны b из a on в тот год:

# create column for 5 year total imports of b



for (row in 1:nrow(z)){
  j   <-z[row,3]
  year<-as.numeric(paste(z[row,1]))
  z[row,6]<- sum(z[z[,3]==j & z[,1]==year,5])+  
    sum(z[z[,3]==j & z[,1]==year-1,5])+
    sum(z[z[,3]==j & z[,1]==year-2,5])+
    sum(z[z[,3]==j & z[,1]==year-3,5])+
    sum(z[z[,3]==j & z[,1]==year-4,5])
}

colnames(z)[6]<-"5year_imp_b

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

Извините, если это не очень хороший вопрос, я новичок в R и программировании в целом.

Большое спасибо!

1 Ответ

0 голосов
/ 01 ноября 2018

Вот функция, которая должна быть относительно быстрой (вам нужно будет импортировать data.table, чтобы она работала):

calculate_rolling_sum <- function(df, date_col, calc_col, id_var, k) {

  return(setDT(df)[order(get(date_col)),][, paste(calc_col, "roll_sum", k, sep = "_") := sapply(get(date_col), function(x) sum(get(calc_col)[between(get(date_col), x - k, x)])),
                                                                 by = mget(id_var)])

}

Пример кадра данных:

df <- data.frame(
  state_A = c(rep("x", 6), rep("y", 4), rep("z", 6)),
  state_B = c(rep("d", 16)),
  imports_AB = c(rep(3, 3), rep(4, 4), rep(5, 2), rep(6, 2), rep(9, 3), rep(3, 2)),
  yr = c(seq(2000, 2006, 1), seq(2009, 2017, 1))
)

    state_A state_B imports_AB   yr
 1:       x       d          3 2000
 2:       x       d          3 2001
 3:       x       d          3 2002
 4:       x       d          4 2003
 5:       x       d          4 2004
 6:       x       d          4 2005
 7:       y       d          4 2006
 8:       y       d          5 2009
 9:       y       d          5 2010
10:       y       d          6 2011
11:       z       d          6 2012
12:       z       d          9 2013
13:       z       d          9 2014
14:       z       d          9 2015
15:       z       d          3 2016
16:       z       d          3 2017

Применение функции для текущего и последних 3 лет и нового кадра данных:

library(data.table)

df_rolling <- calculate_rolling_sum(df, date_col = "yr", calc_col = "imports_AB", id_var = c("state_A", "state_B"), k = 3)

df_rolling[]

    state_A state_B imports_AB   yr imports_AB_roll_sum_3
 1:       x       d          3 2000                     3
 2:       x       d          3 2001                     6
 3:       x       d          3 2002                     9
 4:       x       d          4 2003                    13
 5:       x       d          4 2004                    14
 6:       x       d          4 2005                    15
 7:       y       d          4 2006                     4
 8:       y       d          5 2009                     9
 9:       y       d          5 2010                    10
10:       y       d          6 2011                    16
11:       z       d          6 2012                     6
12:       z       d          9 2013                    15
13:       z       d          9 2014                    24
14:       z       d          9 2015                    33
15:       z       d          3 2016                    30
16:       z       d          3 2017                    24

В чем преимущество этой функции перед стандартными функциями прокатки? Например, в 2010 году он больше не будет учитывать 2006 год, поскольку это не является обязательным требованием.

Обычные функции прокрутки, которые рассчитывают только по индексам строк, будут считать его (так как это на 2 строки ниже).

Таким образом, вам не нужно заботиться о том, есть ли у вас разрыв между годами, и нет необходимости заполнять набор данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...