2017-06-06 59 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