【问题标题】:Mean of top x entries of subset in RR中子集的前x个条目的平均值
【发布时间】:2012-06-07 15:53:56
【问题描述】:

假设我有数据框

df <- data.frame('A' = c('a','a','a','a','b','b','b','b','b'),
                 'B' = c('y','y','z','z','y','y','y','z','z'),
                 'value'=c(1  , 2 , 2 , 3 , 2 , 3 , 1 , 2 , 2))

原来是这样的

 A B value  
 a y     1  
 a y     2  
 a z     2  
 a z     3  
 b y     2  
 b y     3  
 b y     1   
 b z     2   
 b z     2  

我可以使用查询获得 A 和 B 的每个子集的平均值

with(df, aggregate(df, by = list(A, B), FUN = mean))

经过一些操作后得到

A B value  
a y   1.5  
b y   2.0  
a z   2.5  
b z   2.0  

有没有办法做到这一点,但只计算每个子集中最高 x 值的平均值。因此,如果我们在此示例中将 x 设为 2,则子集 ay、az 和 bz 的平均值不会改变,因为它们总共只有两个条目(因此顶部 x 条目是子集的整个数据集)。但是 by 包含三个条目,因此我们希望返回最高两个值(2 和 3)的平均值,以便输出表看起来像

A B value  
a y   1.5  
b y   2.5  
a z   2.5  
b z   2.0  

【问题讨论】:

    标签: r subset mean


    【解决方案1】:

    我觉得用aggregate的公式界面比较方便,如下:

    您的原始版本:

    aggregate(value~A+B, data=df, FUN = mean)
      A B value
    1 a y   1.5
    2 b y   2.0
    3 a z   2.5
    4 b z   2.0
    

    您可以通过使用计算排序值尾部平均值的匿名函数来获得所需的版本:

    aggregate(value~A+B, data=df, FUN = function(x)mean(tail(sort(x), 2)))
      A B value
    1 a y   1.5
    2 b y   2.5
    3 a z   2.5
    4 b z   2.0
    

    【讨论】:

    • 简单而整洁,加上喜欢tail() 的用法虽然decreasing = TRUEsort() 将允许head() 这可能很清楚grep 代码的意图(或者你可以使用[1:2] )
    【解决方案2】:

    到同一事物的版本:

    lapply(split(df, list(df$A, df$B)),
           function(x) mean(x[order(x$value, decreasing = TRUE), ][1:2, "value"]))
    

    sapply(split(df, list(df$A, df$B)),
           function(x) mean(x[order(x$value, decreasing = TRUE), ][1:2, "value"]))
    

    给出想要的结果:

    > lapply(split(df, list(df$A, df$B),
    +        function(x) mean(x[order(x$value, decreasing = TRUE), ][1:2, "value"]))
    $a.y
    [1] 1.5
    
    $b.y
    [1] 2.5
    
    $a.z
    [1] 2.5
    
    $b.z
    [1] 2
    
    > sapply(split(df, list(df$A, df$B)),
    +        function(x) mean(x[order(x$value, decreasing = TRUE), ][1:2, "value"]))
    a.y b.y a.z b.z 
    1.5 2.5 2.5 2.0
    

    在实际应用程序中,您可能希望将匿名函数设为适当的函数,并使其在每个子集中少于 2 行的情况下保持稳健。这留给读者作为练习。

    我展示的匿名函数(或一个非常相似的函数)可以很容易地与 aggregate() 一起使用:

    aggregate(value ~ A + B, data = df,
              FUN = function(x) mean(x[order(x, decreasing = TRUE)][1:2]))
    

    例如:

    > aggregate(value ~ A + B, data = df,
    +           FUN = function(x) mean(x[order(x, decreasing = TRUE)][1:2]))
      A B value
    1 a y   1.5
    2 b y   2.5
    3 a z   2.5
    4 b z   2.0
    

    但我是老派,经常手工做这些事情。

    【讨论】:

    • 编辑解决了order()默认按升序排序并且OP想要前2名的问题,因此添加了decreasing = TRUE部分。
    【解决方案3】:

    这有帮助吗?

    x <- 2
    with(df, aggregate(df, by = list(A, B), FUN = function(x)
                                                     mean(x[1:x])))
    

    【讨论】:

    • 不处理订单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 2021-12-05
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多