XXX
a b1 b2 c1 c2 d e 1 1 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 1 0 0 1 0 0 0 4 1 0 0 0 0 0 0
Comment puis-je les transformer en 3 colonnes en ab = a * sum (contains ("b")) ac = a * (sum (contains ("c")))
Je cherche quelque chose de similaire à transmute (df, ab = a * (sum (b1 + b2)), ac = a * (sum (c1 + c2)), aothers = a * (sum (! ("a" | "b" | "c")))
ab: a * sum (toute colonne contenant "b")
p >
ac: a * sum (toute colonne contenant "c")
aothers: a * sum (contient autre chose que a ou b ou c)
3 Réponses :
Je pense que ce serait plus simple à gérer si nous convertissons les données au format long, créons une nouvelle colonne pour séparer les colonnes «b», «c» et «others», group_by
chacune et multiplier avec des valeurs "a".
library(dplyr) library(tidyr) df %>% mutate(row = row_number()) %>% pivot_longer(cols = -c(a, row)) %>% mutate(col = case_when(grepl('b', name) ~"ab", grepl('c', name) ~"ac", TRUE ~ "others")) %>% group_by(row, col) %>% summarise(value = sum(value * a)) %>% pivot_wider(names_from = col, values_from = value) %>% ungroup() %>% select(-row) # A tibble: 4 x 3 # ab ac others # <dbl> <dbl> <dbl> #1 0 0 0 #2 0 1 0 #3 0 1 0 #4 0 0 0
Une solution de base R:
p <- c("b","c") v <- c("others", paste0("a", p)) s <- sapply(p, grepl, x = names(df)[-1]) collist <- split.default(df[-1], v[rowSums(s * col(s)) + 1L]) l <- lapply(collist, function(x) df$a * rowSums(x)) df2 <- as.data.frame(l)
qui donne:
> df2 ab ac others 1 0 0 0 2 0 1 0 3 0 1 0 4 0 0 0
Une solution alternative de base R:
df2 <- data.frame(ab = df$a * rowSums(df[, grepl("b", names(df))]), ac = df$a * rowSums(df[, grepl("c", names(df))]), others = df$a * rowSums(df[, !grepl("a|b|c", names(df))]))
Voici une autre solution de base R avec cbind ()
+ grep ()
+ rowSums()
> dfout a ab ac others 1 1 0 0 0 2 1 0 1 0 3 1 0 1 0 4 1 0 0 0
tels que
nms <- names(df) dfout <- cbind(df[1], `colnames<-`(df$a*cbind(rowSums(df[grep("b",nms)]), rowSums(df[grep("c",nms)]), rowSums(df[grep("^[^abc]",nms)])), c("ab","ac","others")))