根据键计算多行中的标志

Count flags across multiple rows depending on key

我有一个由客户和帐户组成的数据集,其中一个客户可以有多个帐户。该数据集在每个帐户上有几个 'flags'。

我正在尝试计算每个客户对这些标志的 'unique' 次点击,即如果 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 列求和,为每个客户提供一行,我希望拥有与客户帐户相同的行数。

我想到的一种方法是 colSum 每个 cust 并检查哪些大于 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 的值。

这是一种使用 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

使用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 小插图)用这些值 更新原始 table。


其中 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')

我在阅读了 Roman 的 post 后能够回答我自己的问题,我做了类似的事情,其中​​ 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 的解决方案快一点,但我不确定它是否是最佳解决方案。谢谢大家的意见,这帮了大忙!

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

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