'Calculate Stock
Is it possible calculated stock using R? The formula is stock+purchase-sold. In this case first stock (row1) is 0, rg first result stockB1= 12 - 3 = 9 the second (row1) 9+0-5=4.
df=read.table(text="
AB1 XB1 AB2 XB2 AB3 XB3
12 3 0 5 3 7
11 35 1 7 2 8
0 10 5 16 5 3",h=T)
stock = read.table(text="
AB1 XB1 STB1 AB2 XB2 STB2 AB3 XB3 STB3
12 3 9 5 3 11 3 7 7
11 35 24 1 7 18 2 8 12
11 10 1 5 16 -10 5 3 -2",h=T)
Where STB is my request, I not need the total but the partial for each. It can be also in another dataframe.
Solution 1:[1]
I'm not sure what form of output you're looking for, but here's an approach that assumes each PB column is a purchase and each SB column is a sale.
My first step is to track the original row for later. Then I reshape the data long, splitting the column into two components after the 2nd character, the first component being PB/SB, the second component being the number of trade. I count PB as increases and SB as reductions, and take the cumulative total for each transaction.
library(tidyverse)
df %>%
mutate(row = row_number()) %>%
pivot_longer(-row, names_to = c("type", "num"), names_sep = 2) %>%
mutate(net = value * if_else(type == "SB", -1, 1)) %>%
group_by(row) %>%
mutate(cuml = cumsum(net)) %>%
ungroup()
## A tibble: 18 × 6
# row type num value net cuml
# <int> <chr> <chr> <int> <dbl> <dbl>
# 1 1 PB 1 12 12 12
# 2 1 SB 1 3 -3 9
# 3 1 PB 2 0 0 9
# 4 1 SB 2 5 -5 4
# 5 1 PB 3 3 3 7
# 6 1 SB 3 7 -7 0
# 7 2 PB 1 11 11 11
# 8 2 SB 1 35 -35 -24
# 9 2 PB 2 1 1 -23
#10 2 SB 2 7 -7 -30
#11 2 PB 3 2 2 -28
#12 2 SB 3 8 -8 -36
#13 3 PB 1 11 11 11
#14 3 SB 1 10 -10 1
#15 3 PB 2 5 5 6
#16 3 SB 2 16 -16 -10
#17 3 PB 3 5 5 -5
#18 3 SB 3 3 -3 -8
This is almost certainly not the final format you want, but we could use this to create a few outputs.
For instance, we might add
... %>%
select(row, num, cuml) %>%
pivot_wider(names_from = num, names_prefix = "trades_", values_from = cuml)
to get something like the original, but just showing the total stock after each pair of trades:
# A tibble: 3 × 4
row trades_1 trades_2 trades_3
<int> <dbl> <dbl> <dbl>
1 1 9 4 0
2 2 -24 -30 -36
3 3 1 -10 -8
Solution 2:[2]
library(tidyverse)
df=read.table(text="
PB1 SB1 PB2 SB2 PB3 SB3
12 3 0 5 3 7
11 35 1 7 2 8
11 10 5 16 5 3",h=T)
df %>%
rowwise() %>%
mutate(total = sum(c_across(everything())*c(1,-1)))
#> # A tibble: 3 × 7
#> # Rowwise:
#> PB1 SB1 PB2 SB2 PB3 SB3 total
#> <int> <int> <int> <int> <int> <int> <dbl>
#> 1 12 3 0 5 3 7 0
#> 2 11 35 1 7 2 8 -36
#> 3 11 10 5 16 5 3 -8
Edit 1:
The following pipeline might be what you are looking for:
library(tidyverse)
df=read.table(text="
PB1 SB1 PB2 SB2 PB3 SB3
12 3 0 5 3 7
11 35 1 7 2 8
11 10 5 16 5 3",h=T)
df %>%
as_tibble() %>%
mutate(stock = row_number()) %>%
pivot_longer(
cols = -stock,
names_to = c("type", "tr_num"),
names_pattern = "([P|S]B)([0-9]*)"
) %>%
group_by(stock) %>%
mutate(csum = cumsum(if_else(type == "PB", as.double(value), -1 * value))) %>%
group_by(stock, tr_num) %>%
group_modify(~ add_row(.x, type = "ST")) %>%
mutate(value = if_else(type == "ST", lag(csum), as.double(value))) %>%
ungroup() %>%
select(-csum) %>%
unite("header", c(type, tr_num), sep = "") %>%
pivot_wider(names_from = header, values_from = value) %>%
select(-stock)
#> # A tibble: 3 × 9
#> PB1 SB1 ST1 PB2 SB2 ST2 PB3 SB3 ST3
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 12 3 9 0 5 4 3 7 0
#> 2 11 35 -24 1 7 -30 2 8 -36
#> 3 11 10 1 5 16 -10 5 3 -8
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Jon Spring |
Solution 2 |