繁体   English   中英

过滤列表类型data.table列中的数组

[英]Filtering of an array in a list type data.table column

我正在尝试解决一个问题,即我刚刚找到的新路线(卡车),我检查该路线是否已经是我之前路线的一部分。 例如,假设我存储的路由在数据表routelistnode_list指的是存储的路由。 我想检查路由(5,6,7,8)所属的行。

library(data.table)
routelist=data.table(id=c(1:3),node_list=list(c(1:6),c(4:7),c(1:10)))
item<-c(5:8)
routelist[sum(item%in%unlist(packlist$node_list))==length(item)]

对于上面的检查,返回所有三行,但是只返回第三行。 我可以通过以下for循环来做到这一点,但它并不快,并没有考虑到顺序(并且应该有一种方法以更好的方式做到这一点)。 item中节点的顺序很重要,列表不需要是连续的,即项目可以是c(5,7,8) ,应该在第3行返回,而c(5,8,7)不应该返回。

for(i in 1:3)
{
  if(sum(item%in%unlist(packlist[i]$node_list))==length(item))
    print(routelist[i])
}

OP的data.table方法存在两个问题。

缺少by条款

routelist = data.table(id = 1:3, node_list = list(1:6, 4:7, 1:10))
item <- 5:8
routelist[, sum(item %in% unlist(node_list)) == length(item)] 

返回单个TRUE值,因为

routelist[, unlist(node_list)]

返回一个向量

  [1] 1 2 3 4 5 6 4 5 6 7 1 2 3 4 5 6 7 8 9 10 

如果按id分组,我们会得到所需的结果:

routelist[, sum(item %in% unlist(node_list)) == length(item), by = id]
  id V1 1: 1 FALSE 2: 2 FALSE 3: 3 TRUE 

要么

routelist[routelist[, sum(item %in% unlist(node_list)) == length(item), by = id]$V1]
  id node_list 1: 3 1,2,3,4,5,6, 

%in%仅检查外观但不检查订单

表达式sum(item %in% unlist(node_list)) == length(item)不处理item中元素的顺序。

由于元素的顺序很重要,因此表达式

isTRUE(all(diff(match(item, unlist(node_list))) > 0))

说明了订单。 match()返回node_listitem元素的位置(如果未找到,则返回NA )。 如果item的订单与node_list的订单相同,则所有位置差异必须为正。 isTRUE()来覆盖NA情况。

从而,

item <- c(5, 7, 8)
routelist[routelist[, isTRUE(all(diff(match(item, unlist(node_list))) > 0)), by = id]$V1]

回报

  id node_list 1: 3 1,2,3,4,5,6, 

尽管存在差距

item <- c(5, 8, 7)
routelist[routelist[, isTRUE(all(diff(match(item, unlist(node_list))) > 0)), by = id]$V1]

回报

 Empty data.table (0 rows) of 2 cols: id,node_list 

由于错误的订单请求。

来自dplyrtidyr解决方案。

如果订单不重要,可以使用以下方法。 通过检查routelist2id列,很明显id 3是具有正确条件的id。

# Create example dataset
library(data.table)
routelist=data.table(id=c(1:3),node_list=list(c(1:6),c(4:7),c(1:10)))
item<-c(5:8)

# Solution 1
library(dplyr)
library(tidyr)

routelist2 <- routelist %>%
  unnest() %>%
  group_by(id) %>%
  filter(all(item %in% node_list)) %>%
  nest()

routelist2 
# A tibble: 1 x 2
     id              data
  <int>            <list>
1     3 <tibble [10 x 1]>

如果订单很重要,我们可能必须将路径编号转换为字符串,而不是找到正确的字符串模式。 以下方法应该有效。

# Solution 2
item_str <- toString(item)

routelist3 <- routelist %>%
  rowwise() %>%
  mutate(node_list = toString(node_list)) %>%
  filter(grepl(item_str, node_list)) %>%
  ungroup()

routelist3
# A tibble: 1 x 2
     id                     node_list
  <int>                         <chr>
1     3 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

更新

以下考虑的情况时,在节点item2是不完整的。

# Solution 3
library(dplyr)
library(tidyr)

item2 <- c(5, 7, 8)

routelist4 <- routelist %>%
  unnest() %>%
  group_by(id) %>%
  filter(all(item2 %in% node_list)) %>%
  filter(node_list %in% item2) %>%
  summarise(node_list = toString(node_list)) %>%
  filter(node_list == toString(item2))
routelist4
# A tibble: 1 x 2
     id node_list
  <int>     <chr>
1     3   5, 7, 8

使用循环(不优雅)可以在正文中使用以下检查。 它确实考虑到了顺序:

library(data.table)
routelist=data.table(id=c(1:3),node_list=list(c(1:6),c(4:7),c(1:10)))
item<-c(5,8,7)

for(i in 1:nrow(routelist))
{
  if(identical(intersect(unlist(routelist[i]$node_list),item),item)){
    print(routelist[i])  
  }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM