2016-07-16 55 views
1

調整後的數據我使用Python的numpy的scikit學習。我有數據存儲在SQL表中。我將其作爲返回的元組列表進行檢索:[(id, value),...]。每個id在列表中僅出現一次,並且元組按照升序ID的順序出現。這個過程完成了幾次,以便我有多個key: value對的列表。這樣的:如何構建從多個向量numpy的陣列與ID

dataset = [] 
for sample in samples: 
    listOfTuplePairs = getDataFromSQL(sample) # get a [(id, value),...] list 
    dataset.append(listOfTuplePairs) 

鍵可以在不同的樣本中複製,並且每行可以具有不同的長度。一個例子dataset可能是:

dataset = [[(1, 0.13), (2, 2.05)], 
      [(2, 0.23), (4, 7.35), (5, 5.60)], 
      [(2, 0.61), (3, 4.45)]] 

它可以看出,每行是一個示例,並且一些IDS(在這種情況下2)出現多個樣品英寸

問題:我希望構造一個單個(可能稀疏)numpy的適於與scikit學習處理陣列。關於每個樣本的特定鍵(ID)的值應該在同一「列」對齊(如果這是正確的術語),使得上面的例子中的矩陣將如下所示:

ids =  1 2  3  4 5 
      ------------------------------ 
dataset = [(0.13, 2.05, null, null, null), 
      (null, 0.23, null, 7.35, 5.60), 
      (null, 0.61, 4.45, null, null)] 

正如你所看到的,我也希望從矩陣中去掉id(儘管我需要保留它們的列表,所以我知道矩陣中的值是什麼。每個key: value對的初始列表可能包含數千行,可能會有幾千個樣本,所以得到的矩陣可能會非常大,請提供考慮速度(Python限制內),內存效率和代碼清晰度的答案。任何幫助。

+0

你可能想看看['pandas'](http://pandas.pydata.org/),它提供標記與此類似陣列結構。 – BrenBarn

回答

3

這裏的一個NumPy的基礎的方法來創建一個稀疏矩陣coo_matrix與存儲器效率在聚焦 -

from scipy.sparse import coo_matrix 

# Construct row IDs 
lens = np.array([len(item) for item in dataset]) 
shifts_arr = np.zeros(lens.sum(),dtype=int) 
shifts_arr[lens[:-1].cumsum()] = 1 
row = shifts_arr.cumsum() 

# Extract values from dataset into a NumPy array 
arr = np.concatenate(dataset) 

# Get the unique column IDs to be used for col-indexing into output array 
col = np.unique(arr[:,0],return_inverse=True)[1] 

# Determine the output shape 
out_shp = (row.max()+1,col.max()+1) 

# Finally create a sparse marix with the row,col indices and col-2 of arr 
sp_out = coo_matrix((arr[:,1],(row,col)), shape=out_shp) 

請注意,如果IDs應該是輸出陣列中的列號,那麼您可以替換使用np.unique,它給了我們這樣的唯一ID,像這樣 -

col = (arr[:,0]-1).astype(int) 

這應該會給我們一個很好的性能提升!

樣品運行 -

In [264]: dataset = [[(1, 0.13), (2, 2.05)], 
    ...:   [(2, 0.23), (4, 7.35), (5, 5.60)], 
    ...:   [(2, 0.61), (3, 4.45)]] 

In [265]: sp_out.todense() # Using .todense() to show output 
Out[265]: 
matrix([[ 0.13, 2.05, 0. , 0. , 0. ], 
     [ 0. , 0.23, 0. , 7.35, 5.6 ], 
     [ 0. , 0.61, 4.45, 0. , 0. ]]) 
+0

非常感謝!但是,這僅適用於數據集中的每一行長度相等的情況。如果不是那麼'arr.shape [:2] =(3,)' – Tintin

+0

@Paul是的,它假定數據集的規則形狀。也許在列表不等長的列表中添加一個樣例到問題中?我們會看看解決方案是否可以修改以涵蓋這種情況。 – Divakar

+0

@divakar你說得很對,我在這個問題上沒有說清楚。我現在修改了它。抱歉。 – Tintin

0

您可以將數據集中的每個元素轉換爲字典,然後使用pandas數據框,這將返回結果接近所需的輸出。如果2D numpy的陣列所需的,我們可以使用as_matrix()方法將數據幀轉換爲numpy的數組:

import pandas as pd 
pd.DataFrame(dict(x) for x in dataset).as_matrix() 

# array([[ 0.13, 2.05, nan, nan, nan], 
#  [ nan, 0.23, nan, 7.35, 5.6 ], 
#  [ nan, 0.61, 4.45, nan, nan]]) 
+0

非常感謝,因爲這也符合我的想法,可能是更好的解決方案 - 儘管不是「純粹的numpy」。 – Tintin