在所有对排列中减去列数据 R
Subtracting column data in all pair permutations R
我在数据框中有每小时价格数据,我需要在其中减去所有排列以找到金融交易的最佳配对。每列(不包括定价日期、时间)都可以视为该股票在特定定价日期和时间的收盘价。这是数据:
test <- data.frame(pricedate = as.Date('2019-12-18'), hour = c(1,2,3,4,5), A = c(3,5,6,4,2), B = c(5,3,2,6,7), C = c(1,2,3,6,9))
我想获取所有排列组合之间差异的新数据框(或table)。因此,"A subtract B" 不同于 "B subtract A"。而且我不需要从自身中减去一列。结果 table 看起来像这样:
Pricedate Hour A-B A-C B-A B-C C-A C-B
2019-12-18 1 -2 2 2 4 -2 -4
2019-12-18 2 2 3 -2 1 -3 -1
.
.
.
我认为我需要数据以这种形式保留,因为我想在此之后用 R 计算一些财务统计数据。
这是一个 tidyverse 方法。首先,我们转换为更长的形式,其中每一列 A:C 都在一个新行中表示,并且它来自哪一列的名称在一个名为 "col" 的新列中。然后我们将 table 连接到自身,因此每一行都与共享相同日期和时间的所有行组合在一起。
然后我们计算差值,过滤掉行本身减去的行,将两列headers合并为一个标识列,然后转换回宽格式。
library(tidyverse)
test_longer <- test %>%
pivot_longer(A:C, names_to = "col", values_to = "val")
test_longer %>%
left_join(test_longer,
suffix = c("1", "2"),
by = c("pricedate", "hour")) %>%
filter(col1 != col2) %>%
mutate(dif = val1 - val2) %>%
unite("col", c(col1, col2), sep = "-") %>%
select(-c(val1, val2)) %>%
pivot_wider(names_from = col, values_from = dif)
# A tibble: 5 x 8
pricedate hour `A-B` `A-C` `B-A` `B-C` `C-A` `C-B`
<date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2019-12-18 1 -2 2 2 4 -2 -4
2 2019-12-18 2 2 3 -2 1 -3 -1
3 2019-12-18 3 4 3 -4 -1 -3 1
4 2019-12-18 4 -2 -2 2 0 2 0
5 2019-12-18 5 -5 -7 5 -2 7 2
我知道您将 dplyr
和 tidy
列为标签,但这里有一个可以在整洁的管道中轻松使用的基本方法:
somefunc <- function(x) {
as.data.frame(t(apply(x, 1, function(z) {
df <- as.data.frame.table(outer(z, z, `-`))
df <- df[ df[[1]] != df[[2]], ]
setNames(df[[3]], paste(df[[1]], df[[2]], sep = "_"))
})))
}
somefunc(test[3:5])
# B_A C_A A_B C_B A_C B_C
# 1 2 -2 -2 -4 2 4
# 2 -2 -3 2 -1 3 1
# 3 -4 -3 4 1 3 -1
# 4 2 2 -2 0 -2 0
# 5 5 7 -5 2 -7 -2
另一种使用 combn
的基础 R 方法。由于 B-A
是 -(A-B)
我们可以使用 combn
来计算每两个值之间的差异,并通过取反计算值得到另一个组合。
cols <- combn(names(test)[3:5], 2, paste, collapse = "-")
cols <- c(cols, sub("(.)-(.)", "\2-\1", cols))
test[cols] <- t(apply(test[3:5], 1, function(x) {
out <- combn(x, 2, function(x) x[1] - x[2])
c(out, -out)
}))
test
# pricedate hour A B C A-B A-C B-C B-A C-A C-B
#1 2019-12-18 1 3 5 1 -2 2 4 2 -2 -4
#2 2019-12-18 2 5 3 2 2 3 1 -2 -3 -1
#3 2019-12-18 3 6 2 3 4 3 -1 -4 -3 1
#4 2019-12-18 4 4 6 6 -2 -2 0 2 2 0
#5 2019-12-18 5 2 7 9 -5 -7 -2 5 7 2
我在数据框中有每小时价格数据,我需要在其中减去所有排列以找到金融交易的最佳配对。每列(不包括定价日期、时间)都可以视为该股票在特定定价日期和时间的收盘价。这是数据:
test <- data.frame(pricedate = as.Date('2019-12-18'), hour = c(1,2,3,4,5), A = c(3,5,6,4,2), B = c(5,3,2,6,7), C = c(1,2,3,6,9))
我想获取所有排列组合之间差异的新数据框(或table)。因此,"A subtract B" 不同于 "B subtract A"。而且我不需要从自身中减去一列。结果 table 看起来像这样:
Pricedate Hour A-B A-C B-A B-C C-A C-B
2019-12-18 1 -2 2 2 4 -2 -4
2019-12-18 2 2 3 -2 1 -3 -1
.
.
.
我认为我需要数据以这种形式保留,因为我想在此之后用 R 计算一些财务统计数据。
这是一个 tidyverse 方法。首先,我们转换为更长的形式,其中每一列 A:C 都在一个新行中表示,并且它来自哪一列的名称在一个名为 "col" 的新列中。然后我们将 table 连接到自身,因此每一行都与共享相同日期和时间的所有行组合在一起。
然后我们计算差值,过滤掉行本身减去的行,将两列headers合并为一个标识列,然后转换回宽格式。
library(tidyverse)
test_longer <- test %>%
pivot_longer(A:C, names_to = "col", values_to = "val")
test_longer %>%
left_join(test_longer,
suffix = c("1", "2"),
by = c("pricedate", "hour")) %>%
filter(col1 != col2) %>%
mutate(dif = val1 - val2) %>%
unite("col", c(col1, col2), sep = "-") %>%
select(-c(val1, val2)) %>%
pivot_wider(names_from = col, values_from = dif)
# A tibble: 5 x 8
pricedate hour `A-B` `A-C` `B-A` `B-C` `C-A` `C-B`
<date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2019-12-18 1 -2 2 2 4 -2 -4
2 2019-12-18 2 2 3 -2 1 -3 -1
3 2019-12-18 3 4 3 -4 -1 -3 1
4 2019-12-18 4 -2 -2 2 0 2 0
5 2019-12-18 5 -5 -7 5 -2 7 2
我知道您将 dplyr
和 tidy
列为标签,但这里有一个可以在整洁的管道中轻松使用的基本方法:
somefunc <- function(x) {
as.data.frame(t(apply(x, 1, function(z) {
df <- as.data.frame.table(outer(z, z, `-`))
df <- df[ df[[1]] != df[[2]], ]
setNames(df[[3]], paste(df[[1]], df[[2]], sep = "_"))
})))
}
somefunc(test[3:5])
# B_A C_A A_B C_B A_C B_C
# 1 2 -2 -2 -4 2 4
# 2 -2 -3 2 -1 3 1
# 3 -4 -3 4 1 3 -1
# 4 2 2 -2 0 -2 0
# 5 5 7 -5 2 -7 -2
另一种使用 combn
的基础 R 方法。由于 B-A
是 -(A-B)
我们可以使用 combn
来计算每两个值之间的差异,并通过取反计算值得到另一个组合。
cols <- combn(names(test)[3:5], 2, paste, collapse = "-")
cols <- c(cols, sub("(.)-(.)", "\2-\1", cols))
test[cols] <- t(apply(test[3:5], 1, function(x) {
out <- combn(x, 2, function(x) x[1] - x[2])
c(out, -out)
}))
test
# pricedate hour A B C A-B A-C B-C B-A C-A C-B
#1 2019-12-18 1 3 5 1 -2 2 4 2 -2 -4
#2 2019-12-18 2 5 3 2 2 3 1 -2 -3 -1
#3 2019-12-18 3 6 2 3 4 3 -1 -4 -3 1
#4 2019-12-18 4 4 6 6 -2 -2 0 2 2 0
#5 2019-12-18 5 2 7 9 -5 -7 -2 5 7 2