首页 文章

按因子列聚合混合数据

提问于
浏览
0

在过去的一周里,我一直在尝试聚合我的数据集,该数据集由不同月份的不同重量测量值组成,伴随着R中的大量背景变量 .

我已经阅读了很多关于这个主题的不同问题(即R aggregate data by defining groupingHow to aggregate count of unique values of categorical variables in R),但它们似乎只能用于一种类型的数据,或者只对一列感兴趣 . 具体来说,问题Recoding categorical variables to the most common value处理几乎完全相同的问题,但建议的答案仅解决了分类数据的问题,它也不包括数字数据 . 我的数据包括两个因素(分类和序数)和数字数据 .

可重复的例子是:

IDnumber <- c("1", "1", "1", "2", "2", "3", "3", "3")
Gender <- c("Male", "Male", "Male", "Female", "Female", "Female", "Female",  "Female")
Weight <- c(80, 82, 82, 70, 66, 54, 50, 52)
LikesSoda <- c("Yes", "No", "No", "Yes", "Yes", "Yes", "Yes", NA)
df = data.frame(IDnumber, Gender, Weight, LikesSoda)

我的输出数据帧将取每个数值列的平均值,并且每个因子列的最常见因子 . 在示例中,这将如下所示:

IDnumber <- c("1", "2", "3")
Gender <- c("Male", "Female", "Female")
Weight <- c(81.5, 78, 52)
LikesSoda <- c("No", "Yes", "Yes")
output = data.frame(IDnumber, Gender, Weight, LikesSoda)

到目前为止,我还没有找到分类数据的工作函数 . 另一个选项是使用dplyr df &>& group_by(IDnumber) %>% summarise( transformation for each variable ) 代码,但这需要我指定如何手动处理每个列 . 由于我有超过2500列,这似乎不是一个可行的解决方案 .

1 回答

  • 2

    您可以编写自己的函数,然后使用 lapply . 首先,编写一个函数来查找因子变量中最常见的级别

    getmode <- function(v) {
      levels(v)[which.max(table(v))]
    }
    

    然后编写一个函数,根据传递给它的变量类型返回均值或模式

    my_summary <- function(x, id, ...){
      if (is.numeric(x)) {
        return(tapply(x, id, mean))
      }  
      if (is.factor(x)) {
        return(tapply(x, id, getmode))
      }  
    }
    

    最后,使用 lapply 来计算摘要

    data.frame(lapply(df, my_summary, id = df$IDnumber))
      IDnumber Gender   Weight LikesSoda
    1        1   Male 81.33333        No
    2        2 Female 68.00000       Yes
    3        3 Female 52.00000       Yes
    

    如果一个因子中有两个或更多个级别具有相同的最大频率,则 which.max 将返回第一个级别 . 我从你的评论中了解到,你只想知道它们中有多少,所以一个选项可能是略微修改 getmode 函数,所以当有一个平局时它会在级别上添加一个星号:

    getmode <- function(v) {
      tab <- table(v)
      if (sum(tab %in% max(tab)) > 1)  return(paste(levels(v)[which.max(tab)], '*'))
      levels(v)[which.max(tab)]
    }
    

    (更改样本数据,因此有一个女性和一个男性IDn ==“2”)

    data.frame(lapply(df, my_summary, id = df$IDnumber))
    
      IDnumber   Gender   Weight LikesSoda
    1        1     Male 81.33333        No
    2        2 Female * 68.00000       Yes
    3        3   Female 52.00000       Yes
    

    我担心这是一个混乱的“解决方案”,但如果你只是想知道这个问题有多普遍,也许它足以满足你的需求 .

相关问题