【问题标题】:Count flags across multiple rows depending on key根据键计算多行中的标志
【发布时间】:2015-11-18 21:21:23
【问题描述】:

我有一个由客户和帐户组成的数据集,其中一个客户可以拥有多个帐户。数据集在每个帐户上都有几个“标志”。

我正在尝试计算每个客户对这些标志的“唯一”点击次数,即如果 3 个帐户有 flag1,我希望这算作 1 次点击,但如果只有一个帐户也有 flag2,我想要这个计为 2。本质上,我想查看每个客户在其所有帐户中点击了多少个标志。

Example Input data frame:
    cust  acct flag1 flag2 flag3
    a     123    0    1      0
    a     456    1    1      0
    b     789    1    1      1
    c     428    0    1      0
    c     247    0    1      0
    c     483    0    1      1
Example Output dataframe:
    cust  acct flag1 flag2 flag3 UniqueSum
    a     123    0    1      0      2
    a     456    1    1      0      2
    b     789    1    1      1      3
    c     428    0    1      0      2
    c     247    0    1      0      2
    c     483    0    1      1      2

我尝试使用以下方法:

fSumData <- ddply(fData, "cust", numcolwise(sum, c(flag1,flag2,flag3))

但是这也将acct 列相加,给每个客户一行我希望与客户拥有帐户的行数相同。

【问题讨论】:

    标签: r unique counting


    【解决方案1】:

    使用data.table

    require(data.table) # v1.9.6
    dt[, un := sum(sapply(.SD, max)), by = cust, .SDcols = flag1:flag3]
    

    我们按cust 分组,并在每个组的子数据 上为flag1, flag2, flag3 列(使用.SD.SDcols 实现)提取每列的max,然后总结起来将给出1 的总数。

    我们使用LHS := RHS 表示法通过引用使用这些值更新原始表(请参阅Reference Semantics vignette)。


    dt 在哪里:

    dt = fread('cust  acct flag1 flag2 flag3
    a     123    0    1      0
    a     456    1    1      0
    b     789    1    1      1
    c     428    0    1      0
    c     247    0    1      0
    c     483    0    1      1')
    

    【讨论】:

      【解决方案2】:

      我想到的一种方法是为每个cust colSum 并检查哪些大于0。例如,

      > tab
        cust acct flag1 flag2 flag3
      1    a  123     0     1     0
      2    a  456     1     1     0
      3    b  789     1     1     1
      4    c  428     0     1     0
      5    c  247     0     1     0
      6    c  483     0     1     1
      > uniqueSums <- sapply(tab$cust, function(cust) length(which(colSums(tab[tab$cust == cust,3:5]) > 0)))
      > cbind(tab, uniqueSums = uniqueSums)
        cust acct flag1 flag2 flag3 uniqueSums
      1    a  123     0     1     0          2
      2    a  456     1     1     0          2
      3    b  789     1     1     1          3
      4    c  428     0     1     0          2
      5    c  247     0     1     0          2
      6    c  483     0     1     1          2
      

      对于cust 的每个值,sapply 中的函数查找行,进行矢量化求和并检查大于 0 的值。

      【讨论】:

      • 这行得通,但确实花了一些时间来运行,我能够通过使用上面提到的 ddply 包然后将 if/else 语句的结果相加,当每个标志中的值 >= 1。我已经用我的解决方案编辑了我的帖子,非常感谢你的帮助!
      • 您可以使用 mclapply 来并行化 sapply
      【解决方案3】:

      这是一种使用library(dplyr)的方法:

      df %>% 
        group_by(cust) %>% 
        summarise_each(funs(max), -acct) %>% 
        mutate(UniqueSum = rowSums(.[-1])) %>% 
        select(-starts_with("flag")) %>% 
        right_join(df, "cust")
      
      #Source: local data frame [6 x 6]
      #
      #    cust UniqueSum  acct flag1 flag2 flag3
      #  (fctr)     (dbl) (int) (int) (int) (int)
      #1      a         2   123     0     1     0
      #2      a         2   456     1     1     0
      #3      b         3   789     1     1     1
      #4      c         2   428     0     1     0
      #5      c         2   247     0     1     0
      #6      c         2   483     0     1     1
      

      【讨论】:

        【解决方案4】:

        阅读 Roman 的帖子后,我能够回答自己的问题,我做了类似的事情,其中​​ f 数据是我的数据集。

        fSumData <- ddply(fData, "cust", numcolwise(sum))
        fSumData$UniqueHits <- ifelse(fSumData$flag1 >= 1;1,0) + ifelse(fSumData$flag2 >= 1;1;0) + ifelse(fSumData$flag3 >= 1;1;0)
        

        在针对我的数据集运行时,我发现这比 Roman 的解决方案要快一些,但不确定它是否是最佳解决方案。感谢大家的投入,这对您有很大帮助!

        【讨论】:

          【解决方案5】:

          未充分利用的rowsum 也可能有用:

          rowSums(rowsum(DF[-(1:2)], DF$cust) > 0)[DF$cust]
          #a a b c c c 
          #2 2 3 2 2 2
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-03-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多