获取不同组的相同人数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了获取不同组的相同人数相关的知识,希望对你有一定的参考价值。
我有一个包含个人(ID)的数据集,可以是多个组的一部分。
例:
library(data.table)
DT <- data.table(
ID = rep(1:5, c(3:1, 2:3)),
Group = c("A", "B", "C", "B",
"C", "A", "A", "C",
"A", "B", "C")
)
DT
# ID Group
# 1: 1 A
# 2: 1 B
# 3: 1 C
# 4: 2 B
# 5: 2 C
# 6: 3 A
# 7: 4 A
# 8: 4 C
# 9: 5 A
# 10: 5 B
# 11: 5 C
我想知道两组相同个体的总和。
结果应如下所示:
Group.1 Group.2 Sum
A B 2
A C 3
B C 3
Sum表示两组共有的人数。
答案
这是我的版本:
# size-1 IDs can't contribute; skip
DT[ , if (.N > 1)
# simplify = FALSE returns a list;
# transpose turns the 3-length list of 2-length vectors
# into a length-2 list of 3-length vectors (efficiently)
transpose(combn(Group, 2L, simplify = FALSE)), by = ID
][ , .(Sum = .N), keyby = .(Group.1 = V1, Group.2 = V2)]
随着输出:
# Group.1 Group.2 Sum
# 1: A B 2
# 2: A C 3
# 3: B C 3
另一答案
从版本1.9.8(2016年11月25日CRAN)开始,data.table
已经获得了进行非equi连接的能力。因此,可以使用自我非等连接:
library(data.table) # v1.9.8+
setDT(DT)[, Group:= factor(Group)]
DT[DT, on = .(ID, Group < Group), nomatch = 0L, .(ID, x.Group, i.Group)][
, .N, by = .(x.Group, i.Group)]
x.Group i.Group N 1: A B 2 2: A C 3 3: B C 3
Explanantion
ID, Group < Group
上的非equi连接是data.table
的combn()
版本(但是按群体应用):
DT[DT, on = .(ID, Group < Group), nomatch = 0L, .(ID, x.Group, i.Group)]
ID x.Group i.Group 1: 1 A B 2: 1 A C 3: 1 B C 4: 2 B C 5: 4 A C 6: 5 A B 7: 5 A C 8: 5 B C
另一答案
我们使用相同的数据集on
'ID'自行连接,将“Group”列不同的行子集,获得nrows(.N
),按“Group”列分组,对“Group.1”和“Group”进行排序.2'使用pmin/pmax
逐行,并获得'N'的unique
值。
library(data.table)#v1.9.6+
DT[DT, on='ID', allow.cartesian=TRUE][Group!=i.Group, .N ,.(Group, i.Group)][,
list(Sum=unique(N)) ,.(Group.1=pmin(Group, i.Group), Group.2=pmax(Group, i.Group))]
# Group.1 Group.2 Sum
#1: A B 2
#2: A C 3
#3: B C 3
或者正如@MichaelChirico和@Frank的评论中提到的,我们可以将'Group'转换为factor
类,基于as.integer(Group) < as.integer(i.Group)
将行子集化,按'Group','i.Group'分组并得到nrow(.N
)
DT[, Group:= factor(Group)]
DT[DT, on='ID', allow.cartesian=TRUE][as.integer(Group) < as.integer(i.Group), .N,
by = .(Group.1= Group, Group.2= i.Group)]
另一答案
上面的好答案。如果您或其他人对此感兴趣,请使用dplyr
作为替代方案。
library(dplyr)
cmb = combn(unique(dt$Group),2)
data.frame(g1 = cmb[1,],
g2 = cmb[2,]) %>%
group_by(g1,g2) %>%
summarise(l=length(intersect(DT[DT$Group==g1,]$ID,
DT[DT$Group==g2,]$ID)))
# g1 g2 l
# (fctr) (fctr) (int)
# 1 A B 2
# 2 A C 3
# 3 B C 3
另一答案
又一个解决方案(基础R):
tmp <- split(DT, DT[, 'Group'])
ans <- apply(combn(LETTERS[1 : 3], 2), 2, FUN = function(ind){
out <- length(intersect(tmp[[ind[1]]][, 1], tmp[[ind[2]]][, 1]))
c(group1 = ind[1], group2 = ind[2], sum_ = out)
}
)
data.frame(t(ans))
# group1 group2 sum_
#1 A B 2
#2 A C 3
#3 B C 3
首先将数据拆分成组列表,然后对于两个组的每个唯一成对组合,使用length(intersect(...
查看它们共有多少个共同主题。
以上是关于获取不同组的相同人数的主要内容,如果未能解决你的问题,请参考以下文章