Рассчитать относительное изменение времени по группам - PullRequest
5 голосов
/ 23 июня 2019

Я изо всех сил пытаюсь вычислить процентную разницу между годовой чистой продажей компании с учетом NA.

Вот пример данных:

dt <- data.table(lpermno = c(10065, 10065, 10065, 10065, 59328, 61241, 59328, 61241, 59328, 61241, 59328, 61241), fyear = c(2001, 2002, 2003, 2004, 2001, 2001, 2002, 2002, 2003, 2003, 2004, 2004), sale = c(NA, NA, NA, NA, 26539, 3891.754, 26764, 2697.029, 30141, 3519.168, 34209, 5001.435))

lpermno fyear sale
10065   2001    NA
10065   2002    NA
10065   2003    NA
10065   2004    NA
59328   2001    26539.000
59328   2002    26764.000
59328   2003    30141.000
59328   2004    34209.000
61241   2001    3891.754
61241   2002    2697.029
61241   2003    3519.168
61241   2004    5001.435

Я бы хотел вычислить новую переменную с именем sales_change. Эта переменная должна быть процентным изменением для продажи. [sale_n]/[sale_n-1] for each company. Для первого наблюдения за компанией sales_change должен быть всего 1.

Я прочитал следующие посты для руководства, но это не сработало.

  1. Рассчитать первую разницу по группам в R
    • Рассчитать разницу, а не процентное изменение
  2. Рассчитать разницу между значениями по группам и сопоставить по времени
    • Получите только na в качестве вывода после корректировки кода
  3. R: как найти процент различий между столбцами и соответственно присвоить имена?
    • Этот код возвращает новые столбцы для разных периодов продаж, так как я работаю много лет, это не является предпочтительным
  4. Рассчитать процентное изменение во фрейме данных R
  5. Как рассчитать процентное изменение из разных строк по разным пролетам
  6. Рассчитать относительные изменения во временном ряду относительно базовой линии по группе. NA, если базовое значение не было измерено
    • Работает с базовой линией, и это не то, что я ищу
  7. Скользящее среднее (скользящее среднее) по группе / идентификатору с dplyr
    • Выглядит как элегантное решение для вычисления среднего значения, однако я ищу процентное изменение.

Для приведенных выше примеров данных желаемый результат будет:

output <- data.table(lpermno = c(10065, 10065, 10065, 10065, 59328, 59328, 59328, 59328, 61241, 61241, 61241, 61241), fyear = c(2001, 2002, 2003, 2004, 2001, 2002, 2003, 2004, 2001, 2002, 2003, 2004), sale = c(NA, NA, NA, NA, 3891.754, 2697.029, 3519.168, 5001.435, 26539, 26764, 30141, 34209), output = c(NA, NA, NA, NA, 1, 0.693011, 1.304831, 1.421198, 1, 1.008478, 1.126177, 1.134966))

lpermno fyear sale output
10065   2001    NA  NA
10065   2002    NA  NA
10065   2003    NA  NA
10065   2004    NA  NA
59328   2001    3891.754    1.000000
59328   2002    2697.029    0.693011
59328   2003    3519.168    1.304831
59328   2004    5001.435    1.421198
61241   2001    26539.000   1.000000
61241   2002    26764.000   1.008478
61241   2003    30141.000   1.126177
61241   2004    34209.000   1.134966

Буду признателен за помощь. Заранее спасибо.

Ответы [ 2 ]

6 голосов
/ 23 июня 2019

Используя data.table, вы можете сделать следующее:

dt[, pctchnge := sale / c(sale[1], head(sale, -1)), by="lpermno"][order(lpermno)]

Здесь создайте новую переменную с :=, повторите первый месяц продаж и отбросьте последний месяц с хвостом длязнаменатель.Выполнять расчеты по lpermno.Затем сортируйте по lpermno.

это возвращает

    lpermno fyear      sale  pctchnge
 1:   10065  2001        NA        NA
 2:   10065  2002        NA        NA
 3:   10065  2003        NA        NA
 4:   10065  2004        NA        NA
 5:   59328  2001 26539.000 1.0000000
 6:   59328  2002 26764.000 1.0084781
 7:   59328  2003 30141.000 1.1261770
 8:   59328  2004 34209.000 1.1349657
 9:   61241  2001  3891.754 1.0000000
10:   61241  2002  2697.029 0.6930112
11:   61241  2003  3519.168 1.3048314
12:   61241  2004  5001.435 1.4211981
3 голосов
/ 23 июня 2019

Вы можете использовать by, который применяет функцию к вашему фрейму данных, разделенную на lpermno.

При разбиении формула относительного изменения применяется к столбцу sales каждого фрейма данных, которые объединяются на cbind с новым столбцом outputif мы контролируем для anyNA случаев и выбрасываем NA, поскольку значимое среднее не может быть вычислено.С помощью do.call(rbind) мы объединяем фрейм данных.

do.call(rbind, by(dt, dt$lpermno, function(x)
  if (anyNA(x$sale)) return(cbind(x, output=NA))
  else return (cbind(x, output=c(1, 1/x$sale[-length(x$sale)]*c(x$sale[-1]))))))
#     lpermno fyear      sale    output
#  1:   10065  2001        NA        NA
#  2:   10065  2002        NA        NA
#  3:   10065  2003        NA        NA
#  4:   10065  2004        NA        NA
#  5:   59328  2001 26539.000 1.0000000
#  6:   59328  2002 26764.000 1.0084781
#  7:   59328  2003 30141.000 1.1261770
#  8:   59328  2004 34209.000 1.1349657
#  9:   61241  2001  3891.754 1.0000000
# 10:   61241  2002  2697.029 0.6930112
# 11:   61241  2003  3519.168 1.3048314
# 12:   61241  2004  5001.435 1.4211981

Данные

dt <- structure(list(lpermno = c(10065, 10065, 10065, 10065, 59328, 
61241, 59328, 61241, 59328, 61241, 59328, 61241), fyear = c(2001, 
2002, 2003, 2004, 2001, 2001, 2002, 2002, 2003, 2003, 2004, 2004
), sale = c(NA, NA, NA, NA, 26539, 3891.754, 26764, 2697.029, 
30141, 3519.168, 34209, 5001.435)), row.names = c(NA, -12L), class = c("data.table", 
"data.frame"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...