2017-06-06 74 views
2

我正在使用python模拟运行实验,并且需要创建一个输入案例列表。在Python中使用默认值进行多列表迭代

每种情况下从参数列表的列表采取一个实例,例如:

heights = [100,110,120] 
alphas = [0.1,0.01,0.001] 
C = [0.1,0.2,0.5,0.9] 
B = [1,2] 

和列表的列表是:

params = [heights,alphas,C,B] 

原始量较大(〜30× ),所以直接处理每个列表效率不高。

最终,每个输入的情况下是从每个类别一个参数的元组/ namedtuple /字典,例如:

instance = {'height':100, 'alpha':0.1,'C:0.1, 'B':1} 

我想迭代以创建实例的列表的参数空间 - 但这里是渔获

,而不是使所有的人,每次我想要遍历所有选项每个参数的笛卡尔积,而类的其余部分设置为默认值(第一批) 。例如:

params = [[1,2,3],[4,5][7,8]] 

预期实例集合(无重复)是:

[(1,4,7-),(2,4,7),(3,4, 7),(1,5,7)(1,4,8)]

其中是第一索引的默认值,是第二索引的和缺省被第三个的默认值。

制作一个笛卡尔乘积是很容易与itertools

from itertools import product 
params = [[1,2,3],[4,5],[7,8]] 
list(product(*params)) 

[(1,4,7),(1,4,8),(1,5,7),(1 (2,5,8),(2,4,7),(2,4,7),(2,4,8),(2,5,7),(2,5,8),(3,4,7),(3,4 ,8),(3,5,7),(3,5,8)]

然后我可以筛选出不必要的情况,但它听起来不够生成他们在第一个地方。有什么优雅的方式来构建这个迭代?

回答

1
params = [[1, 2, 3], [4, 5], [7, 8]] 
default = [par[0] for par in params] 
instances = set() 

for ii, pp in enumerate(params): 
    for value in pp: 
     new_instance = default[:ii] + [value] + default[ii + 1:] 
     instances.add(tuple(new_instance)) 
1

我建议另一种方法。使用openTURNS。这个python库已经很完善了,并且有一些类定义了一个实验设计,据说这个设计在空间填充方面有很好的性能。

这里看一个例子LowDiscrepancySequence。使用这种设计,您将能够进行统计分析,创建模型等。我与他们没有关系,但他们在该领域是众所周知的。

但是,如果你准备好了,你可以坚持你的方法。为了使它更Python我将建立一个生成器表达式或列表理解直接:

((I,J,K)为I,J,K,在产品(...))

0

注意,在最终的列表中的每个元组的第二和第三实例,是只从第二和初始阵列

a, *b = params 
# a = [1, 2, 3] 
# b = [[4, 5], [7, 8]] 

的第三行的产品制作一个产品的所有元素的b

import itertools 

b = [x for x in itertools.product(*b)] 
# b = [(4, 7), (4, 8), (5, 7), (5, 8)] 

现在做的一个产品,

c = [(a, b, c) for a, (b, c) in itertools.product(a, b)] 

# c = [(1, 4, 7), (1, 4, 8), (1, 5, 7), (1, 5, 8), (2, 4, 7), (2, 4, 8), (2, 5, 7), (2, 5, 8), (3, 4, 7), (3, 4, 8), (3, 5, 7), (3, 5, 8)] 

总体缩短了B的所有值:

import itertools 

params = [[1,2,3], 
      [4,5], 
      [7,8]] 

a, *b = params 
f = itertools.product 

c = [(a, b ,c) for a, (b, c) in f(a, f(*b))] 
+0

是不是仍然首先创建的所有实例,然后过滤他们出去? – Dimgold

+1

我看着你写的最后一个盒子,认为这是你想要的输出,哦,哈哈。 – Rosh