2016-09-07 3 views
1

TLDR: Wie über alle Optionen von mehreren Spalten in einem Pandas-Datenrahmen zu iterieren, ohne die Spalten oder ihre Werte explizit anzugeben?Iterieren über mehrere Spalten in Pandas DF und dynamische Slicing

Lange Version: Ich habe einen Pandas Datenrahmen, der so aussieht, nur hat es viel mehr Funktionen oder Wirkstoffdosis Kombinationen als hier aufgeführt sind. Anstatt nur drei Arten von Merkmalen, könnte es so etwas wie 70 hat ...:

> dosage_df 

First Score Last Score A_dose B_dose C_dose 
22   28   1  40  130 
55   11   2  40  130 
15   72   3  40  130 
42   67   1  90  130 
90   74   2  90  130 
87   89   3  90  130 
14   43   1  40  700 
12   61   2  40  700 
41   5   3  40  700 

Zusammen mit meinem Datenrahmen, ich habe auch einen Python-Wörterbuch mit den relevanten Bereichen für jede Funktion. Die Tasten sind die Feature-Namen, und die verschiedenen Werte, die sie nehmen können, sind die Tasten:

> dict_of_dose_ranges = {'A_dose': [1, 2, 3], 'B_dose': [40, 90], 'C_dose': [130,700]} 

Für meine Zwecke, ich brauche eine bestimmte Kombination zu erzeugen (zB A_dose = 1, B_dose = 90 und C_dose = 700), und basierend auf diesen Einstellungen nehme ich die relevante Schicht aus meinem Datenrahmen und führe relevante Berechnungen aus dieser kleineren Teilmenge durch und speichere die Ergebnisse irgendwo.

Ich muss dies für ALLE möglichen Kombinationen aller meiner Features tun (weit mehr als die 3, die hier sind, und die in der Zukunft variabel sein werden).

In diesem Fall könnte ich dies leicht Pop in Parameter Grids SkLearn erzeugen die Optionen:

> from sklearn.grid_search import ParameterGrid 
> all_options = list(ParameterGrid(dict_of_dose_ranges)) 
> all_options 

und erhalten:

[{'A_dose': 1, 'B_dose': 40, 'C_dose': 130}, 
{'A_dose': 1, 'B_dose': 40, 'C_dose': 700}, 
{'A_dose': 1, 'B_dose': 90, 'C_dose': 130}, 
{'A_dose': 1, 'B_dose': 90, 'C_dose': 700}, 
{'A_dose': 2, 'B_dose': 40, 'C_dose': 130}, 
{'A_dose': 2, 'B_dose': 40, 'C_dose': 700}, 
{'A_dose': 2, 'B_dose': 90, 'C_dose': 130}, 
{'A_dose': 2, 'B_dose': 90, 'C_dose': 700}, 
{'A_dose': 3, 'B_dose': 40, 'C_dose': 130}, 
{'A_dose': 3, 'B_dose': 40, 'C_dose': 700}, 
{'A_dose': 3, 'B_dose': 90, 'C_dose': 130}, 
{'A_dose': 3, 'B_dose': 90, 'C_dose': 700}] 

Dies ist, wo ich in Probleme laufen:

Problem # 1) Ich kann jetzt über all_options iterieren, aber ich bin nicht sicher, wie jetzt aus meiner dosage_df von jeder der Wörterbuchoptionen SELECT (d. h. {'A_dose': 1, 'B_dose': 40, 'C_dose': 130}) OHNE es explizit zu tun.

In der Vergangenheit konnte ich so etwas wie:

dosage_df[(dosage_df.A_dose == 1) & (dosage_df.B_dose == 40) & (dosage_df.C_dose == 130)] 

First Score Last Score A_dose B_dose C_dose 
0   22   28  140  130 

Aber jetzt bin ich nicht sicher, was in den Klammern um es dynamisch zu schneiden ...

dosage_df[?????] 

Problem # 2) Wenn ich tatsächlich in mein vollständiges Wörterbuch von Features mit ihren jeweiligen Bereichen eintrage, erhalte ich einen Fehler, weil es zu viele Optionen hat ...

from sklearn.grid_search import ParameterGrid 
all_options = list(ParameterGrid(dictionary_of_features_and_ranges)) 
all_options 

--------------------------------------------------------------------------- 
OverflowError        Traceback (most recent call last) 
<ipython-input-138-7b73d5e248f5> in <module>() 
     1 from sklearn.grid_search import ParameterGrid 
----> 2 all_options = list(ParameterGrid(dictionary_of_features_and_ranges)) 
     3 all_options 

OverflowError: long int too large to convert to int 

Ich versuchte eine Reihe von alternativen Ansätzen einschließlich der Verwendung von Doppel-While-Schleifen, eine tree/recursion method from here, eine andere recursion method from here, aber es kam nicht zusammen .... Jede Hilfe wird sehr geschätzt.

Antwort

2

Sie können itertools.product verwenden alle möglichen Dosierungskombinationen zu erzeugen, und DataFrame.query um die Auswahl zu tun:

from itertools import product 

for dosage_comb in product(*dict_of_dose_ranges.values()): 
    dosage_items = zip(dict_of_dose_ranges.keys(), dosage_comb) 
    query_str = ' & '.join('{} == {}'.format(*x) for x in dosage_items) 
    sub_df = dosage_df.query(query_str) 

    # Do Stuff... 
0

Wie wäre es mit dem zugrundeliegenden numpy-Array und einiger boolescher Logik, ein Array zu erstellen, das nur die gewünschten Zeilen enthält?

dosage_df = pd.DataFrame((np.random.rand(40000,10)*100).astype(np.int)) 
dict_of_dose_ranges={3:[10,11,12,13,15,20],4:[20,22,23,24]} 

#combined_doses will be bool array that will select all the lines that match the wanted combinations of doses 

combined_doses=np.ones(dosage_df.shape[0]).astype(np.bool) 
for item in dict_of_dose_ranges.items(): 
    #item[0] is the kind of dose 
    #item[1] are the values of that kind of dose 

    next_dose=np.zeros(dosage_df.shape[0]).astype(np.bool) 

    #we then iterate over the wanted values 
    for value in item[1]: 
     # we select and "logical or" all lines matching the values 
     next_dose|=(dosage_df[item[0]] == value) 
    # we "logical and" all the kinds of dose 
    combined_doses&=next_dose 

print(dosage_df[combined_doses]) 
+0

Konnten Sie diese Arbeit bekommen? Ich habe einen Fehler: IndexError: nur ganze Zahlen, Slices (':'), Ellipse ('...'), numpy.newaxis ('None') und Integer oder Boolesche Arrays sind gültige Indizes – Afflatus

+0

Ich habe ein bisschen die bearbeitet Code zum Korrigieren eines Fehlers 'arr [:, item [0]]' und vertauschte arthme für bitweise Operatoren und fügte Beispielwerte hinzu, so dass es kopierbar/verarbeitbar ist. So wie es jetzt ist, läuft es gut für mich. – jadsq

+0

Ich denke, es funktioniert nur für Sie b/c die Spalten von dosage_df und dict_of_dose_ranges hat Tasten, die ganze Zahlen sind. – Afflatus

Verwandte Themen