是否有一种快速计算多个向量中出现的值出现在多个其他向量中的次数?这是一个例子:
library(data.table)
names<-c(rep('apple',4),rep('banana',3),rep('cantalope',2),'date')
set.seed(38291)
v1<-data.table(municipality=rep('A',6),village=rep('1',6),
last=sample(names,6,replace=TRUE),
middle=sample(names,6,replace=TRUE),id=c(1:6))
v2<-data.table(municipality=rep('A',4),village=rep('2',4),
last=sample(names,4,replace=TRUE),
middle=sample(names,4,replace=TRUE),id=c(7:10))
v1
# municipality village last middle id
# 1: A 1 banana cantalope 1
# 2: A 1 cantalope banana 2
# 3: A 1 cantalope cantalope 3
# 4: A 1 apple apple 4
# 5: A 1 banana apple 5
# 6: A 1 apple apple 6
v2
# municipality village last middle id
# 1: A 2 date cantalope 7
# 2: A 2 apple date 8
# 3: A 2 cantalope banana 9
# 4: A 2 apple cantalope 10
DT = rbind(v1, v2)
Run Code Online (Sandbox Code Playgroud)
我想计算村庄1和村庄2中个人之间的家庭关系数量.跨村庄家庭关系的定义是个人的最后或中间名称("最后"或"中间")是否与某人的姓或中名相符在另一个村庄.在这个例子中,居住在村庄1中的id = 1的个体在村庄2中具有三个家庭成员(具有ids 7,9和10的家庭成员),因为他与他们共享至少一个姓名.然后,我想创建一个村庄的二元数据集,其中村庄之间的关系由这些村庄之间的家庭关系的数量来定义.因此,在此示例中,最终数据集将如下所示:
dyads<-data.table(v1='1',v2='2',ties=3+3+3+2+3+2)
dyads
v1 v2 ties
1: 1 2 16
Run Code Online (Sandbox Code Playgroud)
有没有一种有效的方法来计算这个'关系'数字?我写了一个低效的for循环来做这件事,但我有一个庞大的数据集(在40000个村庄中约有5000万人).
受Frank的回答启发的更新:
meltDT =
#use unique to eliminate last+middle duplication
unique(melt(DT, measure.vars = c('last', 'middle'),
id.vars = c('village', 'id'), value.name = 'name'),
by = c('village', 'id', 'name'))
#framework of output -- one row for each pair of villages
out.dt = with(DT, CJ(village, village, unique = TRUE))[V2 > V1]
setkey(meltDT, village)
setindex(meltDT, name)
#set indices to facilitate merges on names
out.dt[ , {
ties :=
#unique here eliminates matching on both last & middle
uniqueN(meltDT[.(.BY$V1)][meltDT[.(.BY$V2)], on = 'name',
allow.cartesian = TRUE, nomatch = 0L],
by = c('id', 'i.id'))
}, by = .(V1, V2)]
out.dt
# V1 V2 ties
# 1: 1 2 16
Run Code Online (Sandbox Code Playgroud)