Constructing a tibble from another tibble (without for loops?)

tibbles documentation

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 of source_cols and is named after a constructed_col.
• initialize an empty constructed_tbl tibble w/ appropriate nrows, ncols, and column names
• Loop through names(col_conversion_lst) replacing the empty column from constructed_tbl with the sum of the appropriate columns from source_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]]])
}

• Welcome to Code Review. You might want to include a reference about what a tibble is. – Simon Forsberg Mar 16 '18 at 19:37
• Thank you. I added a link, but shouldn't I expect that anyone who could answer this question would already know what a tibble is? – timwiz Mar 16 '18 at 19:40
• Sure, but don't expect the readers of your question to know what a tibble is. The more readers can understand of your code the easier it is to post an answer. I'd recommend taking a look at Simon's Guide to posting a good question. In particular, you could improve {todo}. – Simon Forsberg Mar 16 '18 at 21:11

I would use a matrix multiplication. It is both efficient and leads to much shorter code, as you can see:

constructed_tbl <- as.tibble(as.matrix(source_tbl) %*% table(col_conversion_tbl))

• This is a great answer. In reality, my source_tbl contains many more columns than just those listed in the col_conversion_tbl. So in order to use this method I just need to add a line that selects only those columns in source_tbl that are found in source_col from col_conversion_tbl: source_tbl <- source_tbl %>% select(col_conversion_tbl\$source_col) – timwiz Apr 12 '18 at 13:02