【问题标题】:adding together multiple sets of columns in r将r中的多组列加在一起
【发布时间】:2018-09-18 21:13:08
【问题描述】:

我正在尝试将几组列添加在一起。

例子df:

  df <- data.frame(
  key = 1:5,
  ab0 = c(1,0,0,0,1),
  ab1 = c(0,2,1,0,0),
  ab5 = c(1,0,0,0,1),
  bc0 = c(0,1,0,2,0),
  bc1 = c(2,0,0,0,0),
  bc5 = c(0,2,1,0,1),
  df0 = c(0,0,0,1,0),
  df1 = c(1,0,3,0,0),
  df5 = c(1,0,0,0,6)
)

给我:

  key ab0 ab1 ab5 bc0 bc1 bc5 df0 df1 df5
1   1   1   0   1   0   2   0   0   1   1
2   2   0   2   0   1   0   2   0   0   0
3   3   0   1   0   0   0   1   0   3   0
4   4   0   0   0   2   0   0   1   0   0
5   5   1   0   1   0   0   1   0   0   6

我想将所有包含 0 和 5 的列组合在一起,并将它们放在 0 列中。

所以最终的结果是:

  key ab0 ab1 ab5 bc0 bc1 bc5 df0 df1 df5
1   1   2   0   1   0   2   0   0   1   1
2   2   0   2   0   3   0   2   0   0   0
3   3   0   1   0   1   0   1   0   3   0
4   4   0   0   0   2   0   0   2   0   0
5   5   2   0   1   1   0   1   0   0   6

我可以使用 3 行将列添加在一起:

df$ab0 <- df$ab0 + df$ab5
df$bc0 <- df$bc0 + df$bc5
df$df0 <- df$df0 + df$df5

但我的真实示例有一百多列,所以我想遍历它们并使用 apply。

第一个集合的列名包含在 col0 中,第二个集合的名称包含在 col5 中。

col0 <- c("ab0","bc0","df0")
col5 <- c("ab5","bc5","df5")

我创建了一个函数来使用 mapply 将列添加到一起:

fun1 <- function(df,x,y) {
  df[,x] <- df[,x] + df[,y]
}

mapply(fun1,df,col0,col5)

但我收到一个错误:df[, x] 中的错误:维度数不正确

想法?

【问题讨论】:

  • 你为什么有df$df0 &lt;- df$df0 + df$df0??
  • 糟糕,输入错误。最后一个 df$df0 的末尾应该有一个 5。修复了它,但我的问题仍然存在

标签: r multiple-columns mapply multiple-arguments


【解决方案1】:

假设它们的长度相同,只需通过它们的子集列将两个数据框相加。不需要循环。全矢量化操作。

final_df <- df[grep("0", names(df))] + df[grep("5", names(df))]

final_df <- cbind(final_df, df[grep("0", names(df), invert=TRUE)])     

final_df <- final_df[order(names(final_df))]
final_df

#   ab0 ab1 ab5 bc0 bc1 bc5 df0 df1 df5 key
# 1   2   0   1   0   2   0   1   1   1   1
# 2   0   2   0   3   0   2   0   0   0   2
# 3   0   1   0   1   0   1   0   3   0   3
# 4   0   0   0   2   0   0   1   0   0   4
# 5   2   0   1   1   0   1   6   0   6   5

Rextester demo

【讨论】:

  • 我正在寻找那个正则表达式函数并且感觉可能涉及 cbind。很难在这 3 个答案中选择正确答案。考虑到我的问题,您的解决方案是最简单的。谢谢
  • 很高兴听到!很高兴帮助学习过程。您甚至可以通过在grep 中使用 invert 检索所有非零列来缩短 cbind!查看编辑和演示。
【解决方案2】:

您可以使用 purrr 包中的 map2 一次遍历两个向量:

df <- data.frame(
  key = 1:5,
  ab0 = c(1,0,0,0,1),
  ab1 = c(0,2,1,0,0),
  ab5 = c(1,0,0,0,1),
  bc0 = c(0,1,0,2,0),
  bc1 = c(2,0,0,0,0),
  bc5 = c(0,2,1,0,1),
  df0 = c(0,0,0,1,0),
  df1 = c(1,0,3,0,0),
  df5 = c(1,0,0,0,6)
)

col0 <- c("ab0","bc0","df0")
col5 <- c("ab5","bc5","df5")

purrr::map2(col0, col5, function(x, y) {
  df[[x]] <<- df[[x]] + df[[y]]
})

> df
  key ab0 ab1 ab5 bc0 bc1 bc5 df0 df1 df5
1   1   2   0   1   0   2   0   1   1   1
2   2   0   2   0   3   0   2   0   0   0
3   3   0   1   0   1   0   1   0   3   0
4   4   0   0   0   2   0   0   1   0   0
5   5   2   0   1   1   0   1   6   0   6

【讨论】:

  • 我试过玩 purrr 但不知道这个包。谢谢。
【解决方案3】:

这是使用tidyverse 元包中的tidyrdplyr 的方法。

首先,我将表格转换为长(“整洁”)格式,并将列拆分为两个组件,并按这些组件的数字部分展开。

然后我做你描述的计算。

最后,我使用与第 1 步相反的方法将其恢复为原始格式。

library(tidyverse)
df_tidy <- df %>%
  # Step 1
  gather(col, value, -key) %>%
  separate(col, into = c("grp", "num"), 2) %>%
  spread(num, value) %>%
  # Step 2
  mutate(`0` = `0` + `5`) %>%
  # Step 3, which is just the inverse of Step 1.
  gather(num, value, -key, - grp) %>%
  unite(col, c("grp", "num")) %>%
  spread(col, value)

df_tidy
key ab_0 ab_1 ab_5 bc_0 bc_1 bc_5 df_0 df_1 df_5
1   1    2    0    1    0    2    0    1    1    1
2   2    0    2    0    3    0    2    0    0    0
3   3    0    1    0    1    0    1    0    3    0
4   4    0    0    0    2    0    0    1    0    0
5   5    2    0    1    1    0    1    6    0    6

【讨论】:

  • 我一直在尝试为此使用 tidyverse 包,但我无法找出正确的逻辑。这在这方面做得很好,并将它们放在了视野中。谢谢
猜你喜欢
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-26
  • 2020-12-27
相关资源
最近更新 更多