I have a data.frame df
with many groups (series
) where the data area
are presented annually. I'm trying to create a new column where diff
is the difference between area in row 1 and row 2. But I need continue subtracting from the "new" difference. This needs to be done in descending order by year
for each series
.
df<-
structure(list(series = c("A218t23", "A218t23", "A218t23", "A218t23",
"A218t23", "A218t23", "A218t23", "A218t23", "A218t23"), year = 2018:2010,
area = c(16409.3632611811, 274.5866082, 293.8540619, 323.0603775,
544.7366938, 108.0737561, 134.8579038, 143.14125, 167.8244576
)), row.names = c(NA, -9L), groups = structure(list(series = "A218t23",
.rows = structure(list(1:9), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = c(NA, -1L), class = c("tbl_df",
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"))
My desired output would look like this:
Hence, 16409
-275
=16135
then, 16135
-294
=15841
and so on.
The code I've been using:
df_diffs <- df %>%
dplyr::group_by(series) %>%
dplyr::mutate(diff = area - dplyr::lag(area, default=0, order_by = desc(year)))
However, this just returns the lagged difference between rows in the area
column. The result I'm looking for is a "cumulative" or running difference. I've checked out RcppRoll
and some other SO posts, but no luck. Ideally, I could keep this all within a piping framework since I have other functions going on. Bonus points if there's a way to replace the NA in the first row with the corresponding area value for that year.
Suggestions very much appreciated!
Another option, using Reduce()
df %>%
group_by(series) %>%
mutate(diff = Reduce("-", area, accumulate = T))
# A tibble: 9 × 4
# Groups: series [1]
series year area diff
<chr> <int> <dbl> <dbl>
1 A218t23 2018 16409. 16409.
2 A218t23 2017 275. 16135.
3 A218t23 2016 294. 15841.
4 A218t23 2015 323. 15518.
5 A218t23 2014 545. 14973.
6 A218t23 2013 108. 14865.
7 A218t23 2012 135. 14730.
8 A218t23 2011 143. 14587.
9 A218t23 2010 168. 14419.