【问题标题】:R: colSums when not all columns are numericR:当并非所有列都是数字时的 colSums
【发布时间】:2015-08-09 21:00:29
【问题描述】:

我有以下数据框

Type   CA   AR
alpha   1   5  
beta    4   9 
gamma   3   8 

我想得到如下所示的列和行总和:

    Type   CA   AR Total
    alpha   1   5    6
    beta    4   9    13
    gamma   3   8    11
    Total   8   22   30

我想我可以做 rowSums(如上所示),因为它们都是数字的。

colSums(df)

但是,当我执行 colSums 时,我收到错误“x 必须是数字”。我意识到这是因为“类型”列不是数字。

如果我执行以下代码以尝试将值打印到第 4 行(并且仅对第 2 到第 4 列求和)

df[,4] = colSums(df[c(2:4)]

然后我得到一个错误,即替换与数据大小不同。

有谁知道如何解决这个问题?我想打印第 2-4 列的总和,并将第一列总计留空或允许我打印“总计”?

提前致谢!!

【问题讨论】:

  • 他们不是colSums,而是rowSums
  • 错误是因为您要求 R 将 n 列对象与 n-1 向量绑定,并且由于长度差异,R 可能不知道计算这个值。试试这个data[4, ] <- c(NA, colSums(data[, 2:3]) )
  • 错误是因为行不是列。没有 nn-1 概念问题。想象一个有 20 行 5 列的数据框。

标签: r


【解决方案1】:

在 plyr 包中结帐 numcolwise()

library(plyr)

df <- data.frame(
  Type = c("alpha", "beta", "gamme"),
  CA = c(1, 4, 3),
  AR = c(5, 9, 8)
)

numcolwise(sum)(df)

结果:

  CA AR
1  8 22

【讨论】:

  • 不应该。试试我刚刚发布的可重现示例。
  • 我得到这个错误; Error in match.fun(FUN) : '2.55108265612583e+24' is not a function, character or symbol
  • 更新到 plyr 1.0.1 后错误仍然存​​在。尽管我仍在使用 R 3.1.2,但我无法弄清楚可能有什么不同
【解决方案2】:

使用matrix

m <- as.matrix(df[,-1])
rownames(m) <- df$Type
#       CA AR
# alpha  1  5
# beta   4  9
# gamma  3  8

然后添加边距:

addmargins(m,FUN=c(Total=sum),quiet=TRUE)
#       CA AR Total
# alpha  1  5     6
# beta   4  9    13
# gamma  3  8    11
# Total  8 22    30

更简单的addmargins(m) 也可以,但默认使用“Sum”标记边距。

【讨论】:

    【解决方案3】:

    你是对的,这是因为第一列不是数字。

    尝试使用第一列作为行名:

    df <- data.frame(row.names = c("alpha", "beta", "gamma"), CA = c(1, 4, 3), AR = c(5, 9, 8))
    df$Total <- rowSums(df)
    df['Total',] <- colSums(df)
    df
    

    输出将是:

          CA AR Total
    alpha  1  5     6
    beta   4  9    13
    gamma  3  8    11
    Total  8 22    30
    

    如果您需要“类型”一词,只需删除行名并将列添加回:

    Type <- rownames(df)
    df <- data.frame(Type, df, row.names=NULL)
    df
    

    它的输出:

       Type CA AR Total
    1 alpha  1  5     6
    2  beta  4  9    13
    3 gamma  3  8    11
    4 Total  8 22    30
    

    【讨论】:

      【解决方案4】:

      用途:

      df$Total <- df$CA + df$AR
      

      更通用的解决方案:

      data$Total <- Reduce('+',data[, sapply(data, is.numeric)])
      

      编辑:我意识到我完全误解了这个问题。您确实在寻找行的总和,而我给出了列的总和。

      改为做行:

      data <- data.frame(x = 1:3, y = 4:6, z = as.character(letters[1:3]))
      data$z <- as.character(data$z)
      rbind(data,sapply(data, function(y) ifelse(test = is.numeric(y), Reduce('+',y), "Total")))
      

      【讨论】:

        【解决方案5】:

        如果您不知道哪些列是数字,而是想要跨 的总和,请执行以下操作:

        df$Total = rowSums( df[ sapply(df, is.numeric)] )
        

        is.numeric 函数将返回一个对选择列有效的逻辑值,sapply 将返回作为向量的逻辑值。 要添加一组列总计和总计,我们需要回退到创建数据集的位置,并防止“类型”列被构造为一个因素:

         dat <- read.table(text="Type   CA   AR
         alpha   1   5  
         beta    4   9 
         gamma   3   8 ",stringsAsFactors=FALSE)
        
         dat$Total = rowSums( dat[ sapply(dat, is.numeric)] )
        
         rbind( dat, append(c(Type="Total"),  
                            as.list(colSums( dat[ sapply(dat, is.numeric)] ))))
        #----------
           Type CA AR Total
        1 alpha  1  5     6
        2  beta  4  9    13
        3 gamma  3  8    11
        4 Total  8 22    30
        

        这是一个data.frame:

        > str( rbind( dat, append(c(Type="Total"),  as.list(colSums( dat[ sapply(dat, is.numeric)] )))) )
        'data.frame':   4 obs. of  4 variables:
         $ Type : chr  "alpha" "beta" "gamma" "Total"
         $ CA   : num  1 4 3 8
         $ AR   : num  5 9 8 22
         $ Total: num  6 13 11 30
        

        【讨论】:

        • 我认为我们误解了这个问题。 user4918087 正在寻找列和,​​而不是行和。注意底部的总计
        【解决方案6】:

        我认为这应该可以解决您的问题

        x<-data.frame(type=c('alpha','beta','gama'), x=c(1,2,3), y=c(4,5,6))
        x[,'Total'] <- rowSums(x[,c(2:3)])
        x<-rbind(x,c(type = c('Total'), c(colSums(x[,c(2:4)]))))
        

        【讨论】:

          【解决方案7】:
          library(tidyverse)
          
          df <- data.frame(
            Type = c("alpha", "beta", "gamme"),
            CA = c(1, 4, 3),
            AR = c(5, 9, 8)
          )
          
          df2 <- colSums(df[, c("CA", "AR")])
          # CA AR 
          # 8 22 
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-11-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多