日々の学びと煩悩

データフレーム全体のデータ型をastypeで一括変換したかった

が、全然されない。なんでや!!となったのでメモ。

状況

数値データを前処理して、ある特定の列に含まれる文字を置換 → 型を object から int (あるいは float) に変更したい

その後列同士を引き算して特徴量を作りたかったが TypeError、文字列は置換して数値データにしたハズなのになんで??? めっちゃ詰まった。

# d 列だけ型が違う
print(df.dtypes)
# a    int64
# b    int64
# c    int64
# d    object

# 前処理して変換(したつもり)
df = df.replace({'7..4': 74, '10未満': 10}).astype('int64')
# 新しい特徴量を作成したかった
df['d-a'] = df['d'] - df['a']

# TypeError: Cannot compare types 'ndarray(dtype=int64)' and 'str'

原因

replace メソッドではデータフレーム全体に対して特定の要素を複数置換させることができるが、astype メソッドは、全ての列の型が一致していること が必要。特定の列だけ型が違っていた場合、全体変換することができない。

(例)

OK な例

print(df.dtypes)
# a    int64
# b    int64
# c    int64
# d    int64

df_f = df.astype('float64')
print(df_f.dtypes)
# a    float64
# b    float64
# c    float64
# d    float64

NG な例

print(df.dtypes)
# a    int64
# b    int64
# c    int64
# d    object

df_f = df.astype('float64')
print(df_f.dtypes)
# a    int64
# b    int64
# c    int64
# d    object

解決策

前処理で値を変換した後、

  1. データフレーム全体で変換する場合列を指定する
  2. 列個別に astype で変換する (元のデータフレームを変更)
# 1
df_icol = df.astype({'d': 'int64'})
# 2
df['d'] = df['d'].astype('int64')

結論:データフレーム全体を操作するときは注意

普通、データフレームに対する処理は列ごとにする。なぜなら特徴量が列ごとにあることが多いから。

今回なんでデータフレーム全体を処理したいかと言うと、ワイドフォーマット形式のパネルデータを扱っていたから。

  • パネルデータとは:複数の個体が複数時点に渡って観測されているデータ。(例) 2013-2015年の大学の学部別志願者数・受験者数
  • 時系列データとは:一つの個体が複数時点に渡って観察されているデータ。(例) 株価
  • ワイドフォーマットは、時点がカラム、行が1サンプルになっている横並びデータのこと。

具体的に自分が扱っていたデータは、下図のように、一定期間ごとに観測された患者の検査値データがあって、検査の種類ごとにデータが分かれていた。

f:id:wimper_1996:20200916115734p:plain

データの型は1つのデータフレームの中で統一のものだったので、一気に型変換や値の抽出を行いたかったのだ。

上で遭遇したエラー以外にも、例えばデータフレーム全体に条件式を適用させようとしても、想定通りにならないことがある。

(例) BMI 値が外れ値となっている患者(行)を抽出したい。

通常、列に条件式を適用させれば抽出することができる。

#  '2008-10' に BMI 値が45以上の人を抽出
df[df['2008-10'] > 45]

f:id:wimper_1996:20200916120534p:plain
条件に合う行が抽出される

# データ全体に条件式を適用させようとする
df[df > 45]

f:id:wimper_1996:20200916120629p:plain
抽出されない

ただこのサイト では、要素で抽出できる例があった。

どうなんだろう、、、 結局自分は、カラムごとに for 文を回して、条件に合うインデックスを検索して抽出する方法を取った。

内容が間違っていたら、指摘いただけると嬉しいです。

参考: https://note.nkmk.me/python-pandas-dtype-astype/