#r
#r
Вопрос:
У меня есть следующий фрейм данных:
a = data.frame("ID"=c(1,1,1,1,1,1,5,5,5,5),
"Year"=c(2016,2017,2016,2017,2016,2017,2017,2017,2016,2017),
"Quarter"=c(1,1,2,2,3,3,1,2,3,3),
"Revenue" = c(100,300,200,600,500,700,200,300,800,900))
ID Year Quarter Revenue
1 1 2016 1 100
2 1 2017 1 300
3 1 2016 2 200
4 1 2017 2 600
5 1 2016 3 500
6 1 2017 3 700
7 5 2017 1 200
8 5 2017 2 300
9 5 2016 3 800
10 5 2017 3 900
Я хочу вычесть доходы предыдущих кварталов за каждый квартал для каждого идентификатора. Доход за 2 квартала вычитается из дохода за 1 квартал, доход за 3 квартала вычитается из суммы 1 и 2 кварталов и т. Д.. Так что это будет означать, например, для ID = 1, year = 2016:
2016 Q1 = 100, 2016 Q2 = 100 (200-100), 2016 Q3 = 300 (500-100-100).
Есть также некоторые идентификаторы, у которых нет данных за некоторые кварталы, например ID = 5, year = 2016, у которого есть данные только за 3. квартал, поэтому можно вычесть воображаемые 0, и мы получим 2016 Q3 = 800 (800-0-0).
Желаемый результат должен выглядеть следующим образом:
ID Year Quarter Revenue
1 1 2016 1 100
2 1 2017 1 300
3 1 2016 2 100
4 1 2017 2 300
5 1 2016 3 300
6 1 2017 3 100
7 5 2017 1 200
8 5 2017 2 100
9 5 2016 3 800
10 5 2017 3 600
Есть ли простой способ сделать это или мне нужно написать функцию для этого?
Ответ №1:
library(tidyverse)
a %>%
left_join(mutate(a, Quarter = Quarter 1),
by= c("ID", "Year", "Quarter"))%>%
mutate(Revenue = Revenue.x - coalesce(Revenue.y,0)) %>%
select(-contains("."))
ID Year Quarter Revenue
1 1 2016 1 100
2 1 2017 1 300
3 1 2016 2 100
4 1 2017 2 300
5 1 2016 3 300
6 1 2017 3 100
7 5 2017 1 200
8 5 2017 2 100
9 5 2016 3 800
10 5 2017 3 600
Комментарии:
1. Я попытался с помощью %>% упорядочить (идентификатор, год, квартал) %>% group_by(идентификатор, год) %>% мутировать(Доход = case_when(row_number() == 1 ~ Доход, row_number() == 2 ~ Доход [2] — Доход [1], TRUE~ Доход [3] — Доход [2] — Доход [1])) Раньше я использовал этот подход с векторным индексом, но здесь он не работает, по умолчанию не группируется по значениям упорядочивания. Просто чтобы убедиться, я даже добавил функцию упорядочивания, но она все равно не работает. Можете ли вы, пожалуйста, помочь мне понять, почему.
2. @KarthikS Во-первых,
case_when
в этом случае вы не можете. Во-вторых,arrange
это никоим образом не помогает. Вероятно, вы думаетеgroup_by
. Наконец, что вы пытаетесь сделать? Я не понимаю, что вы делаете3. Что я пытаюсь сделать, так это то, что если мы упорядочим фрейм данных, используя %>% arrange(ID, год, квартал), у нас будет доход за каждый год с 1 по 3 кварталы. С помощью, case_whenкогда я попытался сделать вычитание первого квартала из второго, а первого и второго кварталов из третьего на основе номеров строк. Не могли бы вы сообщить мне, почему case_when не будет работать в таких случаях.
4. @KarthikS Не удовлетворяет ли решение, которое я предоставил выше? Обратите внимание, что у вас могут быть данные для кварталов 3 и 1 без квартала 2. согласно договоренности, вы вычтете 3 и 1, но вы не должны этого делать. Просто попытайтесь понять предоставленное решение.
Ответ №2:
Вы можете использовать purrr
accumulate
функцию ‘s для выполнения такого рекурсивного вычисления.
library(dplyr)
a %>%
group_by(ID, Year) %>%
mutate(Revenue = Revenue - cumsum(purrr::accumulate(lag(Revenue)[-1],
~.y - .x, .init = 0)))
# ID Year Quarter Revenue
# <dbl> <dbl> <dbl> <dbl>
# 1 1 2016 1 100
# 2 1 2017 1 300
# 3 1 2016 2 100
# 4 1 2017 2 300
# 5 1 2016 3 300
# 6 1 2017 3 100
# 7 5 2017 1 200
# 8 5 2017 2 100
# 9 5 2016 3 800
#10 5 2017 3 600
Ответ №3:
Вы можете сделать это в data.table
.
library(data.table)
setDT(a)
a[,Revenue:= Revenue-shift(Revenue,type = 'lag',fill = 0), by= c('ID','Year')]