Zastępowanie wartości kolumn w pandach DataFrame

141

Próbuję zastąpić wartości w jednej kolumnie ramki danych. Kolumna („kobieta”) zawiera tylko wartości „kobieta” i „mężczyzna”.

Próbowałem następujących rzeczy:

w['female']['female']='1'
w['female']['male']='0' 

Ale otrzymaj dokładnie tę samą kopię poprzednich wyników.

Idealnie chciałbym uzyskać wyjście, które przypomina elementarną pętlę.

if w['female'] =='female':
    w['female'] = '1';
else:
    w['female'] = '0';

Przejrzałem dokumentację gotchas ( http://pandas.pydata.org/pandas-docs/stable/gotchas.html ), ale nie mogę zrozumieć, dlaczego nic się nie dzieje.

Każda pomoc zostanie doceniona.

czarny
źródło

Odpowiedzi:

259

Jeśli dobrze rozumiem, chcesz czegoś takiego:

w['female'] = w['female'].map({'female': 1, 'male': 0})

(Tutaj konwertuję wartości na liczby zamiast ciągów zawierających liczby. Możesz je przekonwertować na "1"i "0", jeśli naprawdę chcesz, ale nie jestem pewien, dlaczego chcesz to zrobić.)

Twój kod nie działa, ponieważ użycie ['female']w kolumnie (drugiej 'female'w Twojej w['female']['female']) nie oznacza „wybierz wiersze, w których wartość to„ kobieta ””. Oznacza to wybranie wierszy, w których indeks to „kobieta”, których może nie być w ramce DataFrame.

BrenBarn
źródło
6
Dzięki. Dokładnie to, czego szukałem. Gdybym miał zamapować „kobieta” na 1, a cokolwiek innego na „0”. Jak by to działało?
Czarny
17
użyj tego tylko wtedy, gdy wszystkie wartości w kolumnie są podane w funkcji map. Wartości kolumn nie określone w funkcji map zostaną zastąpione przez nan.
Chandra
1
Polecam również przy użyciu .locskładni, aby uniknąć SettingWithCopyWarning: pandas.pydata.org/pandas-docs/stable/...
NickBraunagel
2
zamiast .map użyłem .replace
JS noob
Jak pozbyć się „.” tysięcy na dwóch lub więcej kolumnach, nie może tego rozgryźć. dziękuję bardzo
M. Mariscal
115

Możesz edytować podzbiór ramki danych, używając loc:

df.loc[<row selection>, <column selection>]

W tym przypadku:

w.loc[w.female != 'female', 'female'] = 0
w.loc[w.female == 'female', 'female'] = 1
Jimmy Petersson
źródło
1
Jak bym go dostosować, aby nie trzeba było wybierać określonych wierszy za pomocą warunku, tylko wszystkie wiersze w określonej kolumnie? Więc zmień wszystkie komórki w kolumnie na określoną wartość.
Dhruv Ghulati,
3
@DhruvGhulati, użyłbyś df.loc [:, <wybór kolumny>]
38

Drobna różnica:

w.female.replace(['male', 'female'], [1, 0], inplace=True)
deckard
źródło
19

Powinno to również działać:

w.female[w.female == 'female'] = 1 
w.female[w.female == 'male']   = 0
Nick Crawford
źródło
11

Możesz także używać applyz .getnp

w['female'] = w['female'].apply({'male':0, 'female':1}.get):

w = pd.DataFrame({'female':['female','male','female']})
print(w)

Ramka danych w:

   female
0  female
1    male
2  female

Używanie applydo zamiany wartości ze słownika:

w['female'] = w['female'].apply({'male':0, 'female':1}.get)
print(w)

Wynik:

   female
0       1
1       0
2       1 

Uwaga: apply ze słownikiem należy używać, jeśli wszystkie możliwe wartości kolumn w ramce danych są zdefiniowane w słowniku else, będzie miał puste dla tych, które nie są zdefiniowane w słowniku.

student
źródło
8

To jest bardzo kompaktowe:

w['female'][w['female'] == 'female']=1
w['female'][w['female'] == 'male']=0

Kolejny dobry:

w['female'] = w['female'].replace(regex='female', value=1)
w['female'] = w['female'].replace(regex='male', value=0)
Azz
źródło
Pierwszy przykład dotyczy indeksowania łańcuchowego i jest ostrzegany, ponieważ nie może zagwarantować, że wynikowy plik df jest kopią czy widokiem. Zobacz indeksowanie łańcuchowe
Nordle,
7

Alternatywnie istnieje wbudowana funkcja pd.get_dummies dla tego rodzaju przypisań:

w['female'] = pd.get_dummies(w['female'],drop_first = True)

W ten sposób otrzymasz ramkę danych z dwiema kolumnami, po jednej dla każdej wartości występującej w w ['female'], z których usuwasz pierwszą (ponieważ można ją wywnioskować z tej, która została). Nowa kolumna zostanie automatycznie nazwana jako zastąpiony ciąg.

Jest to szczególnie przydatne, jeśli masz zmienne kategorialne z więcej niż dwiema możliwymi wartościami. Ta funkcja tworzy tyle zmiennych fikcyjnych, ile potrzeba do rozróżnienia wszystkich przypadków. Uważaj więc, aby nie przypisać całej ramki danych do pojedynczej kolumny, ale zamiast tego, jeśli w ['żeński'] może być 'męski', 'żeński' lub 'neutralny', zrób coś takiego:

w = pd.concat([w, pd.get_dummies(w['female'], drop_first = True)], axis = 1])
w.drop('female', axis = 1, inplace = True)

Następnie masz dwie nowe kolumny dające fikcyjne kodowanie „kobieta” i pozbyłeś się kolumny ze stringami.

galliwuzz
źródło
4

Korzystanie Series.mapzSeries.fillna

Jeśli kolumna zawiera więcej ciągów niż tylko femalei male, Series.mapw tym przypadku zakończy się niepowodzeniem, ponieważ zwróci NaNinne wartości.

Dlatego musimy połączyć to z fillna:

Przykład dlaczego .mapzawodzi :

df = pd.DataFrame({'female':['male', 'female', 'female', 'male', 'other', 'other']})

   female
0    male
1  female
2  female
3    male
4   other
5   other
df['female'].map({'female': '1', 'male': '0'})

0      0
1      1
2      1
3      0
4    NaN
5    NaN
Name: female, dtype: object

Dla właściwej metody, łańcuch mapz fillna, więc wypełnić NaNwartościami z kolumny oryginalnej:

df['female'].map({'female': '1', 'male': '0'}).fillna(df['female'])

0        0
1        1
2        1
3        0
4    other
5    other
Name: female, dtype: object
Erfan
źródło
2

Istnieje również funkcja pandasnazwana, factorizektórej możesz użyć do automatycznego wykonania tego typu pracy. Przetwarza on etykiety z numerami: ['male', 'female', 'male'] -> [0, 1, 0]. Zobacz odpowiedź, aby uzyskać więcej informacji.

Roald
źródło
0

Myślę, że w odpowiedzi należy wskazać, jaki typ obiektu otrzymujesz we wszystkich sugerowanych powyżej metodach: czy to Series czy DataFrame.

Kiedy otrzymasz kolumnę według w.female.lub w[[2]](gdzie, załóżmy, że 2 to numer Twojej kolumny), otrzymasz z powrotem DataFrame. W tym przypadku możesz użyć metod DataFrame, takich jak .replace.

Podczas korzystania .localbo ilocwrócisz Series, a seria nie ma .replacesposobu, więc należy użyć metod, takich jak apply, mapi tak dalej.

Alex-droid AD
źródło