【问题标题】:Sum observations from two columns, looping over many columns in R对两列的观察求和,循环 R 中的许多列
【发布时间】:2016-02-13 03:36:39
【问题描述】:

我已经搜索了高低,但我被困在如何处理这个问题上。我有两组要逐行求和的列,但我想遍历多列。如果我要手动执行此操作,我会想要:

df1[1,1]+df2[1,1]
df1[2,1]+df2[2,1]

等等...我找到了很多有用的例子来说明如何做这样的事情:

apply(df[,c("a","d")], 1, sum)

虽然我想在很多列上执行此操作。此外,虽然它并不完全相关,但我想尽可能接近我的现实来表达我的问题,所以我下面的示例包括 NA,因为我的实际数据包含许多缺失值。

# make a data frame, df1, with three columns
a <- sample(1:100, 50, replace = T)
b <- sample(100:300, 50, replace = T)
c <- sample(2:50, 500, replace = T)
df1 <- cbind(a,b,c)

# make another data frame, df2, with three columns
x <- sample(1:100, 50, replace = T)
y <- sample(100:300, 50, replace = T)
z <- sample(2:50, 50, replace = T)
df2 <- cbind(x,y,z)

# make another data frame, df2, with three columns
x <- sample(1:100, 50, replace = T)
y <- sample(100:300, 50, replace = T)
z <- sample(2:50, 50, replace = T)
df2 <- cbind(x,y,z)

使随机抛出一些 NA 成为可能,函数来自 http://www.r-bloggers.com/function-to-generate-a-random-data-set/

NAins <-  NAinsert <- function(df, prop = .1){
    n <- nrow(df)
    m <- ncol(df)
    num.to.na <- ceiling(prop*n*m)
    id <- sample(0:(m*n-1), num.to.na, replace = FALSE)
    rows <- id %/% m + 1
    cols <- id %% m + 1
    sapply(seq(num.to.na), function(x){
            df[rows[x], cols[x]] <<- NA
    }
    )
    return(df)
}

将 NA 添加到帧中

NAins(df1, .2)
NAins(df2, .14)       

然后,我尝试沿每个数据帧中的列排序,并使用 apply 将索引设置为 1,这意味着对每个行条目求和。这行不通。

for(i in seq_along(df1)){
    for(j in seq_along(df2)){ 
            apply(c(df1[,i], col2[j]), 1, function(x) sum(x, na.rm = T))}}

感谢您的帮助!

【问题讨论】:

  • replace(df1, is.na(df1), 0) + replace(df2, is.na(df2), 0)?
  • (哦,虽然很高兴您提供了可重现的数据,但您共享的数据是矩阵,而不是data.frames,我认为您可以用不到 500 的数据来解释您的问题行样本数据!)
  • 哎呀 - 意味着输入 50,而不是 500...更新它。我想我可能没有正确地表达我的问题。实际上有一个 52 长的列列表和另一个 52 长的列表。我想在两个列表的每一列中添加观察结果(它可能是两个列列表,也可能只是来自两个数据框的列)。
  • 请使示例尽可能小,以便您也可以显示所需的输出。另外,使用data.frame 创建data.frames,而不是cbind
  • @M.Elliott 考虑投票并检查答案是否正确

标签: r loops


【解决方案1】:

您应该可以将NA 替换为0,然后添加“+”:

replace(df1, is.na(df1), 0) + replace(df2, is.na(df2), 0)
#    X  Y  Z
# 1  7 19  6
# 2 11 12  1
# 3 16 14 11
# 4 13  7 13
# 5 10  2 11

或者,如果您有不止两个data.frames,您可以将它们收集到list 并使用Reduce

Reduce("+", lapply(mget(c("df1", "df2", "df3")), function(x) replace(x, is.na(x), 0)))

这里有一些示例数据(我认为创建它的方法更简单):

set.seed(1) ## Set a seed so others can reproduce your sample data

dfmaker <- function() {
  setNames(
    data.frame(
      replicate(3, sample(c(NA, 1:10), 5, TRUE), FALSE)), 
    c("X", "Y", "Z"))
}

df1 <- dfmaker()
df1
#   X  Y Z
# 1 2  9 2
# 2 4 10 1
# 3 6  7 7
# 4 9  6 4
# 5 2 NA 8

df2 <- dfmaker()
df2
#    X  Y  Z
# 1  5 10  4
# 2  7  2 NA
# 3 10  7  4
# 4  4  1  9
# 5  8  2  3

df3 <- dfmaker()

【讨论】:

    【解决方案2】:

    您可以将 data.frame 转换为数组并使用 apply 函数对它们求和。

    install.package('abind')    
    library(abind)
    
    df <- abind(list(df1,df2), along = 3)
    results <- apply(df, MARGIN = c(1,2), FUN = function(x) sum(x, na.rm = TRUE))
    results
    

    【讨论】:

      猜你喜欢
      • 2020-11-27
      • 2016-04-07
      • 1970-01-01
      • 1970-01-01
      • 2018-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-17
      相关资源
      最近更新 更多