将大型数据框转换为 3 列

Sha*_*hin 1 r tidyverse

数据

df <- data.frame(a=c(1,1,1,1), b1=c(0,0,0,0), b2=c(0,0,0,0),c1=c(0,0,1,0), 
                 c2=c(0,1,0,0), e=c(0,0,0,0), d=c(0,0,0,0))
Run Code Online (Sandbox Code Playgroud)
  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
Run Code Online (Sandbox Code Playgroud)

我怎样才能将这些转换成 3 列变成 ab=a * sum(contains("b")) ac=a * (sum(contains("c")))

我正在寻找类似的东西 transmute(df, ab=a*(sum(b1+b2)), ac=a*(sum(c1+c2)), aothers=a*(sum (!contains ("a" | "b" | "c")))

AB: a * sum(any col that contains "b")

交流: a * sum(any col that contains "c")

其他: a * sum(contains anything but a or b or c)

Jaa*_*aap 5

一个基本的 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))]))
Run Code Online (Sandbox Code Playgroud)

这使:

> df2
  ab ac others
1  0  0      0
2  0  1      0
3  0  1      0
4  0  0      0
Run Code Online (Sandbox Code Playgroud)

另一种基础 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)
Run Code Online (Sandbox Code Playgroud)