提问人:JCWong 提问时间:11/15/2023 更新时间:11/15/2023 访问量:49
使用 dplyr 和 across 计算多个点积
Using dplyr and across to compute multiple dot products
问:
我有一个采用以下形式的数据帧
set.seed(100)
n = 1000
data = data.frame(
y1_a = rnorm(n),
y1_b = abs(rnorm(n)),
y2_a = rnorm(n),
y2_b = abs(rnorm(n))
)
我想计算 y1_a * y1_b 的点积,以及 y2_a * y2_b。
我能够像这样计算元素明智的产品mutate
across
data %>%
mutate(
(across(ends_with("a"), .names = '{.col}_b_dp') * across(ends_with("b")))
)
这将生成 2 个额外的列,分别称为“y1_a_b_dp”和“y2_a_b_dp”。但这些是元素乘积,而不是点积。因此,需要对这些列求和以产生点积。
但我很好奇,有没有办法使用带有 2 个引用的 summarise 来跨越
data %>%
summarise(
colSums(across(ends_with("a"), .names = '{.col}_b_dp') * across(ends_with("b")))
)
这几乎有效。它将元素乘积计算为 2 列,然后执行 colSums 以计算 2 个点积。但是,发回 summarise 的返回值是一个包含 2 行的数据帧,dplyr 对此表示不满。我希望发送到 summarise 的返回值是 2 列,就像在手动构造 mutate 和 sum 中一样。这可能吗?
答:
3赞
stefan
11/15/2023
#1
为了提高可读性,这里是一种使用方法和一个小的便利函数:reframe
library(dplyr, warn.conflicts = FALSE)
dp <- function(x, y) {
data.frame(
t(colSums(x * y))
)
}
data %>%
reframe(
dp(
across(ends_with("a"), .names = "{.col}_b_dp"),
across(ends_with("b"))
)
)
#> y1_a_b_dp y2_a_b_dp
#> 1 57.31544 -15.33576
评论
1赞
Maël
11/15/2023
我真的很喜欢这个辅助功能的使用。它使这个双重技巧更具可读性。+1!across
1赞
stefan
11/15/2023
谢谢@Maël。从你那里学到了这个技巧。它仍然让我感到惊讶的是它有效。:D
1赞
one
11/15/2023
#2
这是另一种方法:
data %>%
reframe(
across(ends_with("a"), ~sum(. * get(gsub("a","b",cur_column()))),.names = '{.col}_b_dp') )
y1_a_b_dp y2_a_b_dp
1 57.31544 -15.33576
评论