1
votes

transmute une grande trame de données en 3 colonnes

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)


0 commentaires

3 Réponses :


2
votes

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


0 commentaires

5
votes

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))]))


0 commentaires

2
votes

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")))


0 commentaires