Reputation: 335
I have a tibble like this, which can be seen as a longitudinal dataset
df <- tibble( T = rep(1:5,each=3), dens = rnorm(15,0,1) )
From df
, I wish to obtain a new 3-by-5
matrix, so that the first column is the value of dens
for T=1
; the second column is product of dens[T=1] dens[T=2]
so on and so forth.
The expected output is
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])
How this can be done in a tibble more efficiently?
Upvotes: 1
Views: 36
Reputation: 101663
Perhaps a base R option using Reduce
could help
> 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
Upvotes: 1
Reputation: 887213
An option is to do a group by the rowid
of 'T' column, get the cumprod
of 'dens' and reshape to 'wide' format with 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)
-output
# 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
-checking with OP's expected
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
Upvotes: 1