apple | banana | orange | fruits_name |
---|---|---|---|
1 | 0 | 1 | apple orange |
1 | 0 | 0 | apple |
1 | 0 | 1 | apple orange |
1 | 1 | 1 | apple banana orange |
I want to create and mutate the column "frutis_name" if the rest of the columns get 1. As an example, apple and orange got 1 then "frutis_name will be apple space banana.
CodePudding user response:
Using purrr::map_chr()
:
df <- data.frame(apple = c(1,1), banana = c(0,0), orange = c(1,0))
df$fruit_name <- purrr::pmap_chr(df, ~ paste(names(df)[as.logical(c(...))], collapse = " "))
df
#> apple banana orange fruit_name
#> 1 1 0 1 apple orange
#> 2 1 0 0 apple
CodePudding user response:
Perhaps not the easiest solution but one that works, based on the idea of recasting column names as values, which is done by pivot_longer
:
library(tidyverse)
df %>%
# create row ID:
mutate(row = row_number()) %>%
# cast longer so that fruit names become values:
pivot_longer(-row, names_to = "fruits") %>%
# for each combination of `row` and `value`...
group_by(row, value) %>%
# ... combine fruit names if `value == 1`:
mutate(fruits = ifelse(value == 1, str_c(fruits, collapse = " "), fruits)) %>%
# remove obsolete rows:
filter(value == 1 & !duplicated(fruits)) %>%
# deactivate grouping:
ungroup() %>%
# remove unnecessary columns:
select(-c(value, row)) %>%
# bind original `df` together with new `fruit` column:
bind_cols(df, .)
apple banana orange fruits
1 1 0 1 apple orange
2 1 0 0 apple
3 1 0 1 apple orange
4 1 1 1 apple banana orange
CodePudding user response:
df$fruits_name <-
apply(df, 1, \(x) paste(names(df)[as.logical(x)], collapse = " "))
# apple banana orange fruits_name
# 1 1 0 1 apple orange
# 2 1 0 0 apple
# 3 1 0 1 apple orange
# 4 1 1 1 apple banana orange
Same logic but more efficient
library(data.table)
df$fruits_name <-
vapply(transpose(df), \(x) paste(names(df)[as.logical(x)], collapse = " "), character(1L))
Reproducible data
df <- data.frame(
apple = 1,
banana = c(0,0,0,1),
orange = c(1,0,1,1)
)
CodePudding user response:
You can use apply
to do it:
x <- data.frame(apple = c(1,0,1), banana = c(0,0,1), orange = c(1,0,0))
x$fruits_name <- apply(x, 1, function(y) paste(colnames(x)[y==1], collapse=" "), simplify = TRUE)
x
apple banana orange fruits_name
1 1 0 1 apple orange
2 0 0 0
3 1 1 0 apple banana
EDIT: I replaced the sep
parameter with collapse
and now it produces a vector, not a list