在 tibble 的一个变量中执行向量乘法
Execute vector multiplication in one variable of a tibble
我有一个这样的tibble,可以看成一个纵向数据集
df <- tibble( T = rep(1:5,each=3), dens = rnorm(15,0,1) )
从df
,我想得到一个新的3-by-5
矩阵,所以第一列是dens
的值,对于T=1
;第二列是 dens[T=1] dens[T=2]
的乘积,依此类推。
预期输出为
new_df <- cbind(df$dens[1:3], dff$dens[1:3]*df$dens[4:6],df$dens[1:3]*df$dens[4:6]*df$dens[7:9],
df$dens[1:3]*df$dens[4:6]*df$dens[7:9]*df$dens[10:12],df$dens[1:3]*df$dens[4:6]*df$dens[7:9]*df$dens[10:12]*df$dens[13:15])
如何更高效地完成这项工作?
一个选项是按 'T' 列的 rowid
进行分组,得到 'dens' 的 cumprod
并重塑为 'wide' 格式pivot_wider
library(dplyr)
library(tidyr)
library(data.table)
df %>%
group_by(rn = rowid(T)) %>%
mutate(dens = cumprod(dens)) %>%
ungroup %>%
pivot_wider(names_from = T, values_from = dens) %>%
select(-rn)
-输出
# A tibble: 3 x 5
# `1` `2` `3` `4` `5`
# <dbl> <dbl> <dbl> <dbl> <dbl>
#1 1.77 2.06 1.53 2.23 -4.41
#2 1.96 0.414 0.522 -0.175 0.182
#3 1.57 3.18 -3.99 -4.59 6.64
-检查 OP 的预期
cbind(df$dens[1:3],
df$dens[1:3]*df$dens[4:6],
df$dens[1:3]*df$dens[4:6]*df$dens[7:9],
df$dens[1:3]*df$dens[4:6]*df$dens[7:9]*df$dens[10:12],
df$dens[1:3]*df$dens[4:6]*df$dens[7:9]*df$dens[10:12]*df$dens[13:15])
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1.773718 2.0604976 1.5309983 2.2307720 -4.4127195
#[2,] 1.961222 0.4142233 0.5222992 -0.1748975 0.1820611
#[3,] 1.571597 3.1822827 -3.9931628 -4.5932566 6.6440672
也许使用 Reduce
的基本 R 选项可能会有所帮助
> do.call(cbind, Reduce("*", with(df, split(dens, T)), accumulate = TRUE))
[,1] [,2] [,3] [,4] [,5]
[1,] -1.2667876 -1.52064920 -2.25924893 2.55495272 -4.02049920
[2,] -0.2854711 -0.23282226 0.08117526 0.01885956 -0.01893413
[3,] 0.2698863 -0.07630793 0.06976650 0.05718294 -0.10454398
我有一个这样的tibble,可以看成一个纵向数据集
df <- tibble( T = rep(1:5,each=3), dens = rnorm(15,0,1) )
从df
,我想得到一个新的3-by-5
矩阵,所以第一列是dens
的值,对于T=1
;第二列是 dens[T=1] dens[T=2]
的乘积,依此类推。
预期输出为
new_df <- cbind(df$dens[1:3], dff$dens[1:3]*df$dens[4:6],df$dens[1:3]*df$dens[4:6]*df$dens[7:9],
df$dens[1:3]*df$dens[4:6]*df$dens[7:9]*df$dens[10:12],df$dens[1:3]*df$dens[4:6]*df$dens[7:9]*df$dens[10:12]*df$dens[13:15])
如何更高效地完成这项工作?
一个选项是按 'T' 列的 rowid
进行分组,得到 'dens' 的 cumprod
并重塑为 'wide' 格式pivot_wider
library(dplyr)
library(tidyr)
library(data.table)
df %>%
group_by(rn = rowid(T)) %>%
mutate(dens = cumprod(dens)) %>%
ungroup %>%
pivot_wider(names_from = T, values_from = dens) %>%
select(-rn)
-输出
# A tibble: 3 x 5
# `1` `2` `3` `4` `5`
# <dbl> <dbl> <dbl> <dbl> <dbl>
#1 1.77 2.06 1.53 2.23 -4.41
#2 1.96 0.414 0.522 -0.175 0.182
#3 1.57 3.18 -3.99 -4.59 6.64
-检查 OP 的预期
cbind(df$dens[1:3],
df$dens[1:3]*df$dens[4:6],
df$dens[1:3]*df$dens[4:6]*df$dens[7:9],
df$dens[1:3]*df$dens[4:6]*df$dens[7:9]*df$dens[10:12],
df$dens[1:3]*df$dens[4:6]*df$dens[7:9]*df$dens[10:12]*df$dens[13:15])
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1.773718 2.0604976 1.5309983 2.2307720 -4.4127195
#[2,] 1.961222 0.4142233 0.5222992 -0.1748975 0.1820611
#[3,] 1.571597 3.1822827 -3.9931628 -4.5932566 6.6440672
也许使用 Reduce
的基本 R 选项可能会有所帮助
> do.call(cbind, Reduce("*", with(df, split(dens, T)), accumulate = TRUE))
[,1] [,2] [,3] [,4] [,5]
[1,] -1.2667876 -1.52064920 -2.25924893 2.55495272 -4.02049920
[2,] -0.2854711 -0.23282226 0.08117526 0.01885956 -0.01893413
[3,] 0.2698863 -0.07630793 0.06976650 0.05718294 -0.10454398