dput(df)
structure(list(trtmt = c(26, 28, 35, 42, 49, 63, 33, 24, 38,
4, 24, 10, 59, 20, 16, 15, 66, 23, 51, 41, 39, 17, 8, 9, 28,
2, 13, 32, 43, 58, 4, 49, 63, 27, 27, 34, 6, 8, 57, 43, 23, 10,
50, 47, 41, 65, 57, 21, 15, 35), R = c(150, 150, 0, 0, 25, 25,
0, 100, 0, 150, 100, 0, 100, 50, 25, 25, 33, 100, 100, 0, 0,
50, 0, 0, 150, 50, 25, 0, 0, 50, 150, 25, 25, 150, 150, 0, 0,
0, 25, 0, 100, 0, 50, 100, 0, 100, 25, 100, 25, 0), V = c(50,
150, 50, 150, 0, 100, 50, 150, 100, 0, 150, 0, 0, 150, 150, 100,
30.3, 100, 0, 150, 100, 25, 150, 0, 150, 0, 25, 25, 150, 0, 0,
0, 100, 100, 100, 50, 50, 150, 0, 150, 100, 0, 0, 0, 150, 25,
0, 25, 100, 50), B = c(0, 0, 100, 50, 50, 25, 25, 0, 50, 0, 0,
50, 150, 0, 0, 0, 1.8, 0, 50, 25, 100, 0, 0, 25, 0, 0, 0, 150,
100, 150, 0, 50, 25, 0, 0, 50, 0, 0, 150, 100, 0, 50, 50, 25,
25, 25, 150, 0, 0, 100)), row.names = c(NA, -50L), class = c("tbl_df",
"tbl", "data.frame"))
head(df)
# A tibble: 6 × 4
trtmt R V B
<dbl> <dbl> <dbl> <dbl>
1 26 150 50 0
2 28 150 150 0
3 35 0 50 100
4 42 0 150 50
5 49 25 0 50
6 63 25 100 25
With the code below, I was telling R, for each row in the key
column, grab the column names and values of R, V, and B, from left to right, and combine.
df %>%
rowwise() %>%
mutate(key = paste0(names(.[2:4])[c_across() == c(2:4)], collapse = '_'))
but I got this error
Error in `mutate()`:
! Problem while computing `key = paste0(names(.)[c_across() == c(2:4)], collapse = "_")`.
ℹ The error occurred in row 1.
Caused by error:
! Can't combine `trtmt` <double> and `id` <character>.
What I expected is
trtmt R V B key
<dbl> <dbl> <dbl> <dbl> <chr>
1 26 150 50 0 R150_V50_B0
2 28 150 150 0 R150_V150_B0
3 35 0 50 100 R0_V50_B100
4 42 0 150 50 R0_V150_B_50
5 49 25 0 50 R25_V0_B50
6 63 25 100 25 R25_V100_B25
I got the hint from Create new column containing names of other columns based on values of those columns.
Thanks for stopping by.
CodePudding user response:
We could use cur_column()
to get the column names by looping across
the columns of interest, paste
(str_c
) the column names with the values of the column, then use invoke
(or exec
from purrr
- similar to do.call/Reduce
in base R
to paste the columns row wise)
library(purrr)
library(dplyr)
library(stringr)
df %>%
mutate( key = invoke(str_c,
across(R:B, ~ str_c(cur_column(), .x)), sep = "_"))
-output
# A tibble: 50 × 5
trtmt R V B key
<dbl> <dbl> <dbl> <dbl> <chr>
1 26 150 50 0 R150_V50_B0
2 28 150 150 0 R150_V150_B0
3 35 0 50 100 R0_V50_B100
4 42 0 150 50 R0_V150_B50
5 49 25 0 50 R25_V0_B50
6 63 25 100 25 R25_V100_B25
7 33 0 50 25 R0_V50_B25
8 24 100 150 0 R100_V150_B0
9 38 0 100 50 R0_V100_B50
10 4 150 0 0 R150_V0_B0
# … with 40 more rows
CodePudding user response:
Another way to do this is with sprintf()
, my favorite little string function:
library(tidyverse)
df %>% mutate(key = sprintf('R%g_V%g_B%g',R ,V ,B ))
Note that unlike @akrun's solution this doesn't work if you need to dynamically assign the column names (i.e. if R V B are not known or can change).
# A tibble: 50 x 5
trtmt R V B key
<dbl> <dbl> <dbl> <dbl> <chr>
1 26 150 50 0 R150_V50_B0
2 28 150 150 0 R150_V150_B0
3 35 0 50 100 R0_V50_B100
4 42 0 150 50 R0_V150_B50
5 49 25 0 50 R25_V0_B50
6 63 25 100 25 R25_V100_B25
7 33 0 50 25 R0_V50_B25
8 24 100 150 0 R100_V150_B0
9 38 0 100 50 R0_V100_B50
10 4 150 0 0 R150_V0_B0