计算具有条件的两个特定行之间的行
counting rows between two specific rows with a condition
df <- structure(list(inv = c("INV_1", "INV_1", "INV_1", "INV_1", "INV_1"), ass = c("x", "x", "x", "x", "x"), datetime = c("2010-01-01",
"2010-01-02", "2010-01-03", "2010-01-08", "2010-01-19"), portfolio = c(10,
0, 5, 2, 0)), operation = c(10, -10, 5, -3, -2), class = "data.frame", row.names = c(NA, -5L))
所以我有 4000
个拥有 6000
不同资产的投资者,对于每个投资者,我有两个不同变量的交易操作:操作告诉我他是否 buying/selling;投资组合告诉我他在投资组合中有多少。
我想做的是计算一个头寸在投资组合中保持开放的天数,所以我想计算投资组合回到零的那一天和投资组合去的那一天之间的差异正面(不可能获得负面投资组合)。
所以在上面的数据集中我会算 row2 - row1 ==> 2010-01-02 - 2010-01-01
和 row 5 - row 3 ==> 2010-01-19 - 2010-01-03
等等...
我想对数据集中所有我发现 portfolio > 0
.
的所有行的所有投资者和资产进行此计算
所以我的数据集将有一个名为 duration
的列,在这种情况下,它等于 c(0,1,0,5,16)
(所以我当然还必须计算 raw1 - raw1
和 raw3 - raw3
)
因此我的问题是每次 portfolio
回到零时重新开始计数。
library(dplyr)
df %>%
mutate(datetime = as.Date(datetime, "%Y-%m-%d")) %>%
group_by(investor, asset) %>%
arrange(datetime) %>%
mutate(grp.pos = cumsum(lag(portfolio, default = 1) == 0)) %>%
group_by(investor, asset, grp.pos) %>%
mutate(`Open (#days)` = datetime - datetime[1])
#> # A tibble: 5 x 6
#> # Groups: investor, asset, grp.pos [2]
#> investor asset datetime portfolio grp.pos `Open (#days)`
#> <chr> <chr> <date> <dbl> <int> <drtn>
#> 1 INV_1 x 2010-01-01 10 0 0 days
#> 2 INV_1 x 2010-01-02 0 0 1 days
#> 3 INV_1 x 2010-01-03 5 1 0 days
#> 4 INV_1 x 2010-01-08 2 1 5 days
#> 5 INV_1 x 2010-01-19 0 1 16 days
数据:
df <- structure(list(investor = c("INV_1", "INV_1", "INV_1", "INV_1", "INV_1"),
asset = c("x", "x", "x", "x", "x"),
datetime = c("2010-01-01", "2010-01-02", "2010-01-03",
"2010-01-08", "2010-01-19"),
portfolio = c(10, 0, 5, 2, 0)),
operation = c(10, -10, 5, -3, -2),
class = "data.frame", row.names = c(NA, -5L))
这是我们可以做到的方法,如果需要,可以扩展 ass
首先我们按 inv
分组以用于原始数据集。然后将datetime
转换为日期格式,方便计算(这里使用ymd()
函数)。
下一步可以用不同的方式完成:
主要思想是将组的最后一行 0 指示的列 portfolio
分组。为此,我们以降序形式排列 datetime
,以便轻松应用分组 ID 和 cumsum == 0
.
重新排列后 datetime
我们可以按预期从第一个开始计算最后一个:
library(dplyr)
library(lubridate)
df %>%
group_by(inv) %>%
mutate(datetime = ymd(datetime)) %>%
arrange(desc(datetime)) %>%
group_by(position_Group = cumsum(portfolio==0)) %>%
arrange(datetime) %>%
mutate(position_open = last(datetime)-first(datetime)) %>%
ungroup()
inv ass datetime portfolio operation id_Group position_open
<chr> <chr> <date> <dbl> <dbl> <int> <drtn>
1 INV_1 x 2010-01-01 10 10 2 1 days
2 INV_1 x 2010-01-02 0 -10 2 1 days
3 INV_1 x 2010-01-03 5 5 1 16 days
4 INV_1 x 2010-01-08 2 -3 1 16 days
5 INV_1 x 2010-01-19 0 -2 1 16 days
df <- structure(list(inv = c("INV_1", "INV_1", "INV_1", "INV_1", "INV_1"), ass = c("x", "x", "x", "x", "x"), datetime = c("2010-01-01",
"2010-01-02", "2010-01-03", "2010-01-08", "2010-01-19"), portfolio = c(10,
0, 5, 2, 0)), operation = c(10, -10, 5, -3, -2), class = "data.frame", row.names = c(NA, -5L))
所以我有 4000
个拥有 6000
不同资产的投资者,对于每个投资者,我有两个不同变量的交易操作:操作告诉我他是否 buying/selling;投资组合告诉我他在投资组合中有多少。
我想做的是计算一个头寸在投资组合中保持开放的天数,所以我想计算投资组合回到零的那一天和投资组合去的那一天之间的差异正面(不可能获得负面投资组合)。
所以在上面的数据集中我会算 row2 - row1 ==> 2010-01-02 - 2010-01-01
和 row 5 - row 3 ==> 2010-01-19 - 2010-01-03
等等...
我想对数据集中所有我发现 portfolio > 0
.
所以我的数据集将有一个名为 duration
的列,在这种情况下,它等于 c(0,1,0,5,16)
(所以我当然还必须计算 raw1 - raw1
和 raw3 - raw3
)
因此我的问题是每次 portfolio
回到零时重新开始计数。
library(dplyr)
df %>%
mutate(datetime = as.Date(datetime, "%Y-%m-%d")) %>%
group_by(investor, asset) %>%
arrange(datetime) %>%
mutate(grp.pos = cumsum(lag(portfolio, default = 1) == 0)) %>%
group_by(investor, asset, grp.pos) %>%
mutate(`Open (#days)` = datetime - datetime[1])
#> # A tibble: 5 x 6
#> # Groups: investor, asset, grp.pos [2]
#> investor asset datetime portfolio grp.pos `Open (#days)`
#> <chr> <chr> <date> <dbl> <int> <drtn>
#> 1 INV_1 x 2010-01-01 10 0 0 days
#> 2 INV_1 x 2010-01-02 0 0 1 days
#> 3 INV_1 x 2010-01-03 5 1 0 days
#> 4 INV_1 x 2010-01-08 2 1 5 days
#> 5 INV_1 x 2010-01-19 0 1 16 days
数据:
df <- structure(list(investor = c("INV_1", "INV_1", "INV_1", "INV_1", "INV_1"),
asset = c("x", "x", "x", "x", "x"),
datetime = c("2010-01-01", "2010-01-02", "2010-01-03",
"2010-01-08", "2010-01-19"),
portfolio = c(10, 0, 5, 2, 0)),
operation = c(10, -10, 5, -3, -2),
class = "data.frame", row.names = c(NA, -5L))
这是我们可以做到的方法,如果需要,可以扩展 ass
首先我们按 inv
分组以用于原始数据集。然后将datetime
转换为日期格式,方便计算(这里使用ymd()
函数)。
下一步可以用不同的方式完成:
主要思想是将组的最后一行 0 指示的列 portfolio
分组。为此,我们以降序形式排列 datetime
,以便轻松应用分组 ID 和 cumsum == 0
.
重新排列后 datetime
我们可以按预期从第一个开始计算最后一个:
library(dplyr)
library(lubridate)
df %>%
group_by(inv) %>%
mutate(datetime = ymd(datetime)) %>%
arrange(desc(datetime)) %>%
group_by(position_Group = cumsum(portfolio==0)) %>%
arrange(datetime) %>%
mutate(position_open = last(datetime)-first(datetime)) %>%
ungroup()
inv ass datetime portfolio operation id_Group position_open
<chr> <chr> <date> <dbl> <dbl> <int> <drtn>
1 INV_1 x 2010-01-01 10 10 2 1 days
2 INV_1 x 2010-01-02 0 -10 2 1 days
3 INV_1 x 2010-01-03 5 5 1 16 days
4 INV_1 x 2010-01-08 2 -3 1 16 days
5 INV_1 x 2010-01-19 0 -2 1 16 days