在R中,我有两个包含列表列的数据框
d1 <- data.table(
group_id1=1:4
)
d1$Cat_grouped <- list(letters[1:2],letters[3:2],letters[3:6],letters[11:12] )
和
d_grouped <- data.table(
group_id2=1:4
)
d_grouped$Cat_grouped <- list(letters[1:5],letters[6:10],letters[1:2],letters[1] )
我想根据d1$Cat_grouped
d_grouped$Cat_grouped
中的向量合并这两个data.tables
更确切地说,可能有两个匹配标准:
a)d1$Cat_grouped
的每个向量的所有元素必须位于d_grouped$Cat_grouped
导致以下匹配:
result_a <- data.table(
group_id1=c(1,2)
group_id2=c(1,1)
)
b)d1$Cat_grouped
每个向量中至少有一个元素必须位于d_grouped$Cat_grouped
导致以下匹配:
result_b <- data.table(
group_id1=c(1,2,3,3),
group_id2=c(1,1,1,2)
)
我如何实施a)或b)?最好采用data.table方式。
EDIT1:添加了a)和b)的预期结果
EDIT2:向d_grouped添加了更多组,因此分组变量重叠。这打破了一些建议的解决方案
答案 0 :(得分:4)
所以我认为长形态更好,虽然我的答案感觉有点迂回。我敢打赌,数据表更加时尚的人可以用更少的步骤做到这一点,但这就是我所拥有的:
首先,让我们解压缩示例数据中的向量:
d1_long <- d1[, list(cat=unlist(Cat_grouped)), group_id1]
d_grouped_long <- d_grouped[, list(cat=unlist(Cat_grouped)), group_id2]
现在,我们可以合并各个元素:
result_b <- merge(d1_long, d_grouped_long, by='cat')
根据我们的例子,您似乎并不需要知道哪些元素是比赛的一部分...
result_b[, cat := NULL]
最后,我的答案有重复的group_id对,因为它为每个成对匹配获得了一个连接,而不仅仅是向量级匹配。所以我们可以将它们独一无二。
result_b <- unique(result_b)
这是我的结果:
group_id.1 group_id.2
1: 1 1
2: 2 1
3: 3 1
4: 3 2
我们可以使用b作为a的中间步骤,因为任何共同的元素都是所有元素共同的子集。
让我们合并原始表格以查看候选者在子向量和向量方面的含义
result_a <- merge(result_b, d1, by = 'group_id1')
result_a <- merge(result_a, d_grouped, by = 'group_id2')
现在,如果Cat_grouped.x的长度与Cat_grouped.x的TRUE数量匹配,%Cat_grouped.y为%,那就是宾果游戏。
我尝试了一些简洁的方法,但是在数据表中列出的奇怪之处击败了最明显的尝试。这似乎有效:
让我们添加row
列来操作by
result_a[, row := 1:.N]
现在让我们了解比赛的长度和数量......
result_a[, x.length := length(Cat_grouped.x[[1]]), row]
result_a[, matches := sum(Cat_grouped.x[[1]] %in% Cat_grouped.y[[1]]), row]
并过滤到只有长度和匹配相同的行
result_a <- result_a[x.length==matches]
答案 1 :(得分:2)
另一种方式:
交叉连接以获取所有组ID:
Y = Y[d1, on='group_id1'][d_grouped, on='group_id2']
# group_id1 group_id2 Cat_grouped i.Cat_grouped
# 1: 1 1 a,b a,b,c,d,e
# 2: 2 1 c,b a,b,c,d,e
# 3: 3 1 c,d,e,f a,b,c,d,e
# 4: 4 1 k,l a,b,c,d,e
# 5: 1 2 a,b f,g,h,i,j
# 6: 2 2 c,b f,g,h,i,j
# 7: 3 2 c,d,e,f f,g,h,i,j
# 8: 4 2 k,l f,g,h,i,j
然后在向量中合并:
mapply
现在您可以使用Y[mapply(function(u,v) all(u %in% v), Cat_grouped, i.Cat_grouped), 1:2]
# group_id1 group_id2
# 1: 1 1
# 2: 2 1
Y[mapply(function(u,v) length(intersect(u,v)) > 0, Cat_grouped, i.Cat_grouped), 1:2]
# group_id1 group_id2
# 1: 1 1
# 2: 2 1
# 3: 3 1
# 4: 3 2
来过滤您喜欢的内容:
from pysal.cg.kdtree import KDTree
def construct_tree(s):
data_geopoints = [tuple(x) for x in s[['longitude','latitude']].to_records(index=False)]
tree = KDTree(data_geopoints, distance_metric='Arc', radius=pysal.cg.RADIUS_EARTH_KM)
return tree
def get_neighbors(s,tree):
indices = tree.query_ball_point(s, 1)
return indices
#Constructing the tree for search
tree = construct_tree(data)
#Finding the nearest neighbours within 1KM
data['neighborhood'] = data['lat_long'].apply(lambda row: get_neighbors(row,tree))
答案 2 :(得分:2)
这个答案集中在问题的 a)部分。
它遵循Harland's approach但是出于性能原因试图更好地利用data.table
成语,因为OP已经提到他的生产数据可能包含数百万的观察结果。
library(data.table)
d1 <- data.table(
group_id1 = 1:4,
Cat_grouped = list(letters[1:2], letters[3:2], letters[3:6], letters[11:12]))
d_grouped <- data.table(
group_id2 = 1:2,
Cat_grouped = list(letters[1:5], letters[6:10]))
grp_cols <- c("group_id1", "group_id2")
unique(d1[, .(unlist(Cat_grouped), lengths(Cat_grouped)), by = group_id1][
d_grouped[, unlist(Cat_grouped), by = group_id2], on = "V1", nomatch = 0L][
, .(V2, .N), by = grp_cols][V2 == N, ..grp_cols])
group_id1 group_id2
1: 1 1
2: 2 1
在将d1
和d_grouped
的列表元素扩展为长格式时,使用d1
函数确定lengths()
的列表元素数。 lengths()
(注意与length()
的区别)得到列表中每个元素的长度,并在R 3.2.0中引入。
在内连接(注意nomatch = 0L
参数)之后,对.N
的每个组合计算结果集中的行数(使用specal符号grp_cols
)。只考虑那些行,结果集中的计数与列表的原始长度匹配。最后,返回grp_cols
的唯一组合。
结果b)可以通过省略计数来从上述解决方案中得出:
unique(d1[, unlist(Cat_grouped), by = group_id1][
d_grouped[, unlist(Cat_grouped), by = group_id2], on = "V1", nomatch = 0L][
, c("group_id1", "group_id2")])
group_id1 group_id2 1: 1 1 2: 2 1 3: 3 1 4: 3 2