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.

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.


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

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)

19

Powinno to również działać:

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

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.


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)

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.


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

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.


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.