Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R中的高效匹配/查找_R_Performance_Match_Lookup_Memory Efficient - Fatal编程技术网

R中的高效匹配/查找

R中的高效匹配/查找,r,performance,match,lookup,memory-efficient,R,Performance,Match,Lookup,Memory Efficient,从2个对象开始:1个订单属性数据框-订单号、权重和体积,1个列表-订单号组合字符串 attr <- data.frame(Order.No = c(111,222,333), Weight = c(20,75,50), Volume = c(10,30,25)) combn <- list(111, 222, 333, c(111,222), c(111,333), c(222,333), c(111,222,333)) 上面的代码查找单个订单权重和多维数据集,将它们相加,检查以确

从2个对象开始:1个订单属性数据框-订单号、权重和体积,1个列表-订单号组合字符串

attr <- data.frame(Order.No = c(111,222,333), Weight = c(20,75,50), Volume = c(10,30,25))
combn <- list(111, 222, 333, c(111,222), c(111,333), c(222,333), c(111,222,333))
上面的代码查找单个订单权重和多维数据集,将它们相加,检查以确保它们在每个范围限制内,将两个列表合并在一起,并仅将权重和多维数据集都在可接受范围内的列表保留在一起

我目前的解决方案成功地完成了这项任务,但它的生产速度非常慢,无法很好地扩展到数百万条记录。由于要查找11 MM的顺序组合,此过程需要约40分钟才能运行,这是不可接受的

我正在寻找一种更有效的方法,它将大大减少生成相同输出所需的运行时间

# changing names, assigning indices to order list
atdf  = data.frame(Order.No = c(111,222,333), Weight = c(20,75,50), Volume = c(10,30,25))
olist = list(111, 222, 333, c(111,222), c(111,333), c(222,333), c(111,222,333))
olist <- setNames(olist,seq_along(olist))

# defining filtering predicate:

sel_orders = function(os, mins=c(20,10), maxs=c(50,50)) {
    tot = colSums(atdf[match(os, atdf$Order.No), c("Weight","Volume")])
    all(maxs >= tot & tot >= mins)
}

# Filtering orders

olist[sapply(olist, sel_orders)]
# or 
Filter(x = olist, f = sel_orders)
要更改最大值和最小值

olist[ sapply(olist, sel_orders, mins = c(0,0), maxs = c(70,70)) ]

# $`1`
# [1] 111
# 
# $`3`
# [1] 333
# 
# $`5`
# [1] 111 333
要更改最大值和最小值

olist[ sapply(olist, sel_orders, mins = c(0,0), maxs = c(70,70)) ]

# $`1`
# [1] 111
# 
# $`3`
# [1] 333
# 
# $`5`
# [1] 111 333

不知道这会快多少,但这里有一个dplyr/tidyr解决方案

library(dplyr)
library(tidyr)

combination = 
  data_frame(Order.No = combn) %>%
  mutate(combination_ID = 1:n()) %>%
  unnest(Order.No)

acceptable = 
  combination %>%
  left_join(attr) %>%
  group_by(combination_ID) %>%
  summarize(total_weight = sum(Weight),
         total_volume = sum(Volume)) %>%
  filter(total_weight %>% between(20, 50) &
           total_volume %>% between(10, 50) )

不知道这会快多少,但这里有一个dplyr/tidyr解决方案

library(dplyr)
library(tidyr)

combination = 
  data_frame(Order.No = combn) %>%
  mutate(combination_ID = 1:n()) %>%
  unnest(Order.No)

acceptable = 
  combination %>%
  left_join(attr) %>%
  group_by(combination_ID) %>%
  summarize(total_weight = sum(Weight),
         total_volume = sum(Volume)) %>%
  filter(total_weight %>% between(20, 50) &
           total_volume %>% between(10, 50) )

顺便说一句,
combn
attr
是函数名在您的示例中是什么?(示例代码的最后一行)请提供所需的输出可能
库(data.table);图书馆(快配);setDT(melt(combn))[,{tmp@Frank同意。我需要重新审视我的命名约定。我使用了'c'作为两个列表的连接函数。感谢大家的建议。顺便说一句,
combn
attr
是函数名称在您的示例中,
c
是什么?(示例代码的最后一行)请提供所需的输出也许
library(data.table);library(fastmatch);setDT(melt(combn))[,{tmp@Frank同意。我需要重新审视我的命名约定。我使用'c'作为两个列表的连接函数。感谢大家的建议。很好的解决方案,+1!我想出了类似的东西(但在单链接操作中)并在
summary()
调用中添加
Order.No=toString(Order.No)
,以在最终输出中包含初始列表的元素。我将组合框分开,以便可以通过关系访问订单号,例如,
acceptable%>%left\u join(组合)
Nice solution,+1!我提出了类似的解决方案(但在一个单链接操作中),并在
summary()中添加了
Order.No=toString(Order.No)
调用以在最终输出中包含初始列表的元素。我将组合框分开,以便可以通过关系访问订单号,例如,
可接受%>%left\u join(组合)
再次感谢,但这也产生了与我的代码基本相同的运行时间。我从您的方法中学到了一些东西,但我非常感激。是的,我并不惊讶这不会更快。为了真正的加速,我怀疑您需要有人在data.table上发布@akrun的评论/回答。为此,您可能需要发布一个更大的示例,这样就可以进行基准测试,您可能想在问题上加上标记。再次感谢,但这也会产生与我的代码基本相同的运行时间。我从您的方法中学到了一些东西,但我非常感激。是的,我并不奇怪这不会更快。为了真正加快速度,我怀疑您需要有人按照@akrun的评论/回答发布一些东西为了实现这一点,您可能需要发布一个更大的示例,这样就可以进行基准测试。另外(一件小事),您可能需要在问题上加上标签。
library(dplyr)
library(tidyr)

combination = 
  data_frame(Order.No = combn) %>%
  mutate(combination_ID = 1:n()) %>%
  unnest(Order.No)

acceptable = 
  combination %>%
  left_join(attr) %>%
  group_by(combination_ID) %>%
  summarize(total_weight = sum(Weight),
         total_volume = sum(Volume)) %>%
  filter(total_weight %>% between(20, 50) &
           total_volume %>% between(10, 50) )