Reputation:
I have this dataframe with 5 column where stock is the current_stock. And i want a new column stock_over_time which is then calculated as stock_over_time = stock - sales + purchase.
df=tibble(article=rep("article one",5),
week=c(1,2,3,4,5),
sales=10,
purchase=c(5,0,5,5,0),
stock=c(50))
# A tibble: 5 x 5
article week sales purchase stock
<chr> <dbl> <dbl> <dbl> <dbl>
1 article one 1 10 5 50
2 article one 2 10 0 50
3 article one 3 10 5 50
4 article one 4 10 5 50
5 article one 5 10 0 50
My final dataframe should look like this:
# A tibble: 5 x 5
article week sales purchase stock stock_over_time
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 article one 1 10 5 50 NA
2 article one 2 10 0 50 45
3 article one 3 10 5 50 35
4 article one 4 10 5 50 30
5 article one 5 10 0 50 25
...where stock_over_time is calculated as:
50 - 10 + 5 = 45
45 - 10 + 0 = 35
35 - 10 + 5 = 30
30 - 10 + 5 = 25
How would i do this?
Upvotes: 3
Views: 2598
Reputation: 3
What about the following approach?
df$stock_over_time <- df$stock - df$sales + df$purchase
In case there are any NAs inside the dfs columns that are needed for the calculation, I would perform this before:
df[is.na(df)] <- 0
Upvotes: 0
Reputation: 887223
We can use recursive way to do this and it should also work with complex cases
df$stock_over_time <- df$stock
for(i in 2:nrow(df)) {
df$stock_over_time[i] <- df$stock_over_time[i-1] -
df$sales[i-1] + df$purchase[i-1]
}
df
# A tibble: 5 x 6
# article week sales purchase stock stock_over_time
# <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 article one 1 10 5 50 50
#2 article one 2 10 0 50 45
#3 article one 3 10 5 50 35
#4 article one 4 10 5 50 30
#5 article one 5 10 0 50 25
Or another option is accumulate
from purrr
library(purrr)
library(dplyr)
df %>%
mutate(stock_over_time = accumulate((purchase- sales)[-1],
~ .x + .y, .init = first(stock)))
# A tibble: 5 x 6
# article week sales purchase stock stock_over_time
# <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 article one 1 10 5 50 50
#2 article one 2 10 0 50 40
#3 article one 3 10 5 50 35
#4 article one 4 10 5 50 30
#5 article one 5 10 0 50 20
Or it can be written as
df %>%
mutate(stock_over_time = accumulate(c(first(stock),
(purchase- sales)[-1]), ~ .x + .y))
Upvotes: 1
Reputation: 34511
You can use cumsum()
:
library(dplyr)
df %>%
mutate(stock_over_time = lag(stock + cumsum(purchase - sales)))
# A tibble: 5 x 6
article week sales purchase stock stock_over_time
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 article one 1 10 5 50 NA
2 article one 2 10 0 50 45
3 article one 3 10 5 50 35
4 article one 4 10 5 50 30
5 article one 5 10 0 50 25
Upvotes: 2