Mam ramkę danych i słownik. Muszę dodać nową kolumnę do ramki danych i obliczyć jej wartości na podstawie słownika.
Uczenie maszynowe, dodanie nowej funkcji opartej na niektórych tabelach:
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)
Oczekuję następujących danych wyjściowych:
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
źródło
źródło
MultiIIndex
. Alternatywa:df['score'] =df.set_index(['gender', 'age', 'cholesterol', 'smoke']).index.map(score).fillna(0).to_numpy()
.df
viaset_index
, nowySeries
via konstruktor. Chociaż zyskujesz na wyrównaniu indeksu, gdy go przypisujeszdf['score']
. Na koniecfillna(0, downcast='infer')
wykonuje zadanie, ale nikt nie powinien preferować tego długiego rozwiązania z niepotrzebnym tworzeniem wielu obiektów pand.merge
może osiągnąć , jest trochę skomplikowane . Uznałem, że odpowiedź zostanie opublikowana szybko, więc zdecydowałem się na alternatywę iz jakiegoś powodu miałem na myśli MultiIndices. Zgadzam się, to prawdopodobnie nie powinna być zaakceptowana odpowiedź, więc mam nadzieję, że tak się nie stanie.Używanie
assign
ze zrozumieniem listy, pobieranie krotek wartości (każdego wiersza) zescore
słownika, domyślnie zero, jeśli nie zostanie znalezione.Czasy
Biorąc pod uwagę różnorodność podejść, pomyślałem, że byłoby interesujące porównać niektóre czasy.
źródło
score.get
, użyłbymitertuples
lubzip(*map(df.get, df))
... Powtarzam, to jest moje preferowane podejście.df.assign(score=[score.get(t, 0) for t in zip(*map(df.get, df))])
1.0
jest taki sam jak skrót,1
dlatego wyszukiwanie krotek powinno dać tę samą odpowiedź niezależnie od tego. Przepraszam @Alexander za tak wiele komentarzy na ten temat, ale po prostu chcę, aby ludzie głosowali jeszcze bardziej, ponieważ ... powinni (-:.values
zip(*map(df.get, ['col2', 'col1', 'col5']))
lub uzyskać krotki modyfikacjidf
:zip(*map(df.eq(1).get, df))
Możesz użyć mapy , ponieważ wynikiem jest słownik:
Wynik
Alternatywnie możesz użyć rozumienia listy:
źródło
Zrozumienie listy i mapa:
Wynik:
źródło
reindex
Lub
merge
źródło
Może być inny sposób użycia
.loc[]
:źródło
Proste rozwiązanie jednowierszowe, zastosowanie
get
ituple
wierszowanie,Powyższe rozwiązanie zakłada, że nie ma żadnych kolumn oprócz pożądanych. Jeśli nie, po prostu użyj kolumn
źródło
score.get
jest dobre. Moim zdaniem powinieneś jednak raczej rozumieć. Zobacz czasy @ Alexandra .