我正在尝试解决一个问题,即我刚刚找到的新路线(卡车),我检查该路线是否已经是我之前路线的一部分。例如,假设我存储的路由在数据表routelist
中,node_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])
}
答案 0 :(得分:2)
这里有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()
返回item
中node_list
元素的位置(如果未找到,则返回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
按要求。
答案 1 :(得分:1)
来自dplyr
和tidyr
的解决方案。
如果订单不重要,可以使用以下方法。通过检查id
中的routelist2
列,很明显,ID 3是具有正确条件的列。
# 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
答案 2 :(得分:0)
使用循环(不优雅)可以在正文中使用以下检查。它确实考虑到了顺序:
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])
}
}