Czy istnieje metoda zastępowania wartości None
w Pandas w Pythonie?
Możesz użyć df.replace('pre', 'post')
i zastąpić wartość inną, ale nie można tego zrobić, jeśli chcesz zastąpić None
wartość, co jeśli spróbujesz, otrzymasz dziwny wynik.
Oto przykład:
df = DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df.replace('-', 0)
co zwraca pomyślny wynik.
Ale,
df.replace('-', None)
co zwraca następujący wynik:
0
0 - // this isn't replaced
1 3
2 2
3 5
4 1
5 -5
6 -1
7 -1 // this is changed to `-1`...
8 9
Dlaczego zwraca się tak dziwny wynik?
Ponieważ chcę wlać tę ramkę danych do bazy danych MySQL, nie mogę umieścić NaN
wartości w żadnym elemencie w mojej ramce danych i zamiast tego chcę wstawić None
. Z pewnością możesz najpierw zmienić '-'
na, NaN
a następnie przekonwertować NaN
na None
, ale chcę wiedzieć, dlaczego ramka danych działa w tak straszny sposób.
Testowane na pandas 0.12.0 dev w Pythonie 2.7 i OS X 10.8. Python jest preinstalowaną wersją na OS X i zainstalowałem pandy za pomocą skryptu SciPy Superpack, dla twojej informacji.
write_frame
nie parsujeNaN
s donone
s?InternalError: (1054, u"Unknown column 'nan' in 'field list'")
błąd. Nie wiem o żadnych innych rozwiązaniach poza konwersjąNaN
do metodyNone
przed wykonaniemwrite_frame
.na_values
argumentu. Więcej informacji w tej odpowiedzi.Odpowiedzi:
Właściwie w późniejszych wersjach pand da to TypeError:
df.replace('-', None) TypeError: If "to_replace" and "value" are both None then regex must be a mapping
Możesz to zrobić, przekazując listę lub słownik:
In [11]: df.replace('-', df.replace(['-'], [None]) # or .replace('-', {0: None}) Out[11]: 0 0 None 1 3 2 2 3 5 4 1 5 -5 6 -1 7 None 8 9
Ale zalecam używanie NaN zamiast None:
In [12]: df.replace('-', np.nan) Out[12]: 0 0 NaN 1 3 2 2 3 5 4 1 5 -5 6 -1 7 NaN 8 9
źródło
df.replace(['-'], [None])
, albodf.replace({'-': None})
, tak myślę. UżycieNone
jako wartownika wyklucza również użycie go jako wartości ..df
sobie z powrotem w stylu:df = df.replace({'?': np.nan})
df.replace('-', df.replace(['-'], [None])
wygląda dziwnie , czy to literówka?Preferuję rozwiązanie
replace
z adict
ze względu na jego prostotę i elegancję:df.replace({'-': None})
Możesz też mieć więcej zamienników:
df.replace({'-': None, 'None': None})
I nawet w przypadku większych zamienników zawsze jest oczywiste i jasne, co zastępuje się tym - co moim zdaniem jest znacznie trudniejsze w przypadku długich list.
źródło
dict
typu wto_replace
powoduje, żemethod
parametr nie jest oceniany, a tym samymmethod='pad'
domyślnie nie ma żadnych złych skutków.where
jest prawdopodobnie tym, czego szukasz. Więcdata=data.where(data=='-', None)
Z dokumentów pandy :
źródło
Przed przystąpieniem do tego postu ważne jest, aby zrozumieć różnicę między NaN i None . Jeden to typ zmiennoprzecinkowy, drugi to typ obiektowy. Pandy lepiej nadają się do pracy z typami skalarnymi, ponieważ wiele metod na tych typach można wektoryzować. Pandy próbują obsłużyć konsekwentnie None i NaN, ale NumPy nie może.
Moja sugestia ( i Andy'ego ) to trzymać się NaN.
Ale żeby odpowiedzieć na twoje pytanie ...
pandy> = 0.18: użyj
na_values=['-']
argumentu zread_csv
Jeśli załadowałeś te dane z CSV / Excel, mam dla Ciebie dobrą wiadomość. Możesz wyłączyć to w katalogu głównym podczas ładowania danych, zamiast pisać poprawkę z kodem jako kolejny krok.
Większość
pd.read_*
funkcji (takich jakread_csv
iread_excel
) przyjmujena_values
atrybut.file.csv
A,B -,1 3,- 2,- 5,3 1,-2 -5,4 -1,-1 -,0 9,0
Teraz, aby przekonwertować
-
znaki na NaN, zrób,import pandas as pd df = pd.read_csv('file.csv', na_values=['-']) df A B 0 NaN 1.0 1 3.0 NaN 2 2.0 NaN 3 5.0 3.0 4 1.0 -2.0 5 -5.0 4.0 6 -1.0 -1.0 7 NaN 0.0 8 9.0 0.0
I podobnie w przypadku innych funkcji / formatów plików.
PS: W wersji 0.24 + możesz zachować typ całkowity, nawet jeśli twoja kolumna ma NaN (tak, porozmawiaj o tym, że masz ciastko i jesz). Możesz określić
dtype='Int32'
df = pd.read_csv('file.csv', na_values=['-'], dtype='Int32') df A B 0 NaN 1 1 3 NaN 2 2 NaN 3 5 3 4 1 -2 5 -5 4 6 -1 -1 7 NaN 0 8 9 0 df.dtypes A Int32 B Int32 dtype: object
Dtype nie jest konwencjonalnym typem int ... ale raczej typem Nullable Integer. Istnieją inne opcje.
Obsługa danych liczbowych:
pd.to_numeric
zerrors='coerce
Jeśli masz do czynienia z danymi liczbowymi, szybszym rozwiązaniem jest skorzystanie
pd.to_numeric
zerrors='coerce'
argumentem, który wymusza nieprawidłowe wartości (wartości, które nie mogą być oddane do numerycznej) do Nan.pd.to_numeric(df['A'], errors='coerce') 0 NaN 1 3.0 2 2.0 3 5.0 4 1.0 5 -5.0 6 -1.0 7 NaN 8 9.0 Name: A, dtype: float64
Aby zachować wartość całkowitą dtype (dopuszcza wartość null), użyj
pd.to_numeric(df['A'], errors='coerce').astype('Int32') 0 NaN 1 3 2 2 3 5 4 1 5 -5 6 -1 7 NaN 8 9 Name: A, dtype: Int32
Aby wymusić wiele kolumn, użyj
apply
:df[['A', 'B']].apply(pd.to_numeric, errors='coerce').astype('Int32') A B 0 NaN 1 1 3 NaN 2 2 NaN 3 5 3 4 1 -2 5 -5 4 6 -1 -1 7 NaN 0 8 9 0
... i przypisz wynik z powrotem po.
Więcej informacji można znaleźć w tej odpowiedzi .
źródło
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9]) df = df.where(df!='-', None)
źródło
Ustawienie wartości null można wykonać za pomocą
np.nan
:import numpy as np df.replace('-', np.nan)
Zaletą jest to, że
df.last_valid_index()
uznaje je za nieważne.źródło
Korzystanie z zamiany i przypisywanie nowego pliku df:
import pandas as pd df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9]) dfnew = df.replace('-', 0) print(dfnew) (venv) D:\assets>py teste2.py 0 0 0 1 3 2 2 3 5 4 1 5 -5
źródło
df.replace('-', np.nan).astype("object")
Zapewni to możliwość
isnull()
późniejszego użycia w ramce danychźródło
W wersji Pandas ≥1.0.0 użyłbym
DataFrame.replace
lubSeries.replace
:df.replace(old_val, pd.NA, inplace=True)
Jest to lepsze z dwóch powodów:
pd.NA
zamiastNone
lubnp.nan
.źródło