Konwertuj kolumnę Pandas zawierającą Nan na dtype ' int`

Czytam dane z a .plik csv do ramki danych Pandy jak poniżej. Dla jednej z kolumn, mianowicie id, chcę określić typ kolumny jako int. Problem polega na tym, że seria id ma brakujące / puste wartości.

Kiedy próbuję wrzucić id kolumnę do liczby całkowitej podczas czytania .csv, dostaję:

df= pd.read_csv("data.csv", dtype={'id': int}) 
error: Integer column has NA values

Alternatywnie próbowałem przekonwertować typ kolumny po przeczytaniu jak poniżej, ale tym razem otrzymałem:

df= pd.read_csv("data.csv") 
df[['id']] = df[['id']].astype(int)
error: Cannot convert NA to integer

Jak mogę sobie z tym poradzić?

Author: crypdick, 2014-01-22

9 answers

Brak Nan rep w kolumnach całkowitych to "gotcha" .

Zwyczajowym obejściem jest po prostu użycie pływaków.

 87
Author: Andy Hayden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 16:15:51

Mój przypadek użycia polega na gromadzeniu danych przed załadowaniem do tabeli DB:

df[col] = df[col].fillna(-1)
df[col] = df[col].astype(int)
df[col] = df[col].astype(str)
df[col] = df[col].replace('-1', np.nan)

Usuń Nan, przekonwertuj na int, przekonwertuj na str, a następnie ponownie włóż Nan.

Nie jest ładna, ale robi swoje!
 3
Author: hibernado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-02 10:28:33

Jeśli możesz zmodyfikować przechowywane dane, Użyj wartości sentinel dla brakujących id. Często używany przypadek, wywnioskowany przez nazwę kolumny, ponieważ id jest liczbą całkowitą, ściśle większą od zera, możesz użyć 0 jako wartości sentinel, aby zapisać

if row['id']:
   regular_process(row)
else:
   special_process(row)
 1
Author: gboffi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-25 08:38:01

Zakładając, że DateColumn sformatowany 3312018.0 powinien zostać przekonwertowany na 03/31/2018 jako łańcuch znaków. I brakuje niektórych rekordów lub 0.

df['DateColumn'] = df['DateColumn'].astype(int)
df['DateColumn'] = df['DateColumn'].astype(str)
df['DateColumn'] = df['DateColumn'].apply(lambda x: x.zfill(8))
df.loc[df['DateColumn'] == '00000000','DateColumn'] = '01011980'
df['DateColumn'] = pd.to_datetime(df['DateColumn'], format="%m%d%Y")
df['DateColumn'] = df['DateColumn'].apply(lambda x: x.strftime('%m/%d/%Y'))
 0
Author: Justin Malinchak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-06 14:45:13

Natknąłem się na ten problem pracując z pyspark. Ponieważ jest to nakładka Pythona dla kodu uruchamianego na jvm, wymaga bezpieczeństwa typu i użycie float zamiast int nie jest opcją. Obejrzałem ten problem, owijając pandy pd.read_csv w funkcję, która wypełni zdefiniowane przez użytkownika kolumny wartościami wypełnienia zdefiniowanymi przez użytkownika przed wysłaniem ich do wymaganego typu. Oto, czego użyłem:

def custom_read_csv(file_path, custom_dtype = None, fill_values = None, **kwargs):
    if custom_dtype is None:
        return pd.read_csv(file_path, **kwargs)
    else:
        assert 'dtype' not in kwargs.keys()
        df = pd.read_csv(file_path, dtype = {}, **kwargs)
        for col, typ in custom_dtype.items():
            if fill_values is None or col not in fill_values.keys():
                fill_val = -1
            else:
                fill_val = fill_values[col]
            df[col] = df[col].fillna(fill_val).astype(typ)
    return df
 0
Author: Neuneck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 08:45:36

Konwertuj na zmiennoprzecinkowy (ignorując błędy), a następnie przekonwertuj wynik na wartość int.

df['id'] = df['id'].astype(float, errors='ignore').astype(int) 

Alternatywnie:

df['id'] = df['id'].replace(np.nan,0) 

A następnie użyj wyrażenia regularnego:

df['id'] = df['id'].astype(int)

W przypadku liczb pierwotnie sformatowanych jako ciągi znaków (np. '35' zamiast 35) pomaga:

df['id'] = df['id'].apply(lambda x: int(x))
 0
Author: Alla Sorokina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 21:42:40

Najpierw usuń wiersze zawierające NaN. Następnie wykonaj konwersję całkowitą na pozostałych wierszach. W końcu Wstaw ponownie usunięte wiersze. Mam nadzieję, że zadziała

 0
Author: kamran kausar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-01 10:05:17

Możesz użyć .dropna(), jeśli można upuścić wiersze z wartościami NaN.

df = df.dropna(subset=['id'])

Alternatywnie, użyj .fillna() i .astype(), aby zastąpić NaN wartościami i przekonwertować je na int.

Napotkałem ten problem podczas przetwarzania pliku CSV z dużymi liczbami całkowitymi, podczas gdy niektórych z nich brakowało (NaN). Użycie float jako typu nie wchodziło w grę, ponieważ mogłem stracić precyzję.

Moim rozwiązaniem było użycie str jako pośredniego typu. Następnie możesz przekonwertować ciąg znaków do int jak chcesz później w kodzie. Zamieniłem NaN na 0, ale można wybrać dowolną wartość.

df = pd.read_csv(filename, dtype={'id':str})
df["id"] = df["id"].fillna("0").astype(int)

Dla ilustracji, oto przykład, jak pływaki mogą stracić precyzję:

s = "12345678901234567890"
f = float(s)
i = int(f)
i2 = int(s)
print (f, i, i2)

A wyjście to:

1.2345678901234567e+19 12345678901234567168 12345678901234567890
 0
Author: elomage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-13 10:35:34

W moim przypadku edytowałem format kolumny csv tzn. zmieniłem format kolumny z ogólnego na numer.Wtedy jestem w stanie zmienić typ w pandach.

df= pd.read_csv("data.csv")
df[['id']] = df[['id']].astype(int)
 -6
Author: Println,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-27 07:20:17