Преобразовать столбец панды, содержащий 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 77

9 ответов:

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

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

мой случай использования-это munging данных перед загрузкой в таблицу БД:

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)