NumPyまたはPandas:NaN値を保持しながら配列型を整数として保持


160

内部に要素がリストされている間に、numpy配列のデータ型をint(またはint64その他の)として固定しておくための好ましい方法はありnumpy.NaNますか?

特に、社内のデータ構造をPandas DataFrameに変換しています。この構造では、整数型の列がまだNaNを持っています(ただし、列のdtypeはintです)。これをDataFrameにすると、すべてをフロートとして再キャストするように見えますが、本当にそうしたいintです。

考え?

試したこと:

私はfrom_records()pandas.DataFrameで関数を使用してみましたがcoerce_float=False、これは役に立ちませんでした。また、NumPyのマスクされた配列をNaN fill_valueで使用しようとしましたが、これも機能しませんでした。これらすべてが原因で、列のデータ型が浮動小数点になりました。


派手なマスクされた配列を使用できますか?
mgilson 2012

やってみます。私もfrom_recordspandas.DataFrameで関数を試してみましたcoerce_float=Falseが、うまくいきませんでした...それでも新しいデータにtypeが含まれfloat64ます。
12

1
ええ、運はありません。マスクされた配列であっても、浮動小数点に変換されます。Pandasは次のように見えます。「どこかにNaNはありますか?...そして、すべてがフロートです。」うまくいけば、これを回避する方法があります。
2012

1
オプションのNullable Integerサポートがpandas 0.24.0に正式に追加されました-最後に:)-以下の更新された回答を見つけてください。パンダ0.24.xリリースノート
モルク

回答:


70

この機能がパンダに追加されました(バージョン0.24以降):https : //pandas.pydata.org/pandas-docs/version/0.24/whatsnew/v0.24.0.html#optional-integer-na-support

この時点では、デフォルトのdtype int64(小文字)ではなく、拡張dtype Int64(大文字)を使用する必要があります。


1
とりあえず、特別なdtypeを指定して機能させる必要があります'Int64'。それがデフォルトで有効になっている場合、それはさらに良くなります。
ジャンポール、

これは素晴らしい!この方法を使用すると、PyCharmがデバッグウィンドウにデータフレームを表示できないという小さな問題があります。:あなたはそれを表示する強制する方法については、別の質問に対する私の答えを参照することができstackoverflow.com/questions/38956660/...を(元の問題は、データフレームワークを表示するためのソリューションが異なりますが、)
アラーM.

使用する'Int64'必要がありますか、または何かあり'Int8'ますか?と比べて、非常に大量のメモリを使用しnp.floatます。
スーパードオペラヒーロー

'Int8'動作しているようにnp.float見えますが、それでもロードはずっと高速のようです。問題は、その間にメモリを解放していないことです。ガベージコレクターが最終的に実行されると仮定します。
スーパードオペラヒーロー

103

NaN整数配列に格納することはできません。これは現時点でパンダの既知の制限です。私はNumPyのNA値(RのNAと同様)で進捗が見られるのを待っていましたが、NumPyがこれらの機能を使用できるようになるまでには、少なくとも6か月から1年かかります。

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#optional-integer-na-support


7
こんにちはウェス、これに関する更新はありますか?元のリストにNA値が存在することに基づいて、結合列がintまたはfloatに変換されるという問題が発生します。(後でこれらのデータフレームをマージしようとするときに問題を作成する)
Carst


8

パフォーマンスが主な問題ではない場合は、代わりに文字列を保存できます。

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

次に、好きなだけ混ぜることができNaNます。あなたが本当にあなたのアプリケーションに応じて、整数を持っているしたい場合は、使用することができ-1、または0、または1234567890、または他のいくつかの専用の値が表すようにNaN

また、一時的に列を複製することもできます。もう1つは、intまたは文字列を使用した実験的なものです。次にasserts、適切な場所すべてに挿入して、2つが同期していることを確認します。十分なテストを行った後、フロートを手放すことができます。


5

これはすべての場合の解決策ではありませんが、私の(ゲノム座標)私は0をNaNとして使用しました

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

これにより、少なくとも適切な「ネイティブ」列タイプを使用でき、減算、比較などの操作が期待どおりに機能します


5

パンダv0.24以降

NaN整数シリーズでサポートする機能は、v0.24以降で使用できます。これに関する情報はv0.24の「新機能」セクションにあり、詳細はNullable Integer Data Typeにあります。

Pandas v0.23およびそれ以前

一般に、値が含まfloatintているfloatためにシリーズがアップキャストされている場合でも、可能な場合はシリーズを使用するのが最善NaNです。これにより、Pythonレベルのループが処理されるベクトル化されたNumPyベースの計算が可能になります。

ドキュメントは示唆しています:「1つの可能性はdtype=object代わりに配列を使うことです。」例えば:

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

print(s.astype(object))

0      1
1      2
2      3
3    NaN
dtype: object

ファイルへの出力などの外観上の理由から、これが望ましいがあります。

Pandas v0.23およびそれ以前:背景

NaNと見なされますfloat現在ドキュメント(v0.23以降)では、整数シリーズが次のようにアップキャストされる理由が明記されていfloatます。

ゼロからNumPyに組み込まれた高性能NAサポートがない場合、主な犠牲は整数配列でNAを表す能力です。

このトレードオフは、主にメモリとパフォーマンスの理由のために行われ、その結果、シリーズは引き続き「数値」になります。

ドキュメントには、包含によるアップキャストのルールも記載されていますNaN

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


1

float(1.143)ベクトルを整数(1)に変換しようとしている場合に、新しい 'Int64' dtypeにNA変換するとエラーが発生するので、これを追加したいだけです。これを解決するには、数値を四捨五入して、「。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に変換します。


0

テキストデータに空白がある場合、int64 dtypeはnullを処理できないため、通常は整数である列がfloat64 dtypeとしてfloatにキャストされます。空白を含む複数のファイルをロードする場合、これはスキーマの不整合を引き起こす可能性があります(float64として終了し、それ以外のファイルではint64として終了します)

Int64はnullを処理できるため、このコードは、任意の数値型の列を(int64ではなく)Int64に変換しようとします。

import pandas as pd
import numpy as np

#show datatypes before transformation
mydf.dtypes

for c in mydf.select_dtypes(np.number).columns:
    try:
        mydf[c] = mydf[c].astype('Int64')
        print('casted {} as Int64'.format(c))
    except:
        print('could not cast {} to Int64'.format(c))

#show datatypes after transformation
mydf.dtypes
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.