【问题标题】:How to average columns with the same name and ignore columns that are factors如何平均具有相同名称的列并忽略作为因素的列
【发布时间】:2019-01-24 01:09:08
【问题描述】:

我想对具有相同名称模式的列中的数据进行平均。如果您只有数字数据,其中一些示例非常有用:

How to calculate the mean of those columns in a data frame with the same column name

但是,我也有一列是一个因素。我可以删除此列然后 c(bind) 将其恢复,但这似乎很笨重。有没有办法可以使用 !is.factor(x) 之类的东西来忽略我的另一列?

df <- 
as.data.frame(matrix(c(1,3,3,2,2,5,3,2,3,6,3,2,4,7,3,2,5,4,5,2,6,3,5,2),
     ncol=6,
     dimnames=list(NULL, c("A.1", "B.1", "C.1", "B.2", "A.2", "C.2"))))

char = c("Apple", "banana", "cat", "rainbow")
df = cbind(char, df)

res <- as.data.frame(sapply(unique(names(df)), function(col) 
rowMeans(df[names(df) == col] )))

预期结果是: res char A B C Apple 3.0 3 4.5 banana 3.5 6 4.5 cat 4.0 3 4.0 rainbow 2.0 2 2.0

错误是:

` Error in rowMeans(df[names(df) == col]) : 'x' must be numeric `

【问题讨论】:

  • 您的错误是由于char 列是character 向量而不是numeric 向量。

标签: r


【解决方案1】:

对于通过扩展您拥有的基础 R 解决方案,

df <- 
  as.data.frame(matrix(c(1,3,3,2,2,5,3,2,3,6,3,2,4,7,3,2,5,4,5,2,6,3,5,2),
                       ncol=6,
                       dimnames=list(NULL, c("A.1", "B.1", "C.1", "B.2", "A.2", "C.2"))))

char = c("Apple", "banana", "cat", "rainbow")
df <- cbind(char, df)

names(df) <- gsub('.\\d', '', grep('[a-zA-Z]', names(df), value = TRUE)) ## removes the digit from your groups

res <-
  data.frame(
    factor = df$char,
    sapply(setdiff(unique(names(df)), 'char'), function(col)
      rowMeans(df[, names(df) == col]))
  )

> res
   factor   A B   C
1   Apple 3.0 3 4.5
2  banana 3.5 6 4.5
3     cat 4.0 3 4.0
4 rainbow 2.0 2 2.0

【讨论】:

    【解决方案2】:

    使用tidyverse,我想出了以下管道操作

    ##Recreate the data
    df <- as.data.frame(matrix(c(1,3,3,2,2,5,3,2,3,6,3,2,4,7,3,2,5,4,5,2,6,3,5,2),
                       ncol=6,
                       dimnames=list(NULL, c("A.1", "B.1", "C.1", "B.2", "A.2", "C.2"))))
    
    char = c("Apple", "banana", "cat", "rainbow")
    df = cbind(char, df)
    
    ##Load tidyverse
    
    library(tidyverse)
    
    #Gather the columns with titles, extract the first letter, then summarize
     new_df <- df %>% gather(column_type, value, `A.1`:`C.2`) %>%
               mutate(initial = str_extract(column_type, "[A-Z]")) %>%
               group_by(initial, char) %>% 
               summarise(mean = mean(value)) %>%
               spread(initial, mean)
    
    new_df
    

    【讨论】:

      【解决方案3】:

      在基础 R 中:您正在寻找以下内容:

      aggregate(.~char, reshape(df, 2:ncol(df), idvar = 'char',dir = 'long'), mean)[-2]
      
           char   A B   C
      1   Apple 3.0 3 4.5
      2  banana 3.5 6 4.5
      3     cat 4.0 3 4.0
      4 rainbow 2.0 2 2.0
      
      library(datatable)
      melt(setDT(df),'char',patterns(A='^A',B='^B',C='^C'))[,-2][,lapply(.SD,mean),by=char]
              char   A B   C
      1:   Apple 3.0 3 4.5
      2:  banana 3.5 6 4.5
      3:     cat 4.0 3 4.0
      4: rainbow 2.0 2 2.0
      

      【讨论】:

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