如何根据属于另一个向量的一个向量合并向量列表?

时间:2017-07-31 03:16:54

标签: r list merge data.table

在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添加了更多组,因此分组变量重叠。这打破了一些建议的解决方案

3 个答案:

答案 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]))

结果a)

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

解释

在将d1d_grouped的列表元素扩展为长格式时,使用d1函数确定lengths()的列表元素数。 lengths()(注意与length()的区别)得到列表中每个元素的长度,并在R 3.2.0中引入。

在内连接(注意nomatch = 0L参数)之后,对.N的每个组合计算结果集中的行数(使用specal符号grp_cols)。只考虑那些行,结果集中的计数与列表的原始长度匹配。最后,返回grp_cols的唯一组合。

结果b)

结果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