pandasのDataFrameをconcatすると型が変わってしまう場合の対処法
<pandasのDataFrameをconcatすると型が変わってしまう場合の対処法>*1
※ 2020/03/14にQrunchで書いた記事を移行しました。
pandasのDataFrameを連結する際はconcat
を使用します。
このとき、DataFrameにNaNが含まれていると型が変わってしまう場合があります。
起きた事象
dtypeがintの列を結合するとき、結合元のいずれかにNaNが含まれていると、結合後にdtypeがfloatに変わってしまいました。
int_df1 = pd.DataFrame(data=[0, 1, 2, 3, 4], columns=['Int']) int_df2 = pd.DataFrame(data=[np.nan, 6, 7, 8, 9], columns=['Int']) int_df3 = pd.concat([int_df1, int_df2]) print(int_df3['Int'].dtype) # float64
結合元のdtypeを確認すると、NaNを含む方はfloatになっていました。
print('int_df1:', int_df1['Int'].dtype) print('int_df2:', int_df2['Int'].dtype)
NaNはfloat型
np.nanはfloat型なので、int型の中にnp.nanが含まれているとfloat型と認識されてしまいます。 文字列などのobject型の場合は、NaNが含まれていてもobject型のままです。
obj_df1 = pd.DataFrame(data=['0', '1', '2', '3', '4'], columns=['Object']) obj_df2 = pd.DataFrame(data=[np.nan, '6', '7', '8', '9'], columns=['Object']) obj_df3 = pd.concat([obj_df1, obj_df2], ignore_index=True) print(obj_df3['Object'].dtype) # object
対処法1
DataFrameを作成する際にdtypeを明示的にInt64
と指定します。
すると、concatによる結合後も'dtypeはInt64'のままになっています。
int_df1 = pd.DataFrame(data=[0, 1, 2, 3, 4], columns=['Int'], dtype='Int64') int_df2 = pd.DataFrame(data=[np.nan, 6, 7, 8, 9], columns=['Int'], dtype='Int64') int_df3 = pd.concat([int_df1, int_df2], ignore_index=True) print(int_df3['Int'].dtype) # Int64
対処法2
結合後にNaNを他の値に変更してから、dtypeをInt64
に変更する方法もあります。
この場合、対処法1とは異なりNaNが保持されず別の値に変わることになります。
int_df1 = pd.DataFrame(data=[0, 1, 2, 3, 4], columns=['Int']) int_df2 = pd.DataFrame(data=[np.nan, 6, 7, 8, 9], columns=['Int']) int_df3 = pd.concat([int_df1, int_df2], ignore_index=True) # NaNを0で埋める int_df3.fillna({'Int':0 }, inplace=True) # 'Int'列の型を変更する int_df3 = int_df3.astype( {'Int': 'Int64'} ) print(int_df3['Int'].dtype) # Int64
終わりに
世の中に存在する実データは欠損(NaN)を含む場合が多いので、対処法を知っておいて損はないと思います。 上に記載した内容の詳しい説明は、pandasのUserGuideに載っています。 Nullable integer data type — pandas 1.0.2 documentation
*1:Gerd AltmannによるPixabayからの画像