Я предлагаю "pivot", case_when
, и "join" дает вам ваши результаты.
library(dplyr)
# library(tidyr) # pivot_longer
df <- data.frame(a_b_c = c(1,3,5,0,0), a_b=c(0,0,4,0,0), a_b_c_d=c(1,2,2,3,0),
b_d=c(0,0,3,2,3), a_c = c(1,5,1,0,0)) %>%
mutate(row = row_number())
df %>%
tidyr::pivot_longer(-row) %>%
group_by(row) %>%
summarize(
category = case_when(
all(value > 0) ~ "Shared all",
sum(value > 0) == 1L ~ "Appears once",
all(value == 0 | grepl("c", name)) ~ "Shared c",
all(value == 0 | grepl("d", name)) ~ "Shared d",
TRUE ~ "Other"
)
) %>%
left_join(df, ., by = "row")
# a_b_c a_b a_b_c_d b_d a_c row category
# 1 1 0 1 0 1 1 Shared c
# 2 3 0 2 0 5 2 Shared c
# 3 5 4 2 3 1 3 Shared all
# 4 0 0 3 2 0 4 Shared d
# 5 0 0 0 3 0 5 Appears Once
Я должен добавить столбец row
, чтобы быть уверенным, что категория будет обратно в исходную строку, так как в противном случае строки не идентифицируются однозначно (за исключением полной уникальности, на которую я не рассчитывал). Я pivot
сделал так, чтобы мы не полагались на указанные c имена столбцов или на существование ровно пяти столбцов (это одинаково хорошо работает с 3 и 300, дайте или возьмите ваши логические c правила. Наконец, использование !grepl(...) | value>0
- это заданная c инверсия, гарантирующая, что все имена c
, включая (и d
), имеют значение выше 0, она легко расширяема, хотя в зависимости от вашего фактического варианта использования может потребоваться более сильное регулярное выражение (например, границы слова).