我有一个有两列的表:
aaa bbb
a1 b2
a1 b6
a1 b2
a1 b2
a1 b5
a1 b6
a2 b2
a2 b2
a2 b2
a2 b6
a2 b6
a2 b5
Run Code Online (Sandbox Code Playgroud)
这些列都不应被视为已排序.我想要做的是找到最优雅的方式来计算aaa,bbb给出aaa的多少组合,然后采用最流行的组合(100说)并减去所有剩余组合(10说)的总和,这是预计会比受欢迎的人少.输出应该是元素aaa以及这两个数字之间的差异.例如,上面的输出应该如下:
var cnt
a1 0
a2 0
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
这是使用的一种方式 data.table
require(data.table)
DT <- data.table(df) # where df is your data.frame
setkey(DT[, .N, by=list(aaa, bbb)], aaa, N)[, list(cnt =
N[.N]-sum(N[-.N])), by=aaa]
aaa cnt
1: a1 0
2: a2 0
Run Code Online (Sandbox Code Playgroud)
我们的想法是首先得到每个组合的计数.这通过以下方式实现:
OUT <- DT[, .N, by = list(aaa, bbb)]
# which gives you:
aaa bbb N
1: a1 b2 3
2: a1 b6 2
3: a1 b5 1
4: a2 b2 3
5: a2 b6 2
6: a2 b5 1
Run Code Online (Sandbox Code Playgroud)
在此之后,我们setkey在列aaa和N上,默认情况下会对它们进行排序(这是设置密钥的唯一目的).
OUT <- setkey(DT[, .N, by=list(aaa, bbb)], aaa, N)
# which gives you:
aaa bbb N
1: a1 b5 1
2: a1 b6 2
3: a1 b2 3
4: a2 b5 1
5: a2 b6 2
6: a2 b2 3
Run Code Online (Sandbox Code Playgroud)
现在它已经排序了,我们可以按列aaa拆分/分组并获取最终的cnt列.由于N已排序,因此最大值将始终为最后一个.因此,我们取最后一个值,N[.N]并N[-.N]在按列aaa分组时用剩余值的总和减去它.这是最后一部分:
OUT[, list(cnt = N[.N]-sum(N[-.N])), by=aaa]
Run Code Online (Sandbox Code Playgroud)
完成.您可以将所有这些命令链接在一起(就像我已经完成的那样),或者您可以将它们分成不同的步骤(正如我为解释所示).这是你的选择.
注意:如果aaa,bbb的组合超过1,则会产生负值.