[解決済み】pandasでカラムの種類を変更する
質問
リストのリストとして表現されるテーブルを
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つのオプションがあります。
-
to_numeric()
- は、非数値型(例えば文字列)を適切な数値型に安全に変換する機能を提供します。(以下も参照to_datetime()
とto_timedelta()
.) -
astype()
- は、(ほとんど)あらゆる型を(ほとんど)他の型に変換します(たとえそうすることが必ずしも賢明でない場合でも)。への変換も可能です。 カテゴリー の型があります(非常に便利です)。 -
infer_objects()
- Pythonオブジェクトを保持するオブジェクトカラムを、可能であればpandas型に変換するユーティリティメソッドです。 -
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 に変換されました。
関連
-
[解決済み】"No JSON object could be decoded "よりも良いエラーメッセージを表示する。
-
[解決済み] PandasでDataFrameの行を反復処理する方法
-
[解決済み] 列の値に基づいてDataFrameから行を選択するにはどうすればよいですか?
-
[解決済み] Pandasのカラム名のリネーム
-
[解決済み] オブジェクトの種類を決定しますか?
-
[解決済み] Pandas DataFrameからカラムを削除する
-
[解決済み] Pandasのデータフレームで複数の列を選択する
-
[解決済み] Pandas DataFrameの行数を取得する方法は?
-
[解決済み] Pythonのdictをdataframeに変換する
-
[解決済み】Pandas DataFrameのカラムヘッダからリストを取得する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Python 人工知能 人間学習 描画 機械学習モデル作成
-
PythonはWordの読み書きの変更操作を実装している
-
Python jiabaライブラリの使用方法について説明
-
Pythonコードの可読性を向上させるツール「pycodestyle」の使い方を詳しく解説します
-
任意波形を生成してtxtで保存するためのPython実装
-
[解決済み】終了コード -1073741515 (0xC0000135)でプロセス終了)
-
[解決済み】Django: ImproperlyConfigured: SECRET_KEY 設定は空であってはならない
-
[解決済み】"No JSON object could be decoded "よりも良いエラーメッセージを表示する。
-
[解決済み】Python: SyntaxError: キーワードは式になり得ない
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。