Curt F.
Curt F.

Reputation: 4824

add new column to dataframe by referencing name of existing columns

I have a dataframe of this form:

df <- data.frame(abc = c(1, 0, 3, 2, 0), 
                 foo = c(0, 4, 2, 1, 0),
                 glorx = c(0, 0, 0, 1, 2))

Here, the column names are strings and the values in the data frame are the number of times I would like to concatenate that string in a new data column. The new column I'd like to create would be a concatenation across all existing columns, with each column name being repeated according to the data.

For example, I'd like to create this new column and add it to the dataframe.

new_col <- c('abc', 'foofoofoofoo', 'abcabcabcfoofoo', 'abcabcfooglorx', 'glorxglorx')
also_acceptable <- c('abc', 'foofoofoofoo', 'abcfooabcfooabc', 'abcfooglorxabc', 'glorxglorx')

df %>% mutate(new_col = new_col, also_acceptable = also_acceptable)

The order of concatenation does not matter. The core problem I have is I don't know how to reference the name of a column by row when constructing a purrr::map() or dplyr::mutate() function to build a new column. Thus, I'm not sure how to programatically construct this new column.

(The core application here is combinatorial construction of chemical formulae in case anyone wonders why I would need such a thing.)

Upvotes: 1

Views: 826

Answers (1)

akuiper
akuiper

Reputation: 214927

Here is an option using Map and strrep:

mutate(df, new_col = do.call(paste, c(sep="", Map(strrep, names(df), df))))

#  abc foo glorx         new_col
#1   1   0     0             abc
#2   0   4     0    foofoofoofoo
#3   3   2     0 abcabcabcfoofoo
#4   2   1     1  abcabcfooglorx
#5   0   0     2      glorxglorx

Or a simpler version as @thelatemail's comment:

df %>% mutate(new_col = do.call(paste0, Map(strrep, names(.), .)))

Map gives a list as follows:

Map(strrep, names(df), df) %>% as.tibble()

# A tibble: 5 x 3
#        abc          foo      glorx
#      <chr>        <chr>      <chr>
#1       abc                        
#2           foofoofoofoo           
#3 abcabcabc       foofoo           
#4    abcabc          foo      glorx
#5                        glorxglorx

Use do.call(paste, ...) to paste strings rowwise.

Upvotes: 2

Related Questions