【问题标题】:How to find the means of consecutive numbers in a column given consecutive string of another column in r如何在给定r中另一列的连续字符串的列中找到连续数字的均值
【发布时间】:2016-07-05 13:30:38
【问题描述】:

我有一个与此类似的数据集:

head(df,20)
   mmpd tot
1     0   0
2    mm   0
3    mm   1
4     0   0
5     0   0
6    mm   0
7    mm   1
8    mm   3
9    mm   1
10    0   0
11    0   0
12    0   0
13    0   0
14   mm   0
15   mm   0
16    0   0
17    0   0
18   mm   4
19   mm   1
20   mm   0

当 df$tot 对应于 df$mmpd 中的一串 mm 时,我想得到它的平均值。因此,对于示例数据集,我想获得以下数字字符串:0.5、1.25、0、1.667。 df$mmpd 将始终是 mm > 1 或 0 的字符串,并且该列可以以 0 或 mm 字符串开头。

有没有办法在没有 for 循环的情况下做到这一点?

【问题讨论】:

    标签: r mean


    【解决方案1】:

    使用data.table

    library(data.table) # v 1.9.5+
    setDT(df)[,.(my=mean(tot)), by=.(indx=rleid(mmpd),mmpd)][,indx:=NULL][mmpd=='mm']
       mmpd       my
    #1:   mm 0.500000
    #2:   mm 1.250000
    #3:   mm 0.000000
    #4:   mm 1.666667
    

    显然,有很多方法可以做到这一点(参见r search along a vector and calculate the mean)。 data.table 方法是最快的并且在这里适应了。

    注意:rleid 可以在data.table 语法之外使用。这将更像“传统”R 语法并产生相同的结果。

    subset(aggregate(tot ~ indx + mmpd, 
              data=cbind(df,indx=rleid(df$mmpd)),
              FUN=mean),mmpd=="mm")
    

    不同生成rleid方式的速度比较(myrleid 来自@JasonAizkalns 的回答)。

    > set.seed(1); x<-sample(1:2,100000,replace=T); 
      microbenchmark(rleid(x),
                     myrleid2=cumsum(c(1,diff(x)!=0)),
                     myrleid(x))
    Unit: milliseconds
           expr      min       lq     mean   median       uq       max neval cld
       rleid(x) 1.422263 1.500873 1.586482 1.571315 1.662982  1.938254   100 a  
       myrleid2 3.860290 3.908308 4.369646 3.962497 4.177673 15.674611   100  b 
     myrleid(x) 7.282868 7.386515 7.753515 7.444008 7.654126 18.864898   100   c
    

    对于非数字 x:

    >  set.seed(1); x<-sample(c('a','b'),100000,replace=T); 
    >  microbenchmark(rleid(x),myrleid2=cumsum(c(1,diff(as.numeric(factor(x)))!=0)),myrleid(x))
    Unit: milliseconds
           expr       min        lq      mean    median       uq       max neval cld
       rleid(x)  1.465466  1.571662  1.684568  1.606614  1.66080  2.900983   100 a
       myrleid2  8.705447  9.276787 12.393393  9.907403 10.35032 61.080374   100  b
     myrleid(x) 11.970271 13.176144 18.779256 13.790767 14.09626 69.845587   100   c
    

    【讨论】:

    • 哦,不知道rleid,这是一个非常方便的功能。
    • 是的,它非常有用,因为它比rle 快得多。
    • rleid() 也设计用于处理多个列。例如,rleid(a,b,c)
    • 哇@fishtank 非常优雅。我也不知道rleid 函数@Arun
    【解决方案2】:

    使用这些数据:

    df = structure(list(mmpd = structure(c(1L, 2L, 2L, 1L, 1L, 2L, 2L, 
    2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 2L), .Label = c("0", 
    "mm"), class = "factor"), tot = c(0L, 0L, 1L, 0L, 0L, 0L, 1L, 
    3L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 4L, 1L, 0L)), .Names = c("mmpd", 
    "tot"), class = "data.frame", row.names = c("1", "2", "3", "4", 
    "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", 
    "16", "17", "18", "19", "20"))
    

    添加分组列(只需要对“mm”值有效)

    df$group = cumsum(df$mmpd != "mm")
    

    对于数据的“mm”子集,取分组均值:

    tapply(df$tot[df$mmpd == "mm"], INDEX = group[df$mmpd == "mm"], FUN = mean)
    #        1        3        7        9 
    # 0.500000 1.250000 0.000000 1.666667
    

    组索引没有多大意义(它们增加了中间零的数量减一),但无论如何您都没有要求它们,结果是正确的;)

    【讨论】:

      【解决方案3】:

      使用基础R -- 滚动你自己的relid() 函数,灵感来自data.table 包中的函数:

      myrleid <- function(x) {
        x <- rle(x)$lengths
        rep(seq_along(x), times=x)
      }
      

      然后使用这个函数创建一个group变量并使用aggregate

      df$group <- myrleid(df$mmpd)
      aggregate(data = subset(df, mmpd == "mm"), tot ~ group, mean)
      
      #   group      tot
      # 1     2 0.500000
      # 2     4 1.250000
      # 3     6 0.000000
      # 4     8 1.666667
      

      【讨论】:

      • 使用cumsum(c(1,diff(x)!=0))定义myrleid更快。
      • @fishtank 很酷,感谢您的基准测试,但是在我们有一个非数字列的情况下,这将如何工作?
      • 它仍然可以使用as.numeric(factor(x))。测试它仍然更快。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-15
      • 2016-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多