Pythonパンダで列のdtypeを確認する方法


130

数値列と文字列列を処理するには、さまざまな関数を使用する必要があります。私が今やっていることは本当にばかげています:

allc = list((agg.loc[:, (agg.dtypes==np.float64)|(agg.dtypes==np.int)]).columns)
for y in allc:
    treat_numeric(agg[y])    

allc = list((agg.loc[:, (agg.dtypes!=np.float64)&(agg.dtypes!=np.int)]).columns)
for y in allc:
    treat_str(agg[y])    

これを行うためのよりエレガントな方法はありますか?例えば

for y in agg.columns:
    if(dtype(agg[y]) == 'string'):
          treat_str(agg[y])
    elif(dtype(agg[y]) != 'string'):
          treat_numeric(agg[y])

2
stringはdtypeではありません
David Robinson

回答:


123

列のデータ型にアクセスするにはdtype

for y in agg.columns:
    if(agg[y].dtype == np.float64 or agg[y].dtype == np.int64):
          treat_numeric(agg[y])
    else:
          treat_str(agg[y])

1
こんにちはデイビッド、== np.float64を含めた理由についてコメントできますか?浮動小数点数に変換しようとしていませんか?ありがとう。
ライアンチェイス

@RyanChaseこの質問のOPは、フロートに変換しているとは決して言っていませんtreat_numeric。(指定されていない)関数を使用するかどうかを知る必要があるだけです。彼agg.dtypes==np.float64はオプションとして含まれていたので、私もやった。
David Robinson

3
より多くの数値型は、下のすべてのものは、これらの2つ以上numpyのでありnumber、ここでは:docs.scipy.org/doc/numpy-1.13.0/reference/arrays.scalars.html一般的な解決策があるis_numeric_dtype(agg[y])
アッティラTanyi

94

ではpandas 0.20.2、あなたが行うことができます。

from pandas.api.types import is_string_dtype
from pandas.api.types import is_numeric_dtype

is_string_dtype(df['A'])
>>>> True

is_numeric_dtype(df['B'])
>>>> True

したがって、コードは次のようになります。

for y in agg.columns:
    if (is_string_dtype(agg[y])):
        treat_str(agg[y])
    elif (is_numeric_dtype(agg[y])):
        treat_numeric(agg[y])

1
古いパンダのバージョンに代わるものはありますか?「api.typesという名前のモジュールはありません。
rph 2018年

2
pandas.core.common.is_numeric_dtypePandas 0.13から存在していて、同じことpandas.api.types.is_numeric_dtypeをしますが、0.19 で支持されて廃止されたと思います
Migwell

それは最もネイティブな答えです。ただし、ここではいくつかの注意点に注意する必要があります。
BeforeFlight 2019年

46

私はこれが少し古いスレッドであることを知っていますが、パンダ19.02では、次のことができます。

df.select_dtypes(include=['float64']).apply(your_function)
df.select_dtypes(exclude=['string','object']).apply(your_other_function)

http://pandas.pydata.org/pandas-docs/version/0.19.2/generated/pandas.DataFrame.select_dtypes.html


1
include[np.number]最初の行とexclude[object]2番目の行で(intと32ビットのfloatも含めるために)おそらく行うでしょう。文字列は、dtypeに関する限りオブジェクトです。実際、オブジェクトに 'string'を含めるとエラーが発生します。
JohnE

1
「string」はサポートされなくなったようです。代わりに「object」を使用する必要があります。しかし、
Bertrand

また、'period'現時点ではdtypeが発生していることにも注意してくださいNotImplementedError(pandas 0.24.2)。したがって、手作りのポストプロセスが必要になる場合があります。
BeforeFlight 2019年

21

質問のタイトルは一般的ですが、質問の本文に記載されている著者の使用例は特定のものです。したがって、他の回答を使用することができます。

ただし、タイトルの質問に完全に回答するには、すべてのアプローチが失敗する可能性あり、再作業が必要になる場合があることを明確にしておく必要があります。(私の意見では)信頼性の順序を下げる際にそれらすべて(およびいくつかの追加)を確認しました。

1. ==(受け入れられた回答)を介してタイプを直接比較する。

これは受け入れられた回答であり、賛成票が最も多いという事実にもかかわらず、この方法はまったく使用すべきではないと思います。実際、このアプローチはここで何度か言及されているように、Pythonでは推奨されていません
1はまだそれを使用したい場合でも、 -のようないくつかのパンダ特有のdtypesに注意する必要がありますpd.CategoricalDTypepd.PeriodDtypeまたはpd.IntervalDtype。ここでは、type( )dtypeを正しく認識するために、extraを使用する必要があります。

s = pd.Series([pd.Period('2002-03','D'), pd.Period('2012-02-01', 'D')])
s
s.dtype == pd.PeriodDtype   # Not working
type(s.dtype) == pd.PeriodDtype # working 

>>> 0    2002-03-01
>>> 1    2012-02-01
>>> dtype: period[D]
>>> False
>>> True

ここでのもう1つの注意点は、型を正確に指摘する必要があることです。

s = pd.Series([1,2])
s
s.dtype == np.int64 # Working
s.dtype == np.int32 # Not working

>>> 0    1
>>> 1    2
>>> dtype: int64
>>> True
>>> False

2. isinstance()アプローチ。

この方法は、これまでの回答では言及されていません。

したがって、型を直接比較することが適切でない場合は、この目的のために組み込みのPython関数を試してみましょうisinstance()
我々はいくつかのオブジェクトを持っていることを前提としていますが、ので、それは、ほんの始まりに失敗したpd.Seriesか、pd.DataFrame単に空の事前定義でのコンテナとして使用することもできるdtypeが、その中の無いオブジェクト:

s = pd.Series([], dtype=bool)
s

>>> Series([], dtype: bool)

しかし、この問題を何らかの方法で克服し、たとえば最初の行の各オブジェクトにアクセスしたい場合、次のようなdtypeをチェックします。

df = pd.DataFrame({'int': [12, 2], 'dt': [pd.Timestamp('2013-01-02'), pd.Timestamp('2016-10-20')]},
                  index = ['A', 'B'])
for col in df.columns:
    df[col].dtype, 'is_int64 = %s' % isinstance(df.loc['A', col], np.int64)

>>> (dtype('int64'), 'is_int64 = True')
>>> (dtype('<M8[ns]'), 'is_int64 = False')

単一の列にデータの種類が混在している場合、誤解を招く可能性があります。

df2 = pd.DataFrame({'data': [12, pd.Timestamp('2013-01-02')]},
                  index = ['A', 'B'])
for col in df2.columns:
    df2[col].dtype, 'is_int64 = %s' % isinstance(df2.loc['A', col], np.int64)

>>> (dtype('O'), 'is_int64 = False')

そして最後にCategory重要なことですが、このメソッドはdtypeを直接認識できません。ドキュメントで述べたように:

カテゴリデータから単一のアイテムを返すと、長さ「1」のカテゴリではなく値も返されます。

df['int'] = df['int'].astype('category')
for col in df.columns:
    df[col].dtype, 'is_int64 = %s' % isinstance(df.loc['A', col], np.int64)

>>> (CategoricalDtype(categories=[2, 12], ordered=False), 'is_int64 = True')
>>> (dtype('<M8[ns]'), 'is_int64 = False')

したがって、この方法もほとんど適用できません。

3. df.dtype.kindアプローチ。

このメソッドは、まだ空でも動作しますpd.Seriespd.DataFramesが、別の問題があります。

まず、一部のdtypeを区別することはできません。

df = pd.DataFrame({'prd'  :[pd.Period('2002-03','D'), pd.Period('2012-02-01', 'D')],
                   'str'  :['s1', 's2'],
                   'cat'  :[1, -1]})
df['cat'] = df['cat'].astype('category')
for col in df:
    # kind will define all columns as 'Object'
    print (df[col].dtype, df[col].dtype.kind)

>>> period[D] O
>>> object O
>>> category O

第二に、私にとって実際にまだ不明確なことは、いくつかのdtypes Noneでも返されます。

4. df.select_dtypesアプローチ。

これはほとんど私たちが望んでいることです。このメソッドはパンダの内部で設計されているため、前述のほとんどのコーナーケースを処理します。空のデータフレームは、numpyまたはpandas固有のdtypeとは異なります。のような単一のdtypeでうまく機能し.select_dtypes('bool')ます。dtypeに基づいて列のグループを選択する場合にも使用できます。

test = pd.DataFrame({'bool' :[False, True], 'int64':[-1,2], 'int32':[-1,2],'float': [-2.5, 3.4],
                     'compl':np.array([1-1j, 5]),
                     'dt'   :[pd.Timestamp('2013-01-02'), pd.Timestamp('2016-10-20')],
                     'td'   :[pd.Timestamp('2012-03-02')- pd.Timestamp('2016-10-20'),
                              pd.Timestamp('2010-07-12')- pd.Timestamp('2000-11-10')],
                     'prd'  :[pd.Period('2002-03','D'), pd.Period('2012-02-01', 'D')],
                     'intrv':pd.arrays.IntervalArray([pd.Interval(0, 0.1), pd.Interval(1, 5)]),
                     'str'  :['s1', 's2'],
                     'cat'  :[1, -1],
                     'obj'  :[[1,2,3], [5435,35,-52,14]]
                    })
test['int32'] = test['int32'].astype(np.int32)
test['cat'] = test['cat'].astype('category')

そのように、ドキュメントに記載されているように:

test.select_dtypes('number')

>>>     int64   int32   float   compl   td
>>> 0      -1      -1   -2.5    (1-1j)  -1693 days
>>> 1       2       2    3.4    (5+0j)   3531 days

ここでは、最初に予期しない(以前は私のために使用されていた:質問)結果TimeDeltaが表示されると考えるかもしれません- 出力に含まれていますDataFrame。しかし、反対に答えられるように、それはそうであるべきですが、それを認識する必要があります。注意boolDTYPEはスキップされ、それはまた、誰かのために望ましくないことがありますが、それはのためにだboolnumber違う「にあるサブツリー numpyのdtypesの」。boolの場合、test.select_dtypes(['bool'])こちらを使用することがあります。

このメソッドの次の制限は、現在のバージョンのパンダ(0.24.2)では、このコードtest.select_dtypes('period')はを発生させるということNotImplementedErrorです。

また、他のオブジェクトと文字列を区別することはできません。

test.select_dtypes('object')

>>>     str     obj
>>> 0    s1     [1, 2, 3]
>>> 1    s2     [5435, 35, -52, 14]

しかし、これは最初です-すでにドキュメントで言及されています。そして2番目-このメソッドの問題ではなく、文字列の格納方法DataFrameです。しかし、とにかく、このケースにはいくつかの後処理が必要です。

5. df.api.types.is_XXX_dtypeアプローチ。

これは、私が想定しているように、dtype認識(関数が存在するモジュールのパスはそれ自体で言う)を実現するための最も堅牢でネイティブな方法であることを意図しています。そして、それはほぼ完璧に機能しますが、それでも少なくとも1つの注意点があり、文字列の列を何らかの方法で区別する必要があります

その上、これは主観的である可能性がありますが、このアプローチには、より「人間が理解できる」numberdtypesグループ処理があり.select_dtypes('number')ます。

for col in test.columns:
    if pd.api.types.is_numeric_dtype(test[col]):
        print (test[col].dtype)

>>> bool
>>> int64
>>> int32
>>> float64
>>> complex128

いいえtimedeltabool含まれています。完璧です。

私のパイプラインは、現時点でまさにこの機能を利用しており、少し後処理も行っています。

出力。

すべての議論のアプローチを使用することができるが、唯一のこと-希望私は、引数に要点ができましたpd.DataFrame.select_dtypes()し、pd.api.types.is_XXX_dtype実際に適用されるものと考えるべきです。


1
素晴らしく、よく定式化された答え。:-)
オリバー

7

データフレーム列のタイプを文字列としてマークしたい場合は、次のようにします。

df['A'].dtype.kind

例:

In [8]: df = pd.DataFrame([[1,'a',1.2],[2,'b',2.3]])
In [9]: df[0].dtype.kind, df[1].dtype.kind, df[2].dtype.kind
Out[9]: ('i', 'O', 'f')

あなたのコードに対する答え:

for y in agg.columns:
    if(agg[y].dtype.kind == 'f' or agg[y].dtype.kind == 'i'):
          treat_numeric(agg[y])
    else:
          treat_str(agg[y])

4

列のデータ型をきれいに出力するには

たとえば、ファイルからのインポート後にデータ型を確認するには

def printColumnInfo(df):
    template="%-8s %-30s %s"
    print(template % ("Type", "Column Name", "Example Value"))
    print("-"*53)
    for c in df.columns:
        print(template % (df[c].dtype, c, df[c].iloc[1]) )

例示的な出力:

Type     Column Name                    Example Value
-----------------------------------------------------
int64    Age                            49
object   Attrition                      No
object   BusinessTravel                 Travel_Frequently
float64  DailyRate                      279.0
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.