当前位置: 首页 > 知识库问答 >
问题:

分析R中多个列的重复类别

楚天宇
2023-03-14

我有一个按类别分组的公司数据集。有些公司有多个类别,可以跨多个列重复。我想知道如何根据类别(比如每个类别的平均值)来分析它们。这是一个示例数据框

a <- factor(c("cat1", "cat2", "cat3", "cat4", "cat2"))
b <- factor(c("cat5", "cat4", "cat2", "cat1", "NA"))
comp <- factor(c("company1", "company2", "company3", "company4","company5"))
score <- c(1, -1, 2, -2, 1.5) 
df <- data.frame(a, b, comp, score)

#     a    b     comp score
#1 cat1 cat5 company1   1.0
#2 cat2 cat4 company2  -1.0
#3 cat3 cat2 company3   2.0
#4 cat4 cat1 company4  -2.0
#5 cat2   NA company5   1.5

我想知道的一项任务是每个类别的平均值。通过关注这个简单的数据集,我知道 cat1 的平均值将是 -0.5。我有一些粗略的方法,但没有完成任务:

>

  • 我考虑过将熔体应用于数据。框架,以便类别因子的每个实例都有自己的行(在本例中,维度为10x1,每一行的每个类别分数对)。

    我还考虑过使用dplyr并按照惟一的名称进行分组,比如

    mynames <- unique(c(levels(a), levels(b)))
    

    但是,dplyr要求分组是data.frame中的向量(除非有某种方法可以通过我不知道的模式或因素级别进行分组,这将是很棒的!)

    谢谢你的帮助!

  • 共有2个答案

    韶英达
    2023-03-14

    使用熔化和 ddply 函数:

    df_melt <- melt(df, id.vars = c("comp", "score"), measure.vars = c("a", "b"))
    ddply( .data = df_melt, .variables = .(value), summarise, mean = round(mean(score), digits = 2) )
    

    通过这种方式,也很容易计算其他汇总统计数据。

    对于更大的数据集,按照Molx:

    # adding a hypothetical company column so that we do not deviate from the smaller dataset case above:
    bigdf$comp <- paste("company", 1:50000, sep = "")
    
    measure_vars <- names(bigdf)[-c(dim(bigdf)[2]-1, dim(bigdf)[2])]
    bigdf_melt <- melt(bigdf, id.vars = c("comp", "score"), measure.vars = measure_vars)
    # transform value column to an ordered factor so that ddply returns result in an ordered category fashion
    bigdf_melt$value <- factor(bigdf_melt$value, levels = paste0("cat", 1:ncats), ordered = TRUE)
    
    bigdf_mean <- ddply( .data = bigdf_melt, .variables = .(value), summarise, mean = round(mean(score), digits = 4) )
    bigdf_mean
    
    司空默
    2023-03-14

    按照您获取所有类别的想法,我们可以为每个类别创建布尔列,它们只取具有该类别的那些列的平均值。例如:

    a <- factor(c("cat1", "cat2", "cat3", "cat4", "cat2"))
    b <- factor(c("cat5", "cat4", "cat2", "cat1", NA)) #NA, not "NA" or it will be a new level
    score <- c(1, -1, 2, -2, 1.5) 
    df <- data.frame(a, b, score)
    

    我们创建一个包含所有类别的向量:

    cats <- unique(c(levels(df$a), levels(df$b)))
    

    然后,对于每一个类别,我们检查每一行,类别是否存在于ab中:

    catcols <- sapply(cats, function(i) {
      sapply(1:nrow(df), function(j) {
        return(i %in% df$a[j] | i %in% df$b[j])
      })
    })
    

    这将返回一个矩阵,我们可以将其添加到数据帧中:

    > catcols
          cat1  cat2  cat3  cat4  cat5
    [1,]  TRUE FALSE FALSE FALSE  TRUE
    [2,] FALSE  TRUE FALSE  TRUE FALSE
    [3,] FALSE  TRUE  TRUE FALSE FALSE
    [4,]  TRUE FALSE FALSE  TRUE FALSE
    [5,] FALSE  TRUE FALSE FALSE FALSE
    
    > df2 <- cbind(df, catcols)
    

    现在我们只需要对每个类别取平均值,只对类别的TRUE的那些行进行子集:

    means <- sapply(cats, function(i) {
      mean(df2[df2[,i],"score"])
    })
    
    means
    
    #       cat1       cat2       cat3       cat4       cat5 
    # -0.5000000  0.8333333  2.0000000 -1.5000000  1.0000000 
    

    编辑

    我无法找到更好的替代方案,但我能够稍微改进代码。使用关于您提到的大小的随机数据

    ncats <- 500
    allcats <- paste0("cat", 1:ncats)
    nrow <- 50000
    ncol <- 26
    set.seed(1)
    bigdf <- data.frame(replicate(ncol, sample(allcats, nrow, replace = TRUE)), score=rnorm(nrow))
    

    代码:

    scorecol <- which(names(bigdf) == "score")
    
    catcols <- data.frame(sapply(allcats, function(i) {
      apply(bigdf[,-scorecol], 1, function(j) i %in% j)
    }))
    
    means <- sapply(allcats, function(i) {
      mean(bigdf[catcols[,i],"score"])
    })
    

    这对我来说花了195秒,大约是之前方法的30%时间(用较小的数据进行微基准测试)。结果是:

    > head(means)
            cat1         cat2         cat3         cat4         cat5         cat6 
    0.0019851051 0.0006465704 0.0066345735 0.0126089999 0.0135545455 0.0253983216 
    

    我试图寻找dplyr替代方案,但找不到任何有用的东西。我确信使用<code>数据有一种更快的方法。表,但我还不太熟悉这个包。

     类似资料:
    • 在R中使用pull命令时,是否可以拉动多个列?怎样当我尝试添加第二列(X2)时,R认为我添加了一个新参数。见下文。

    • 在Python / Django的API中,硒具有driver.find_element/elements_by_class_name()的功能,但是没有写它是否可用于几个类,我需要选择具有bj,bd,bi等几个类的元素如果可能的话,如何?

    • 我有一个Pandas DataFrame列,其中包含一个列表中的多个列表。类似于这样: 我想将列表拆分为多列,因此输出应该是这样的: 请帮我做这件事。预先感谢

    • 我正在使用熊猫。我试图从一个较大的文件中读取一列名称。这个文件总共是35GB,这使得我的内核死了。所以我想在其中一个专栏里读到。然后我希望“块”这个数据,这样内核就不会死。由此,我需要得到每个名字的总和,并找到计数最高的名字。以下是可能有用的: 要从主文件导入的列名:

    • 总之,我是R的初学者。我不太熟悉R中类的组织方式。我注意到一些class()调用返回一种类类型,而其他调用返回多个类名。 例1 {我的对象名是“sassign”}以下是我的数据: 现在,如果我执行上面的类(对象),我会得到: 我很擅长这个。我知道这个数据结构是数据帧类型。 例2现在,我最近看到了韦翰的tibbleR软件包。下面是我如何将数据帧转换为TIBLE的: 这就是我迷路的地方。我不知道tbl