1. ホーム
  2. パイソン

[解決済み】pandasでカラムの種類を変更する

2022-03-23 18:12:43

質問

リストのリストとして表現されるテーブルを Pandas DataFrame . 極端に簡略化した例として

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a)

列を適切な型に変換する最良の方法は何でしょうか。この場合、列 2 と 3 は浮動小数点に変換されます。DataFrameに変換する際に、型を指定する方法はありますか?それとも、最初にDataFrameを作成し、その後、列をループして各列の型を変更する方が良いのでしょうか?理想的には、何百ものカラムがあり、どのカラムがどのタイプであるかを正確に指定したくないので、動的な方法でこれを行いたいと考えています。私が保証できるのは、各カラムが同じ型の値を含んでいることだけです。

どのように解決するのですか?

pandasの型変換には、主に4つのオプションがあります。

  1. to_numeric() - は、非数値型(例えば文字列)を適切な数値型に安全に変換する機能を提供します。(以下も参照 to_datetime() to_timedelta() .)

  2. astype() - は、(ほとんど)あらゆる型を(ほとんど)他の型に変換します(たとえそうすることが必ずしも賢明でない場合でも)。への変換も可能です。 カテゴリー の型があります(非常に便利です)。

  3. infer_objects() - Pythonオブジェクトを保持するオブジェクトカラムを、可能であればpandas型に変換するユーティリティメソッドです。

  4. convert_dtypes() - DataFrameのカラムを、以下のようなD型をサポートする最適なものに変換します。 pd.NA (欠損値を示すpandasのオブジェクト)。

それぞれのメソッドの詳細な説明や使い方は、続きをお読みください。


1. to_numeric()

DataFrameの1つまたは複数の列を数値に変換する最も良い方法は、以下の通りです。 pandas.to_numeric() .

この関数は、文字列などの非数値オブジェクトを、適宜、整数または浮動小数点数に変更しようとする。

基本的な使い方

への入力は to_numeric() は、Series または DataFrame の1カラムです。

>>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
>>> s
0      8
1      6
2    7.5
3      3
4    0.9
dtype: object

>>> pd.to_numeric(s) # convert everything to float values
0    8.0
1    6.0
2    7.5
3    3.0
4    0.9
dtype: float64

ご覧のように、新しいSeriesが返されます。この出力を継続して使用するには、変数またはカラム名に代入することを忘れないでください。

# convert Series
my_series = pd.to_numeric(my_series)

# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])

また、DataFrameの複数カラムを変換するために apply() メソッドを使用します。

# convert all columns of DataFrame
df = df.apply(pd.to_numeric) # convert all columns of DataFrame

# convert just columns "a" and "b"
df[["a", "b"]] = df[["a", "b"]].apply(pd.to_numeric)

値がすべて変換されるのであれば、おそらくそれで十分でしょう。

エラー処理

しかし、ある値が数値型に変換できない場合はどうすればよいのでしょうか。

to_numeric() もまた errors キーワード引数を使用すると、数値以外の値を強制的に NaN または、これらの値を含む列を単に無視する。

以下は、文字列のシリーズを使った例である。 s であり、object dtype を持つ。

>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0         1
1         2
2       4.7
3    pandas
4        10
dtype: object

デフォルトの動作は、値を変換できない場合にレイズすることです。この場合、文字列 'pandas' を扱うことができません。

>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string

失敗するよりも、'pandas' が欠落している/悪い数値と見なされることを望むかもしれません。無効な値を NaN を使用して、以下のように errors キーワード引数を指定します。

>>> pd.to_numeric(s, errors='coerce')
0     1.0
1     2.0
2     4.7
3     NaN
4    10.0
dtype: float64

の3つ目のオプションは errors は、無効な値に遭遇した場合、その操作を無視するだけです。

>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched

この最後のオプションは、DataFrame全体を変換したいが、どのカラムが確実に数値型に変換できるのか分からない場合に特に有効です。その場合は、次のように書けばよい。

df.apply(pd.to_numeric, errors='ignore')

この関数はDataFrameの各列に適用されます。数値型に変換できる列は変換され、変換できない列(例えば、数字以外の文字列や日付を含む)はそのままにされます。

ダウンキャスト

デフォルトでは to_numeric() int64 または float64 dtype (または、お使いのプラットフォームのネイティブな整数幅)。

しかし、メモリを節約して、よりコンパクトなd型を使用したい場合はどうしたらよいでしょうか。 float32 または int8 ?

to_numeric() のどちらかにダウンキャストするオプションがあります。 'integer' , 'signed' , 'unsigned' , 'float' . 以下は、単純なシリーズの例です。 s の整数型です。

>>> s = pd.Series([1, 2, -7])
>>> s
0    1
1    2
2   -7
dtype: int64

にダウンキャストする。 'integer' は、その値を保持できる最小の整数を使用します。

>>> pd.to_numeric(s, downcast='integer')
0    1
1    2
2   -7
dtype: int8

にダウンキャストする。 'float' も同様に、通常より小さなフローティングタイプを選択します。

>>> pd.to_numeric(s, downcast='float')
0    1.0
1    2.0
2   -7.0
dtype: float32


2. astype()

astype() メソッドを使用すると、DataFrame や Series が持つべきデータ型を明示することができます。これは、ある型から他の型に移行することができるという点で、非常に汎用的なものです。

基本的な使い方

NumPyのdtypeを使うことができます。 np.int16 ) 、Pythonの型(例えばbool)、pandas固有の型(例えばcategorical dtype)があります。

変換したいオブジェクトのメソッドを呼び出して astype() が変換を試みます。

# convert all DataFrame columns to the int64 dtype
df = df.astype(int)

# convert column "a" to int64 dtype and "b" to complex type
df = df.astype({"a": int, "b": complex})

# convert Series to float16 type
s = s.astype(np.float16)

# convert Series to Python strings
s = s.astype(str)

# convert Series to categorical type - see docs for more details
s = s.astype('category')

試してみる」と言ったことに注意してください。 astype() がSeriesやDataFrame内の値の変換方法を知らない場合、エラーを発生させます。例えば NaN または inf の値を整数に変換しようとすると、エラーが発生します。

pandas 0.20.0では、このエラーを抑制するために errors='ignore' . 元のオブジェクトはそのまま返されます。

注意すること

astype() は強力ですが、時々、値を不正に変換してしまうことがあります。例えば

>>> s = pd.Series([1, 2, -7])
>>> s
0    1
1    2
2   -7
dtype: int64

これらは小さな整数なので、メモリを節約するために符号なし8ビット型に変換してはどうでしょうか?

>>> s.astype(np.uint8)
0      1
1      2
2    249
dtype: uint8

変換はうまくいったのですが、-7が回り込んで249になってしまいました(つまり、2 8 - 7)!

を使ってダウンキャストに挑戦 pd.to_numeric(s, downcast='unsigned') の代わりに、このエラーを防ぐことができます。


3. infer_objects()

pandas のバージョン 0.21.0 で導入されたメソッドです。 infer_objects() オブジェクトデータ型を持つDataFrameの列をより特定の型に変換する(ソフトコンバージョン)ためのものです。

例えば、ここにオブジェクト型の2つの列を持つDataFrameがあります。一つは実際の整数を保持し、もう一つは整数を表す文字列を保持しています。

>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a    object
b    object
dtype: object

使用方法 infer_objects() で、カラム 'a' の型を int64 に変更することができます。

>>> df = df.infer_objects()
>>> df.dtypes
a     int64
b    object
dtype: object

カラム 'b' はその値が整数ではなく文字列であったため、そのままにしてあります。もし、両方のカラムを強制的に整数型にしたい場合は df.astype(int) の代わりに


4. convert_dtypes()

バージョン1.0以降では、メソッド convert_dtypes() をサポートする最適なデータ型に変換します。 pd.NA の値が欠落している。

ここで、"best possible"とは、値を保持するのに最適な型を意味する。例えば、このpandasの整数型は、すべての値が整数(または欠損値)である場合:Pythonの整数型オブジェクトの列は、以下のように変換されます。 Int64 の列、NumPyの int32 の値が、pandas の d 型になります。 Int32 .

私たちの object DataFrame df とすると、次のような結果が得られる。

>>> df.convert_dtypes().dtypes                                             
a     Int64
b    string
dtype: object

カラム 'a' は整数値を保持しているので、これを Int64 型(欠損値を保持することができる。 int64 ).

列 'b' には文字列オブジェクトが含まれていたため、pandas の string dtypeを使用します。

デフォルトでは、このメソッドは各列のオブジェクトの値から型を推論します。を渡すことでこれを変更することができます。 infer_objects=False :

>>> df.convert_dtypes(infer_objects=False).dtypes                          
a    object
b    string
dtype: object

ここで、カラム 'a' はオブジェクトカラムのままです:pandasは、それが「整数」カラムとして記述できることを知っています(内部では infer_dtype しかし、どのような整数型であるべきかを正確に推論していなかったため、変換しませんでした。列 'b' は 'string' 値を保持していると認識されたので、再び 'string' dtype に変換されました。