2016-04-05 97 views
0

所以我很努力使這個代碼更適用於更大的數據集。下面是代碼,我會徹底地再具體解釋:將迭代的值存儲到一個numpy數組 - Python,Numpy

import numpy as np 
np.set_printoptions(threshold='nan') 

tri_nums = [3, 2, 1] 


paths = [1, 3, 4, 5] 

vol_list = [10, 10, 10, 15, 15, 25] 

n = 0 

array_list = [] 

while n <= len(tri_nums): 
    for num in tri_nums: 
     print "assigning volume", vol_list[sum(tri_nums)-len(vol_list)+1] 
     volume_array = np.zeros(shape = (6, 6)) 
     volume_array[paths[num-1],paths[num]] = vol_list[sum(tri_nums)-len(vol_list)+1] 
     array_list.append(volume_array) 
     print paths[num-1], paths[num] 


    tri_nums.pop(0) 
    paths.pop(0) 
    n+=1 
    print paths 
    print tri_nums 


final_array = sum(array_list) 
print array_list 
print final_array 

tri_nums開始: 的tri_nums值將永遠是paths長度的三角形號碼列表。所以paths列表說,[1, 3, 4, 5, 6, 8],將提供tri_nums[5, 4, 3, 2, 1]

tri_nums也與vol_list中的值的數目相關。如您所見,vol_list中有三個1010的數量等於第一個值tri_nums。對於第二個值tri_nums,還有兩個152。這種模式永遠不會改變!另外一個例子是:

paths = [1, 3, 4, 5, 6, 8] 

tri_nums = [5, 4, 3, 2, 1] 

vol_list = [15, 15, 15, 15, 15, 250, 250, 250, 250, 25, 25, 25, 10, 10, 15] 

列表paths(在原始情況下)是由四個「節點」,節點1,3,4和5的每個相鄰節點之間存在一個路徑,即路徑1-3,3-4,4-5。可以看到,volume_array是一個6x6數組,由零組成。 volume_array中要更改的行值對應於每個路徑的第一個值,即1,3,4。列值對應於每條路徑的第二數字,即3,4,5

這裏有棘手的一點!

  1. 對於vol_list一個值加到volume_arraytri_nums的每個值:

    vol_list的值如下所示被分配給前述數組項。該數組中的行值由路徑的第一個值定義,即[4],列值由路徑的第二個值定義(對於值[4],這將意味着[5])。

  2. 對於tri_nums[0],將值10添加三次,一次爲volume_array[4][5],一次爲volume_array[3][4],一次爲volume_array[1][3]
  3. 對於tri_nums[1],值15被添加兩次,一次到volume_array[4][5]並且一次到volume_array[3][4]
  4. 對於tri_nums[2],值25被添加一次到volume_array[4][5]
  5. 最後,將前三步中生成的數組中的所有值加起來得到final_array

值得一提的另一件事是tri_nums的總和等於len(vol_list)。此外tri_nums[n]總是>tri_nums[n+1]

理想情況下,我想爲pathtri_numvol_list實現此代碼,其中包含數百個項目。我現在使用的方法意味着我需要手工製作數百個while循環。我怎樣才能使while循環同時工作,這樣我就可以避免「數百個while while循環」情形?

一切工作得很好,但最終輸出是:

[[ 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 10. 0. 0.] 
[ 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 25. 0.] 
[ 0. 0. 0. 0. 0. 25.] 
[ 0. 0. 0. 0. 0. 0.]] 

意思就是說的vol_list的終值是(25)尚未分配到array_list[4][5],因此不在final_array。它只需要做一個循環,它會工作,我不知道如何讓它做最後一個循環。

請讓我知道,如果有什麼不清楚!

感謝

+1

'list'是一個數據類型 - 它不應該被用作變量名(重命名它)。 '而count <1:'是多餘的,因爲如果你刪除它,你會得到相同的結果。如果您稍後想要多次迭代,則將其保留下來纔有意義。 – jDo

+0

任何你可以用手做的事情你都可以用電腦做。想想你會用手去做的步驟。然後讓電腦做到這一點。有時讓電腦變得更難,但YMMV。 –

+0

既然你問了,代碼示例有點長,說明也適度複雜。我認爲如果你將描述的各個部分與代碼的相應部分交織在一起,會產生更清晰的問題。在幾個地方添加示例輸出將有助於進一步提高。這就是說,我知道你在做什麼;讓我看看我能否拿出答案。 –

回答

1

你錯過了數組的最後一個元素的原因是,你在同一時間遞增n你大跌眼鏡元素關閉的tri_nums。看看ntri_nums值在你while每次循環的開頭:

iteration n tri_nums n <= len(tri_nums) 
0   0 [3, 2, 1] True 
1   1 [2, 1]  True 
2   2 [1]   False 

您應該保持n爲0,並讓您的病情while tri_nums(即相當於while len(tri_nums) > 0),或可能會更好,您應該避免修改tri_nums並只使用for循環。這樣,你會需要修改內部循環每次只遍歷部分tri_nums,就像這樣:

for n in xrange(len(tri_nums)): 
    for num in tri_nums[n:]: 

話雖這麼說,遍歷列表,創建多個陣列,並把它們加起來的整個方法效率很低。因爲這不是Code Review,我不會進入所有的低效率,但也有幾個關鍵的人我想提一提:

  • 你在你的輸入數據,你可以利用有很多結構的
  • 你應該嘗試儘可能
  • 你保持在同一指標推杆數,所以可以先加起來的數字,僅創建在最後
  • 陣列使用numpy的矢量化操作,而不是原生的Python操作

考慮到這一切,我會建議更改您的代碼,以便vol_list只包含每個編號一次

vol_list = [10, 15, 25] 

然後,您可以通過先將數字加起來,然後將結果總和粘貼到數組中,來構造所需的數組。 NumPy的便利,包括cumsum函數來計算數組的部分和:

>>> np.cumsum([10, 15, 25]) 
array([10, 25, 50]) 

,它可以讓你在它的索引操作一次指定多個值。所以,整個算法可以減少到這一點:

final_array = np.zeros((6, 6)) 
final_array[paths[:-1], paths[1:]] = np.cumsum(vol_list) 

如果你的內存需求成爲一長串問題,您可能需要使用Scipy's sparse matrices進行存儲,而不是普通的NumPy的陣列。

+0

這是不可思議的。我只是重複檢查它適用於更大的數據集,但目前爲止這麼好。你先生,是一個巫師和一個學者。 –

+0

很高興能夠提供幫助,但我確實希望你能記住首先理解這個問題有多困難,並用它來改善你未來的問題。我認爲在描述代碼的工作方式時,您可以更加謹慎。爲未來的讀者再次清理問題也是有幫助的。 (如果我的答案解決了您的問題,如果您通過點擊綠色複選標記來接受它,那將會很棒。) –