我有一个数据集,其中包含客户和帐户,其中客户可以拥有多个帐户。数据集在每个帐户上都有几个“标志”。
我试图在每个客户的这些标志上计算'唯一'点击次数,即如果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
列,每个客户只有一行,我希望拥有与客户帐户相同的行数。
答案 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