カピバラ好きなエンジニアブログ

興味ある技術とか検証した内容を赴くままに書いていきます。カピバラの可愛さこそ至高。

欠損値が混ざってるfloat型データをpandasで整数部のみに変換する方法

pandasを使ったデータ変換をしていてfloat型の列を整数部のみにしたい場合、「astype」などを使用してint型に変換すれば簡単に実現できるかと思いますが、そこに欠損値が含まれている場合うまく変換できなかったので、変換する方法を試してみました。

尚、タイトルで"int型"に変換する方法と書いてないのは理由があります。

目次



準備

テストデータは以下を使用します。

$ cat test.csv
"age","point"
"12","null"
"13","null"
"14","1.0"
"15","null"
"16","2.0"
"17","null"

CSVファイルをpandasで読み込んでおきます。

>>> import pandas as pd
>>> import np
>>> df = pd.read_csv('test.csv')
>>> df
   age  point
0   12    NaN
1   13    NaN
2   14    1.0
3   15    NaN
4   16    2.0
5   17    NaN



できなかったパターン

最初に実現しようとしてできなかったint型に変換するパターンです。
やりたいこととしてはシンプルで、欠損値を一旦別の値に変換してfloat→int変換した後に、欠損値に戻す方法を試しました。
float→int変換については想定通り変換できました。

>>> df['point_int']=df['point'].fillna(99).round().astype('int64')
>>> df
   age  point  point_int
0   12    NaN         99
1   13    NaN         99
2   14    1.0          1
3   15    NaN         99
4   16    2.0          2
5   17    NaN         99

ただ、そのあと欠損値にreplaceで戻そうとした際にデータ型がfloat型に戻ってしまい、本来整数部のみ表示したい1や2が1.0と2.0になってしまいました。
この方法では自分のやりたいことはできませんでした。

>>> df['point_int'].replace(99, np.nan)
0    NaN
1    NaN
2    1.0
3    NaN
4    2.0
5    NaN
Name: point_int, dtype: float64



できたパターン

かなり力技にはなってしまうのですが、自分のやりたいことができたパターンです。
一度文字列型に変換した後、文字列として小数部で除去し欠損値だけ文字列の"nan"から"NaN"に戻すようにしました。
int型にはできませんでしたが、私が今回やりたかったのは整数部のみに変換して文字列としてCSV出力することでしたので、これで特に問題はなかったです。

>>> df['point_str']=df['point'].astype('str').str.replace('\.0','').replace('nan', np.nan)
>>> df
   age  point  point_int point_str
0   12    NaN         99       NaN
1   13    NaN         99       NaN
2   14    1.0          1         1
3   15    NaN         99       NaN
4   16    2.0          2         2
5   17    NaN         99       NaN



感想及び所感

調べてみてもやりたかったことを実現する方法が見つからなかったので、備忘として書きました。
pandasを使う例だと良くデータ分析時の変換方法が出てきて、欠損値を全体の平均値にするなどが散見されたのですが、今回はデータ分析ではなく単純にデータクレンジングの用途で使いたかったので、その方法は取れませんでした。
スマートではない解決方法でしたので、もし他に良いやり方をご存じの方がいれば、ぜひコメントいただけると嬉しいです。