根据键

时间:2015-11-18 21:21:23

标签: r unique counting

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

我试图在每个客户的这些标志上计算'唯一'点击次数,即如果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列,每个客户只有一行,我希望拥有与客户帐户相同的行数。

5 个答案:

答案 0 :(得分:3)

使用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晕影)。

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

答案 1 :(得分:1)

我想到的一种方法是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的值。

答案 2 :(得分:1)

以下是使用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

答案 3 :(得分:0)

在阅读了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的解决方案快一点,但我不确定它是否是最佳解决方案。谢谢大家的帮助,这对你有所帮助!

答案 4 :(得分:0)

未充分利用的rowsum也可以使用:

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