NumPy или Pandas: сохранение типа массива как целого с указанием значения NaN

Есть ли предпочтительный способ сохранить тип данных массива numpy фиксированным как int (или int64 или что-то еще), но все еще содержащий элемент внутри, указанный как numpy.NaN?

В частности, я преобразовываю внутреннюю структуру данных в Pandas DataFrame. В нашей структуре у нас есть столбцы целочисленного типа, у которых все еще есть NaN (но dtype столбца - int). Кажется, он переделает все как float, если мы сделаем это DataFrame, но нам бы очень хотелось быть int.

Мысли?

Проверенные вещи:

Я попытался использовать функцию from_records() в pandas.DataFrame, с coerce_float=False, и это не помогло. Я также пробовал использовать маскированные массивы NumPy с NaN fill_value, которые также не работали. Все это привело к тому, что тип данных столбца стал плавающим.

Ответ 2

NaN не может быть сохранен в целочисленном массиве. Это известное ограничение панд на данный момент; Я ждал прогресса в достижении значений NA в NumPy (аналогично NA в R), но пройдет не менее 6 месяцев в году, пока NumPy получит эти функции, кажется:

http://pandas.pydata.org/pandas-docs/stable/gotchas.html#support-for-integer-na

(Эта функция была добавлена начиная с версии 0.24 для панд, но учтите, что для нее требуется расширение dtype Int64 (с заглавной буквы), а не по умолчанию dtype int64 (строчные буквы): https://pandas.pydata.org/pandas- docs/version/0.24/whatsnew/v0.24.0.html # option-integer-na-support)

Ответ 3

Если производительность не является основной проблемой, вы можете сохранить строки вместо этого.

df.col = df.col.dropna().apply(lambda x: str(int(x)) )

Затем вы можете смешать с NaN столько, сколько хотите. Если вы действительно хотите иметь целые числа, в зависимости от вашего приложения вы можете использовать -1 или 0, или 1234567890, или другое выделенное значение для представления NaN.

Вы также можете временно дублировать столбцы: один, как у вас, с поплавками; другой - экспериментальный, с ints или строками. Затем вставляет asserts в каждое разумное место, проверяя, что эти два синхронизированы. После достаточного тестирования вы можете отпустить поплавки.

Ответ 4

Это не решение для всех случаев, но мои (геномные координаты) я прибегал к использованию 0 в качестве NaN

a3['MapInfo'] = a3['MapInfo'].fillna(0).astype(int)

Это, по крайней мере, позволяет использовать собственный тип столбца "native", такие операции, как вычитание, сравнение и т.д. Работают так, как ожидалось

Ответ 5

Панды v0. 24+

Функциональность для поддержки NaN в целочисленных рядах будет доступна в версии v0.24 и выше. Информация об этом содержится в разделе "Что нового" в v0.24, а также в разделе " Тип данных Nullable Integer".

Панды v0.23 и ранее

В общем случае, лучше всего работать с сериями с float где это возможно, даже если ряд переходит с int на float из-за включения значений NaN. Это позволяет векторизовать вычисления на основе NumPy, где в противном случае будут обрабатываться циклы уровня Python.

Документы предлагают: "Одна из возможностей - использовать вместо этого массивы dtype=object ". Например:

s = pd.Series([1, 2, 3, np.nan])

print(s.astype(object))

0      1
1      2
2      3
3    NaN
dtype: object

По косметическим причинам, например, вывод в файл, это может быть предпочтительным.

Панды v0.23 и более ранние: фон

NaN считается float. Документы в настоящее время (по состоянию на v0.23) указывают причину, по которой целочисленные ряды выгружаются для float:

В отсутствие поддержки высокой производительности NA, встроенной в NumPy с нуля, основной жертвой является возможность представлять NA в целочисленных массивах.

Этот компромисс сделан в основном из-за памяти и производительности, а также из-за того, что полученный ряд продолжает оставаться "числовым".

Документы также предоставляют правила для апкастинга из-за включения NaN:

Typeclass   Promotion dtype for storing NAs
floating    no change
object      no change
integer     cast to float64
boolean     cast to object

Ответ 6

Теперь это возможно, поскольку pandas v 0.24.0

Замечания к выпуску pandas 0.24.x Цитата: "У Pandas появилась возможность хранить целочисленные dtypes с пропущенными значениями.

Ответ 7

Просто хочу добавить, что в случае, если вы пытаетесь преобразовать вектор с плавающей точкой (1.143) в целое число (1), в котором преобразование NA в новый тип Int64 Int64, даст вам ошибку. Чтобы решить эту проблему, вы должны округлить числа, а затем выполнить ".astype('Int64')"

s1 = pd.Series([1.434, 2.343, np.nan])
#without round() the next line returns an error 
s1.astype('Int64')
#cannot safely cast non-equivalent float64 to int64
##with round() it works
s1.round().astype('Int64')
0      1
1      2
2    NaN
dtype: Int64

Мой вариант использования состоит в том, что у меня есть серия чисел с плавающей точкой, которую я хочу округлить до int, но когда вы делаете .round(), в конце числа остается "*.0", так что вы можете сбросить этот 0 с конца на преобразование в int.

Ответ 8

Округление с плавающей точкой до целых значений:

Представьте себе серию V панд со смесью положительных поплавков и NaN. Чтобы удалить весь десятичный мусор:

V.fillna(-1).astype(int).replace(-1, np.nan)