2016-07-16 11 views
1

ausgerichtet konstruieren Ich verwende Python, numpy und Scikit-Learn. Ich habe Daten Schlüssel und Werte, die in einer SQL-Tabelle gespeichert sind. Ich erhalte dies als eine Liste von Tupeln zurückgegeben als: [(id, value),...]. Jede ID erscheint nur einmal in der Liste und die Tupel erscheinen in der Reihenfolge der aufsteigenden ID sortiert. Dieser Prozess ist ein paar Mal abgeschlossen, so dass ich mehrere Listen von key: value Paaren habe. So dass:Wie ein numpy Array aus mehreren Vektoren, die mit Daten, die von ID

Schlüssel können über verschiedene Beispiele dupliziert werden, und jede Zeile kann eine andere Länge haben. Ein Beispiel dataset könnte sein:

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

Es ist ersichtlich, dass jede Zeile eine Probe ist, und daß einige IDs (in diesem Fall 2) in mehreren Proben erscheinen.

Problem: Ich möchte eineinzigen (möglicherweise sparse) numpy Array geeignet für die Verarbeitung mit konstruieren Scikit-Learn. Die Werte in Zusammenhang mit einem bestimmten Schlüssel (ID) für jede Probe sollen in der gleichen ‚Spalte‘ ausgerichtet werden, (wenn, dass die richtige Terminologie ist), dass die Matrix aus dem obigen Beispiel würde wie folgt aussehen:

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)] 

Wie Sie sehen können, möchte ich auch die IDs von der Matrix entfernen (obwohl ich eine Liste von ihnen behalten muss, damit ich weiß, worauf sich die Werte in der Matrix beziehen. Jede erste Liste von key: value Paaren kann mehrere tausend Zeilen und enthalten es kann mehrere tausend Stichproben geben, daher kann die resultierende Matrix sehr groß sein Bitte geben Sie Antworten, die Geschwindigkeit (innerhalb der Grenzen von Python), Speichereffizienz und Code-Klarheit berücksichtigen

Vielen, vielen Dank in adv für jede Hilfe.

+0

Möglicherweise möchten Sie auf [ 'pandas'] (http://pandas.pydata.org/) zu sehen, die Array-Strukturen ähnlich wie dies markiert bietet. – BrenBarn

Antwort

3

hier ein NumPy basierten Ansatz eine spärliche Matrix coo_matrix mit Speichereffizienz im Fokus zu schaffen -

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) 

Wenn die IDs Spaltennummern im Ausgabe-Array sein sollen, können Sie die Verwendung von np.unique ersetzen, die uns so eindeutige IDs gibt -

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

Dies sollte uns einen guten Leistungsschub geben!

Probelauf -

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

Vielen Dank!Dies funktioniert jedoch nur, wenn jede Zeile im Dataset gleich lang ist. Wenn nicht, dann 'arr.shape [: 2] = (3,)' – Tintin

+0

@Paul Ja, es nimmt für den Datensatz eine normale Form an. Fügen Sie vielleicht einen Musterfall mit ungleich langen Listen in die Frage ein? Wir werden sehen, ob die Lösung geändert werden könnte, um einen solchen Fall abzudecken. – Divakar

+0

@divakarDu hast recht, das habe ich in der Frage nicht klargestellt. Ich habe es jetzt geändert. Es tut uns leid. – Tintin

0

Sie können jedes Element im Dataset in ein Wörterbuch konvertieren und dann den Pandas-Datenrahmen verwenden, der das Ergebnis nahe an die gewünschte Ausgabe zurückgibt. Wenn 2D numpy Array gewünscht wird, können wir as_matrix() Methode verwenden, um den Datenrahmen zu numpy Array zu konvertieren:

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

Vielen Dank dafür, das hat auch so funktioniert, wie ich es wollte und es ist wahrscheinlich eine bessere Lösung - allerdings kein "pure numpy". – Tintin