Pandy: konwertuj kategorie na liczby

86

Załóżmy, że mam ramkę danych z krajami, które są następujące:

cc | temp
US | 37.0
CA | 12.0
US | 35.0
AU | 20.0

Wiem, że istnieje funkcja pd.get_dummies służąca do konwersji krajów na „kodowanie na jeden gorący”. Chciałbym jednak przekonwertować je na indeksy zamiast takich, które otrzymam cc_index = [1,2,1,3]zamiast tego.

Zakładam, że istnieje szybszy sposób niż użycie get_dummies wraz z klauzulą ​​numpy where, jak pokazano poniżej:

[np.where(x) for x in df.cc.get_dummies().values]

Jest to nieco łatwiejsze do zrobienia w R przy użyciu „czynników”, więc mam nadzieję, że pandy mają coś podobnego.

sachinruk
źródło
2
Czy masz na myśli cc_index = [0,1,0,2]?
juanpa.arrivillaga
1
jasne
Pomocne mogą być serie kategorialne lub kolumny w DataFrame.
min2bro

Odpowiedzi:

150

Najpierw zmień typ kolumny:

df.cc = pd.Categorical(df.cc)

Teraz dane wyglądają podobnie, ale są przechowywane kategorycznie. Aby uchwycić kody kategorii:

df['code'] = df.cc.cat.codes

Teraz masz:

   cc  temp  code
0  US  37.0     2
1  CA  12.0     1
2  US  35.0     2
3  AU  20.0     0

Jeśli nie chcesz modyfikować swojej ramki DataFrame, ale po prostu pobierz kody:

df.cc.astype('category').cat.codes

Lub użyj kolumny kategorialnej jako indeksu:

df2 = pd.DataFrame(df.temp)
df2.index = pd.CategoricalIndex(df.cc)
John Zwinck
źródło
5
df.cc.cat.codesWygląda na to, że wezwanie zmieniło się na sprawiedliwe df.cc.codes?
Andreas Storvik Strauman
1
Zauważ, że jeśli masz brakujące wartości, zostaną one zakodowane na -1. Jeśli chcesz uniknąć leczenia tego przypadku, możesz najpierw rzutować na łańcuch: df.cc.astype ('str'). Astype ('category'). Cat.codes
Guy s
Wydaje się, że zmienia się NaNjak -1?
ahbon
25

Jeśli chcesz tylko przekształcić swój szereg w identyfikatory całkowite, możesz użyć pd.factorize.

Zwróć uwagę, że to rozwiązanie, w przeciwieństwie do pd.Categorical, nie będzie sortowane alfabetycznie. Tak więc zostanie przypisany pierwszy kraj 0. Jeśli chcesz zacząć od 1, możesz dodać stałą:

df['code'] = pd.factorize(df['cc'])[0] + 1

print(df)

   cc  temp  code
0  US  37.0     1
1  CA  12.0     2
2  US  35.0     1
3  AU  20.0     3

Jeśli chcesz sortować alfabetycznie, określ sort=True:

df['code'] = pd.factorize(df['cc'], sort=True)[0] + 1 
jpp
źródło
14

Jeśli korzystasz z sklearnbiblioteki, możesz użyć LabelEncoder. Podobnie jak pd.Categoricalciągi wejściowe są sortowane alfabetycznie przed kodowaniem.

from sklearn.preprocessing import LabelEncoder

LE = LabelEncoder()
df['code'] = LE.fit_transform(df['cc'])

print(df)

   cc  temp  code
0  US  37.0     2
1  CA  12.0     1
2  US  35.0     2
3  AU  20.0     0
jpp
źródło
2

Spróbuj tego, zamień na liczbę na podstawie częstotliwości (wysoka częstotliwość - duża liczba):

labels = df[col].value_counts(ascending=True).index.tolist()
codes = range(1,len(labels)+1)
df[col].replace(labels,codes,inplace=True)
Palepalli Surendra Reddy
źródło
1

Zmieni dowolne kolumny na liczby. Nie utworzy nowej kolumny, ale po prostu zastąpi wartości danymi liczbowymi.

def characters_to_numb(*args): for arg in args: df[arg] = pd.Categorical(df[arg]) df[arg] = df[arg].cat.codes return df

Denis Kalyan
źródło
0

Kod jednowierszowy:

df[['cc']] = df[['cc']].apply(lambda col:pd.Categorical(col).codes)

Działa to również, jeśli masz list_of_columns:

df[list_of_columns] = df[list_of_columns].apply(lambda col:pd.Categorical(col).codes)

Ponadto, jeśli chcesz zachować swoje NaNwartości, możesz zastosować zamianę:

df[['cc']] = df[['cc']].apply(lambda col:pd.Categorical(col).codes).replace(-1,np.nan)
Piotro
źródło