Ich habe einen Datenrahmen und ein Wörterbuch. Ich muss dem Datenrahmen eine neue Spalte hinzufügen und seine Werte basierend auf dem Wörterbuch berechnen.
Maschinelles Lernen, Hinzufügen neuer Funktionen basierend auf einer Tabelle:
score = {(1, 45, 1, 1) : 4, (0, 1, 2, 1) : 5}
df = pd.DataFrame(data = {
'gender' : [1, 1, 0, 1, 1, 0, 0, 0, 1, 0],
'age' : [13, 45, 1, 45, 15, 16, 16, 16, 15, 15],
'cholesterol' : [1, 2, 2, 1, 1, 1, 1, 1, 1, 1],
'smoke' : [0, 0, 1, 1, 7, 8, 3, 4, 4, 2]},
dtype = np.int64)
print(df, '\n')
df['score'] = 0
df.score = score[(df.gender, df.age, df.cholesterol, df.smoke)]
print(df)
Ich erwarte folgende Ausgabe:
gender age cholesterol smoke score
0 1 13 1 0 0
1 1 45 2 0 0
2 0 1 2 1 5
3 1 45 1 1 4
4 1 15 1 7 0
5 0 16 1 8 0
6 0 16 1 3 0
7 0 16 1 4 0
8 1 15 1 4 0
9 0 15 1 2 0
python
pandas
dataframe
dictionary
Mikola
quelle
quelle
MultiIIndex
. Alternative :df['score'] =df.set_index(['gender', 'age', 'cholesterol', 'smoke']).index.map(score).fillna(0).to_numpy()
.df
Via erstelltset_index
, ein neuesSeries
Via-Konstruktor. Sie profitieren jedoch von der Indexausrichtung, wenn Sie sie zuweisendf['score']
. Schließlichfillna(0, downcast='infer')
wird die Arbeit erledigt, aber niemand sollte diese langwierige Lösung mit der unnötigen Erstellung vieler Pandas-Objekte bevorzugen.merge
könnte. Ich dachte, dass die Antwort schnell veröffentlicht werden würde, also entschied ich mich für eine Alternative und hatte aus irgendeinem Grund MultiIndices im Kopf. Ich stimme zu, dies sollte wahrscheinlich nicht die akzeptierte Antwort sein, also hoffentlich passiert das nicht.Verwenden
assign
eines Listenverständnisses, Abrufen eines Tupels von Werten (jede Zeile) aus demscore
Wörterbuch, standardmäßig Null, wenn es nicht gefunden wird.Timings
Angesichts der Vielfalt der Ansätze halte ich es für interessant, einige der Timings zu vergleichen.
quelle
score.get
würde ichitertuples
oderzip(*map(df.get, df))
... Um es noch einmal zu wiederholen, ist dies mein bevorzugter Ansatz.df.assign(score=[score.get(t, 0) for t in zip(*map(df.get, df))])
1.0
der gleiche ist wie der Hash,1
daher sollten die Tupel-Lookups unabhängig davon zu derselben Antwort führen. Entschuldigung @Alexander für so viele Kommentare dazu, aber ich möchte nur, dass die Leute dies mehr befürworten, weil ... sie sollten (-:.values
zip(*map(df.get, ['col2', 'col1', 'col5']))
oder Tupel einer Modifikation vondf
:zip(*map(df.eq(1).get, df))
Sie könnten eine Karte verwenden , da die Punktzahl ein Wörterbuch ist:
Ausgabe
Alternativ können Sie ein Listenverständnis verwenden:
quelle
Listenverständnis und Karte:
Ausgabe:
quelle
reindex
Oder
merge
quelle
Möglicherweise würde ein anderer Weg verwendet werden
.loc[]
:quelle
Einfache einzeilige Lösung, Verwendung
get
undtuple
zeilenweise,Bei der obigen Lösung wird davon ausgegangen, dass keine anderen Spalten als die gewünschten in der Reihenfolge vorhanden sind. Wenn nicht, verwenden Sie einfach Spalten
quelle
score.get
ist gut. Meiner Meinung nach sollten Sie jedoch ein Verständnis vorziehen. Siehe @ Alexanders Timings.