はじめに~本記事作成の経緯~
業務中にリファクタリングを行っていましたが pd.concatを行っている箇所で FutureWarningが発生していました。具体的にはデータフレームを結合する際に空のデータフレームが混入したこと、これが警告発生の原因でした。私は業務にて、その対処を行っていましたが同様の現象が発生した場合に備えて、一つの対処法としてテンプレ化して再利用できる形にすれば誰でも簡単に対処ができると考え、本記事で皆さんに共有しようと思います。初心者のうちは警告やエラーを見るとびっくりすると思いますが対処法を知ってしまえばもう怖くないと思いますので本記事でテンプレ化された対処法を覚えていきましょう。
そもそも FutureWarningとは?
FutureWarning は「今は動くが、将来のバージョンでは動かなくなる可能性がある」ことを知らせる警告です。すなわち、この警告が出ている段階で修正を行わないと将来的にバグが発生する可能性があります。
今回の警告が発生したケース
A. 警告が発生するサンプルコード
この警告を実際に発生させる簡単なサンプルコードを見てみましょう。
import pandas as pd
# データフレーム準備
df1 = pd.DataFrame(
{
"A": [1, 2, 3],
"B": [4, 5, 6]
}
)
df2 = pd.DataFrame(
{
"A": [7, 8, 9],
"B": [10, 11, 12]
}
)
# 空のデータフレーム
df3 = pd.DataFrame()
# データフレームを結合(警告発生箇所)
df_result = pd.concat(
[df1, df2, df3],
ignore_index=True
)
print(df_result)
このコードの問題点は以下の部分です。
df_result = pd.concat(
[df1, df2, df3],
ignore_index=True
)
この部分では三つのデータフレームを結合していますが問題は df3が空であるため、警告が発生しています。具体的にはこのような警告が出力されます。
FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated.
In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes.
B. 警告を回避したサンプルコード
この警告に対して、私が業務上で対処した方法は以下の通りです。
import pandas as pd
# データフレーム準備
df1 = pd.DataFrame(
{
"A": [1, 2, 3],
"B": [4, 5, 6]
}
)
df2 = pd.DataFrame(
{
"A": [7, 8, 9],
"B": [10, 11, 12]
}
)
# 空のデータフレーム
df3 = pd.DataFrame()
# データフレームを結合
# 1.結合したいデータフレームをリストでまとめる
frames = [df1, df2, df3]
# 2.空のデータフレームを除外する
nonempty_frames = [f for f in frames if not f.empty]
# 3.結合処理
df_result =pd.concat(
nonempty_frames,
ignore_index=True
)
print(df_result)
具体的に見ていきましょう。先ほどのデータフレームの結合処理は pd.concatに結合したいデータフレームをそのまま渡していましたが今回は渡す前に前処理を行ってから渡しています。
# データフレームを結合
# 1.結合したいデータフレームをリストでまとめる
frames = [df1, df2, df3]
# 2.空のデータフレームを除外する
nonempty_frames = [f for f in frames if not f.empty]
# 3.結合処理
df_result =pd.concat(
nonempty_frames,
ignore_index=True
)
それでは順番に見ていきましょう。
対処法解説
1. 結合したいデータフレームをリスト化する
frames = [df1, df2, df3]
このフェーズではエラーが発生していたコードで pd.concatに渡していたデータフレームをリスト化しています。厳密にいえば必ずしも必要な処理ではありませんが可読性を高めるために行っています。
2. 空のデータフレームを除外する
nonempty_frames = [f for f in frames if not f.empty]
このフェーズでは第一フェーズでリスト化した結合したいデータフレーム一つ一つに対して、空判定を行い、空でないものだけ新しいリストに追加しています。具体的には framesの要素を順番に変数 fへ代入して、f.emptyで空判定を行っています。これはDataFrame.emptyという pandasライブラリの DataFrameAPIのプロパティであり、空のデータフレームの場合は Trueを返します。そのため、if notで条件式を反転させることで空ではないデータフレームの場合のみ、新しいリストに追加されます。すなわち、このフェーズが終了した際、リスト nonempty_framesには空ではないデータフレームのみ格納されているのです。
3. 安全に結合する
df_result =pd.concat(
nonempty_frames,
ignore_index=True
)
最終フェーズで前処理を行ったデータフレームのリストを pd.concatに渡して、結合処理を行います。ここまでの一連の処理を行うことで以前のコードと同じ結合結果を返しつつ、将来的なアップデートがあってもバグが発生しない、堅牢なコードが完成しました。
まとめ
以上の通り、本記事の処理に改修することで堅牢なコードを作成できて、最初はギョッとした警告文でもたった3行で回避することができました。今回扱った警告をはじめ、警告やエラーは対処法すら知っておけば簡単に回避できるものも多いです。そのため、知っているかどうかで対処の可否だけではなく警告やエラーに対する苦手意識すらも払拭できると思います。これからも実際の業務で体験した初心者が苦手意識を持ちそうな警告やエラーの対処法をまとめていこうと思います。