在R

时间:2018-04-04 19:18:11

标签: r function dataframe multiple-columns apply

我想构建一个特定的函数,它对整个数据框中不同列组合的行进行求和。

示例 - 我有一个带有第一个描述性列和20个列(v1,v2,v3,...)的数据框,从1到20,其中只有可能的值为1或0.我想要一个函数,我可以根据特定事件从列中求和值。如果每个示例函数都设置为3,那么我需要在第一个新创建的变量(v1s)中将前3列(v1,v2和v3)相加在一起,然后将下3个列相加在一起(v2,v3, v4)在下一个新创建的变量(v2s)等中

可重复的例子:

set.seed(300) 
db <- matrix(sample(0:1,5*20, replace=TRUE),5,20)
us <- c("A","B","C","D","E")
db <- as.data.frame(cbind(us,db))

所以我想控制定义我想要总结的列数(通过控制我的意思是每个例子将其更改为5列并不困难)。在3列的情况下,我想创建18个额外的变量(从1到最后的3个变量的所有连续组合),包含3列的行和。

我尝试了几个选项,但是我无法找到简单的方法。我正在考虑一个函数,它将列的输入数量作为输入,然后将rowums值作为值并迭代所有组合,但是我无法破解这个。请帮忙!

2 个答案:

答案 0 :(得分:2)

可能有一种更简单的方法。无论如何,这是我的方法:

<强>代码:

grp_colsum <- function(df, n) {
  # generate the set of indices 123, 234, 345, ...
  idx <- sapply(1:n, `+`, 0:(ncol(df)-n))
  # for each set of indices
  res <- apply(idx, 1, function(x) {
    rowSums(df[,x])
  })
  colnames(res) <- paste0("v", 1:ncol(res), "s")
  res
}
grp_colsum(db[,-1], 3)

<强>输出:

    v1s v2s v3s v4s v5s v6s v7s v8s v9s v10s v11s v12s v13s v14s v15s v16s v17s v18s
[1,]   2   2   3   2   2   1   1   1   1    2    1    2    2    2    2    1    2    1
[2,]   2   2   1   2   2   2   1   1   2    2    2    1    2    1    1    1    1    2
[3,]   2   2   2   2   2   3   3   2   2    2    3    3    2    2    1    2    2    2
[4,]   2   2   2   2   1   2   2   2   2    2    2    2    1    1    1    2    3    3
[5,]   3   3   2   1   0   1   1   2   2    2    1    1    2    3    2    1    1    1

答案 1 :(得分:1)

如果我正确理解了这个问题,可以通过将数据从宽格式转换为长格式来获得结果,通过滚动窗口对每个组ID us进行求和,并重新调整为宽格式:

library(data.table)
# define number of columns to sum over
width <- 3L
# reshape from wide to long format
melt(setDT(db), id = "us")[
  # make sure that column values can be added
  , value := as.integer(value)][
    # sum across a rolling window for each group
    , Reduce("+", shift(value, n = 0:(width - 1L), type = "lead")), by = us][
      # remove rows from incomplete window sizes
      !is.na(V1)][
        # reshape to wide format again
        , dcast(.SD, us ~ sprintf("S%02i", rowid(us)))]

返回

   us S01 S02 S03 S04 S05 S06 S07 S08 S09 S10 S11 S12 S13 S14 S15 S16 S17 S18
1:  A   2   2   3   2   2   1   1   1   1   2   1   2   2   2   2   1   2   1
2:  B   2   2   1   2   2   2   1   1   2   2   2   1   2   1   1   1   1   2
3:  C   2   2   2   2   2   3   3   2   2   2   3   3   2   2   1   2   2   2
4:  D   2   2   2   2   1   2   2   2   2   2   2   2   1   1   1   2   3   3
5:  E   3   3   2   1   0   1   1   2   2   2   1   1   2   3   2   1   1   1

n <- 5L我们得到

   us S01 S02 S03 S04 S05 S06 S07 S08 S09 S10 S11 S12 S13 S14 S15 S16
1:  A   4   3   4   3   2   2   2   2   2   3   3   3   3   3   3   2
2:  B   3   3   3   3   2   3   3   2   3   3   3   2   2   2   2   2
3:  C   3   3   4   4   4   4   4   4   4   4   4   4   3   3   3   3
4:  D   3   3   3   3   3   3   3   4   3   3   3   2   2   3   3   4
5:  E   4   3   2   2   1   2   3   3   2   3   3   3   3   3   3   2

作为先决条件,db不得包含任何NA值。