I've got this doing what I want, but it's using a for loop and I've read many times to avoid for loops in R for efficiency and style. Well, it's not a computationally demanding task and I think it might be as clear as it could be in a for loop. In any case, it seems a bit tricky to process this functionally rather than iteratively.
I'm starting with one tibble: source_tbl
.
I want to make another tibble: constructed_tbl
.
Every column in constructed_tbl
is a sum of a subset of columns in source_tbl
.
The column mapping is stored in col_conversion_tbl
.
>print(col_conversion_tbl)
# A tibble: 6 x 2
source_col constructed_col
<chr> <chr>
1 col1 A
2 col2 A
3 col3 A
4 col4 A
5 col5 B
6 col6 B
So,
constructed_tbl[,'A']
should be equal to ...
rowSums(source_tbl[,c('col1','col2','col3','col4')])
The best way I've come up with
The best way I've come up with is to
- convert
col_conversion_tbl
to a list,col_conversion_lst
, where each item is an array ofsource_col
s and is named after aconstructed_col
. - initialize an empty
constructed_tbl
tibble w/ appropriate nrows, ncols, and column names - Loop through
names(col_conversion_lst)
replacing the empty column fromconstructed_tbl
with the sum of the appropriate columns fromsource_tbl
.
Here's my code
library(tibble)
library(magrittr)
library(purrr)
source_tbl <- tibble(col1=c(1,1,1),col2=c(2,2,2),col3=c(3,3,3),col4=c(4,4,4),col5=c(5,5,5),col6=c(6,6,6))
col_conversion_tbl <- tibble(source_col = c('col1','col2','col3','col4','col5','col6'), constructed_col = c('A','A','A','A','B','B'))
col_conversion_lst <- col_conversion_tbl %>%
split(.$constructed_col) %>%
map(~.$source_col)
constructed_tbl <- as_tibble(matrix(nrow=nrow(source_tbl),ncol= length(col_conversion_lst) ))
colnames(constructed_tbl) <- names(col_conversion_lst)
for (n in names(col_conversion_lst)){
constructed_tbl[,n] <- rowSums(source_tbl[ ,col_conversion_lst[[n]]])
}
tibble
is. \$\endgroup\$ – Simon Forsberg Mar 16 '18 at 19:37tibble
is? \$\endgroup\$ – timwiz Mar 16 '18 at 19:40