Chcę przekonwertować tabelę reprezentowaną jako lista list na plik Pandas DataFrame
. Jako wyjątkowo uproszczony przykład:
a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a)
Jaki jest najlepszy sposób przekonwertowania kolumn na odpowiednie typy, w tym przypadku kolumny 2 i 3 na zmiennoprzecinkowe? Czy istnieje sposób określenia typów podczas konwersji do DataFrame? A może lepiej najpierw utworzyć DataFrame, a następnie przejść przez kolumny, aby zmienić typ każdej kolumny? Idealnie chciałbym to zrobić w sposób dynamiczny, ponieważ mogą istnieć setki kolumn i nie chcę dokładnie określać, które kolumny są tego typu. Mogę tylko zagwarantować, że każda kolumna zawiera wartości tego samego typu.
df.apply(pd.to_numeric, downcast="integer", errors="ignore")
kolumny liczb całkowitych do najmniejszego (całkowitego) typu, który będzie przechowywał wartości.Odpowiedzi:
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żeto_datetime()
ito_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.Jak widać, zwracana jest nowa seria. Pamiętaj, aby przypisać to wyjście do nazwy zmiennej lub kolumny, aby dalej z niego korzystać:
Można go również użyć do konwersji wielu kolumn DataFrame za pomocą
apply()
metody: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 nienumerycznychNaN
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:Domyślnym zachowaniem jest podniesienie, jeśli nie można przekonwertować wartości. W tym przypadku nie radzi sobie z ciągiem „pandy”:
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ącerrors
argumentu słowa kluczowego:Trzecią opcją
errors
jest zignorowanie operacji, jeśli napotkamy niepoprawną wartość: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:
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 aint64
lubfloat64
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
Lubint8
?to_numeric()
daje opcję spuszczania do „liczb całkowitych”, „podpisanych”, „niepodpisanych”, „zmiennoprzecinkowych”. Oto przykład prostej seriis
liczb całkowitych:Downcasting do „integer” używa najmniejszej możliwej liczby całkowitej, która może przechowywać wartości:
Downcasting do „float” podobnie wybiera mniejszy niż normalny typ pływający:
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ć: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ą to małe liczby całkowite, więc co powiesz na konwersję na niepodpisany 8-bitowy typ w celu oszczędzania pamięci?
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:
Za pomocą
infer_objects()
możesz zmienić typ kolumny „a” na int64: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ć .źródło
.convert_objects
jest depracowany, ponieważ0.17
-df.to_numeric
zamiast tego użyjpd.to_numeric
a metody towarzyszące będą działać tylko na jednej kolumnie na raz, w przeciwieństwie doconvert_objects
. Trwa dyskusja na temat funkcji zamiany w interfejsie API ; Mam nadzieję, że metoda, która działa w całej DataFrame, pozostanie, ponieważ jest bardzo przydatna.int64
doint32
?astype
(jak w drugiej odpowiedzi), tj.astype(numpy.int32)
.Co powiesz na to?
źródło
pd.DataFrame
madtype
argument, który może ci pomóc w / szukasz. df = pd.DataFrame (a, columns = ['one', 'two', 'three'], dtype = float) In [2]: df.dtypes Out [2]: jeden obiekt dwa float64 trzy float64 dtype: obiektSettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead
. Być może zostało to wprowadzone w nowszej wersji pand i dlatego nie widzę w tym nic złego, ale po prostu zastanawiam się, o co chodzi w tym ostrzeżeniu. Dowolny pomysł?ValueError: Cannot convert NA to integer
df = pd.DataFrame(a, columns=['one', 'two', 'three'], dtype={'one': str, 'two': int, 'three': float})
. Trudno mi jednak znaleźć specyfikację dla akceptowanych wartości „dtype”. Lista byłaby miła (obecnie to robiędict(enumerate(my_list))
).ten poniższy kod zmieni typ danych kolumny.
zamiast typu danych możesz podać swój typ danych. czego chcesz, jak str, float, int itp.
źródło
bool
, wszystko zmienia się naTrue
.Kiedy muszę tylko określić konkretne kolumny i chcę wyrazić się jasno, użyłem (według LOKALIZACJI DOCS ):
Korzystając z oryginalnego pytania, ale podając do niego nazwy kolumn ...
źródło
Oto funkcja, która bierze za argumenty ramkę danych i listę kolumn i wymusza wszystkie dane w kolumnach na liczby.
Na przykład:
źródło
Co powiesz na utworzenie dwóch ramek danych, z których każdy ma inny typ danych dla swoich kolumn, a następnie dołączenie ich razem?
Wyniki
Po utworzeniu ramki danych możesz wypełnić ją zmiennymi zmiennoprzecinkowymi w pierwszej kolumnie, a ciągi (lub dowolny typ danych, który chcesz) w drugiej kolumnie.
źródło
pandy> = 1,0
Oto wykres podsumowujący niektóre z najważniejszych konwersji w pandach.
Konwersje na ciąg są trywialne
.astype(str)
i nie są pokazane na rysunku.Konwersje „twarde” kontra „miękkie”
Zauważ, że „konwersje” w tym kontekście mogą odnosić się do konwertowania danych tekstowych na ich rzeczywisty typ danych (konwersja twarda) lub wnioskowania o bardziej odpowiednich typach danych dla danych w kolumnach obiektowych (konwersja miękka). Aby zilustrować różnicę, spójrz na
źródło
Myślałem, że mam ten sam problem, ale w rzeczywistości mam niewielką różnicę, która sprawia, że problem jest łatwiejszy do rozwiązania. Dla innych, którzy patrzą na to pytanie, warto sprawdzić format listy wejściowej. W moim przypadku liczby są początkowo liczbami zmiennoprzecinkowymi, a nie ciągami, jak w pytaniu:
ale przetwarzając listę zbyt dużo przed utworzeniem ramki danych, tracę typy i wszystko staje się ciągiem.
Tworzenie ramki danych za pomocą tablicy numpy
daje taką samą ramkę danych jak w pytaniu, gdzie wpisy w kolumnach 1 i 2 są uważane za ciągi. Jednak robiąc
faktycznie daje ramkę danych z kolumnami w odpowiednim formacie
źródło
Począwszy od pand 1.0.0, mamy
pandas.DataFrame.convert_dtypes
. Możesz nawet kontrolować, jakie typy konwertować!źródło