Masz trzy główne opcje konwersji typów w pandach:
to_numeric()
- zapewnia funkcjonalność pozwalającą bezpiecznie konwertować typy nienumeryczne (np. łańcuchy) na odpowiedni typ numeryczny. (Zobacz także to_datetime()
i to_timedelta()
.)
astype()
- konwertuje (prawie) dowolny typ na (prawie) dowolny inny typ (nawet jeśli niekoniecznie jest to rozsądne). Umożliwia także konwersję na typy kategorialne (bardzo przydatne).
infer_objects()
- metoda użyteczna do konwersji kolumn obiektów zawierających obiekty Python na typ pandy, jeśli to możliwe.
Czytaj dalej, aby uzyskać bardziej szczegółowe wyjaśnienia i zastosowanie każdej z tych metod.
1. to_numeric()
Najlepszym sposobem konwersji jednej lub więcej kolumn DataFrame na wartości liczbowe jest użycie pandas.to_numeric()
.
Ta funkcja spróbuje zmienić obiekty nienumeryczne (takie jak łańcuchy) na liczby całkowite lub liczby zmiennoprzecinkowe, odpowiednio.
Podstawowe użycie
Dane wejściowe to_numeric()
to Seria lub pojedyncza kolumna DataFrame.
>>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
>>> s
0 8
1 6
2 7.5
3 3
4 0.9
dtype: object
>>> pd.to_numeric(s) # convert everything to float values
0 8.0
1 6.0
2 7.5
3 3.0
4 0.9
dtype: float64
Jak widać, zwracana jest nowa seria. Pamiętaj, aby przypisać to wyjście do nazwy zmiennej lub kolumny, aby dalej z niego korzystać:
# convert Series
my_series = pd.to_numeric(my_series)
# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])
Można go również użyć do konwersji wielu kolumn DataFrame za pomocą apply()
metody:
# convert all columns of DataFrame
df = df.apply(pd.to_numeric) # convert all columns of DataFrame
# convert just columns "a" and "b"
df[["a", "b"]] = df[["a", "b"]].apply(pd.to_numeric)
Tak długo, jak wszystkie wartości można przekonwertować, prawdopodobnie to wszystko, czego potrzebujesz.
Obsługa błędów
Ale co, jeśli niektórych wartości nie można przekonwertować na typ liczbowy?
to_numeric()
bierze również errors
argument słowa kluczowego, który pozwala na wymuszenie wartości nienumerycznych NaN
lub po prostu zignorować kolumny zawierające te wartości.
Oto przykład z wykorzystaniem serii ciągów, s
które mają obiekt dtype:
>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0 1
1 2
2 4.7
3 pandas
4 10
dtype: object
Domyślnym zachowaniem jest podniesienie, jeśli nie można przekonwertować wartości. W tym przypadku nie radzi sobie z ciągiem „pandy”:
>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string
Zamiast zawieść, możemy chcieć, aby „pandy” były traktowane jako brakująca / zła wartość liczbowa. Możemy zmusić niepoprawne wartości do NaN
następujących wartości, używając errors
argumentu słowa kluczowego:
>>> pd.to_numeric(s, errors='coerce')
0 1.0
1 2.0
2 4.7
3 NaN
4 10.0
dtype: float64
Trzecią opcją errors
jest zignorowanie operacji, jeśli napotkamy niepoprawną wartość:
>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched
Ta ostatnia opcja jest szczególnie przydatna, gdy chcesz przekonwertować całą ramkę danych, ale nie wiesz, która z naszych kolumn może być niezawodnie przekonwertowana na typ liczbowy. W takim przypadku po prostu napisz:
df.apply(pd.to_numeric, errors='ignore')
Funkcja zostanie zastosowana do każdej kolumny DataFrame. Kolumny, które można przekonwertować na typ liczbowy, zostaną przekonwertowane, a kolumny, które nie będą mogły (np. Zawierają niecyfrowe ciągi lub daty) zostaną pozostawione same.
Downcasting
Domyślnie konwersja z to_numeric()
da ci albo a int64
lub float64
dtype (lub dowolną szerokość całkowitą natywną dla twojej platformy).
Zwykle tego chcesz, ale co jeśli chcesz zaoszczędzić trochę pamięci i użyć bardziej zwartego typu, np. float32
Lub int8
?
to_numeric()
daje opcję spuszczania do „liczb całkowitych”, „podpisanych”, „niepodpisanych”, „zmiennoprzecinkowych”. Oto przykład prostej serii s
liczb całkowitych:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Downcasting do „integer” używa najmniejszej możliwej liczby całkowitej, która może przechowywać wartości:
>>> pd.to_numeric(s, downcast='integer')
0 1
1 2
2 -7
dtype: int8
Downcasting do „float” podobnie wybiera mniejszy niż normalny typ pływający:
>>> pd.to_numeric(s, downcast='float')
0 1.0
1 2.0
2 -7.0
dtype: float32
2) astype()
Ta astype()
metoda umożliwia wyraźne określenie typu, jaki ma mieć DataFrame lub seria. Jest bardzo wszechstronny, ponieważ możesz próbować przejść od jednego typu do drugiego.
Podstawowe użycie
Po prostu wybierz typ: możesz użyć typu NumPy (np. np.int16
), Niektórych typów Python (np. Bool) lub typów specyficznych dla pand (takich jak typowy typ).
Wywołaj metodę na obiekcie, który chcesz przekonwertować, i astype()
spróbuje go przekonwertować:
# convert all DataFrame columns to the int64 dtype
df = df.astype(int)
# convert column "a" to int64 dtype and "b" to complex type
df = df.astype({"a": int, "b": complex})
# convert Series to float16 type
s = s.astype(np.float16)
# convert Series to Python strings
s = s.astype(str)
# convert Series to categorical type - see docs for more details
s = s.astype('category')
Zauważ, że powiedziałem „spróbuj” - jeśli astype()
nie wie, jak przekonwertować wartość w Series lub DataFrame, zgłosi błąd. Na przykład, jeśli masz wartość NaN
lub, inf
zobaczysz błąd podczas próby konwersji jej na liczbę całkowitą.
Począwszy od pand 0.20.0, błąd ten można stłumić, przekazując errors='ignore'
. Twój oryginalny obiekt zostanie nienaruszony.
Bądź ostrożny
astype()
jest potężny, ale czasami konwertuje wartości „niepoprawnie”. Na przykład:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Są to małe liczby całkowite, więc co powiesz na konwersję na niepodpisany 8-bitowy typ w celu oszczędzania pamięci?
>>> s.astype(np.uint8)
0 1
1 2
2 249
dtype: uint8
Konwersja zadziałała, ale wartość -7 została zawinięta na 249 (tj. 2 8–7 )!
Próba użycia downcast przy użyciu pd.to_numeric(s, downcast='unsigned')
zamiast tego może pomóc zapobiec temu błędowi.
3) infer_objects()
W wersji 0.21.0 pand wprowadzono metodę infer_objects()
konwersji kolumn DataFrame, które mają typ danych obiektu na bardziej konkretny typ (konwersje miękkie).
Na przykład, oto DataFrame z dwiema kolumnami typu obiektu. Jedna zawiera rzeczywiste liczby całkowite, a druga ciągi znaków reprezentujące liczby całkowite:
>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a object
b object
dtype: object
Za pomocą infer_objects()
możesz zmienić typ kolumny „a” na int64:
>>> df = df.infer_objects()
>>> df.dtypes
a int64
b object
dtype: object
Kolumna „b” została pozostawiona sama, ponieważ jej wartości były łańcuchami, a nie liczbami całkowitymi. Jeśli chcesz spróbować wymusić konwersję obu kolumn na typ całkowity, możesz df.astype(int)
zamiast tego użyć .