Преобразование столбца Pandas, содержащего NaNs, в dtype ' int`

Я читаю данные из a .csv-файл для фрейма данных Pandas, как показано ниже. Для одной из колонок, а именно id, Я хочу указать тип столбца как int. Проблема в id серия имеет отсутствующие / пустые значения.

когда я пытаюсь бросить id столбец в целое число при чтении .csv, я получаю:

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

альтернативно, я попытался преобразовать тип столбца после чтения, как показано ниже, но на этот раз я получаю:

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

как я могу решить это?

9 ответов


отсутствие NaN rep в целочисленных столбцах является панды "Гоча".

обычный обходной путь-просто использовать поплавки.


мой вариант использования-это munging data перед загрузкой в таблицу 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)

удалить NaNs, преобразовать в int, преобразовать в str, а затем повторно вставить NANs.

Это не красиво, но он получает работу!


если вы можете изменить сохраненные данные, используйте значение sentinel для missing id. Общий вариант использования, выводимый именем столбца, является то, что id является целым числом, строго больше нуля, вы можете использовать 0 как значение sentinel, так что вы можете написать

if row['id']:
   regular_process(row)
else:
   special_process(row)

Предположим ваш DateColumn отформатирован 3312018.0 должны быть преобразованы в 03/31/2018 как струна. И некоторые записи отсутствуют или 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'))

я столкнулся с этой проблемой, работая с pyspark. Поскольку это интерфейс python для кода, запущенного на jvm, он требует безопасности типов, и использование float вместо int не является опцией. Я работал над проблемой, обернув панд pd.read_csv в функции, которая будет заполнять пользовательские столбцы пользовательскими значениями заполнения перед приведением их к требуемому типу. Вот что я в итоге использовал:

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

преобразовать в float (игнорируя ошибки), а затем преобразовать результат в int.

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

кроме того:

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

а затем используйте регулярное выражение:

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

в случае чисел, первоначально отформатированных как строки (например, " 35 " вместо 35), помогает следующее:

df['id'] = df['id'].apply(lambda x: int(x))

Сначала удалите строки, содержащие NaN. Затем выполните преобразование целых чисел в оставшихся строках. Наконец, снова вставьте удаленные строки. Надеюсь, это сработает


можно использовать .dropna() если это нормально, чтобы удалить строки со значениями NaN.

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

в качестве альтернативы, использовать .fillna() и .astype() заменить NaN значениями и преобразовать их в int.

я столкнулся с этой проблемой при обработке CSV-файла с большими целыми числами, в то время как некоторые из них отсутствовали (NaN). Использование float в качестве типа не было вариантом, потому что я мог потерять точность.

моим решением было использовать str в качестве промежуточного тип. Затем вы можете преобразовать строку в int, как вам будет угодно позже в коде. Я заменил NaN на 0, но вы можете выбрать любое значение.

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

для иллюстрации, вот пример того, как поплавки могут потерять точность:

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

и выход:

1.2345678901234567e+19 12345678901234567168 12345678901234567890

в моем случае я отредактировал формат столбца csv, т. е. изменил формат столбца с общего на число.Тогда я могу изменить тип в панд.

df= pd.read_csv("data.csv")
df[['id']] = df[['id']].astype(int)