Python実践データ分析100本ノック ~11 - 20本目~
Python実践データ分析100本ノックをはじめました。
ノックして気付いたことや応用したことなどを、残していこうかと思います。
1〜10本目はサクッと終わらせたので、11本目以降で詰まったところや気になったところを書いていきます。
100本目まで連載したいと思ってます。
ノック15 SettingWithCopyWarningが発生
欠損値を穴埋めする作業において、locを使って、欠損箇所を指定、そこに代入をおこなうというコードがありました。
for trg in list(uriage_data.loc[flg_is_null, "item_name"].unique()):
price = uriage_data.loc[(~flg_is_null) & (uriage_data["item_name"] == trg), "item_price"].max()
uriage_data["item_price"].loc[(flg_is_null) & (uriage_data["item_name"] == trg)] = price
結果
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
self._setitem_with_indexer(indexer, value)
実行自体は出来ていて、欠損値も埋まるのですが、warningが表示されました。
warningなので、そこまで問題ではないのですが、意図しない処理になっていると不安なので、warningが出ない方法を調べてみました。
対策
for trg in list(uriage_data.loc[flg_is_null, "item_name"].unique()):
price = uriage_data.loc[(~flg_is_null) & (uriage_data["item_name"] == trg), "item_price"].max()
uriage_data.loc[(flg_is_null) & (uriage_data["item_name"] == trg), ["item_price"]] = price
コード詳細
Before:
uriage_data["item_price"].loc[(flg_is_null) & (uriage_data["item_name"] == trg)] = price
After:
uriage_data.loc[(flg_is_null) & (uriage_data["item_name"] == trg), ["item_price"]] = price
どうやらloc関数の正しい使い方としては、
データフレームの列まで指定してデータを渡すのでは無く、
データフレームを渡してloc利用時に、列を指定してあげるほうが使い方としてふさわしいそうです。
ノック18 結合(Join)の注意点
前処理として非常によく使うjoinです。
今回は例題で、left joinをしました。
最近、郵便番号の入っている顧客データに、郵便局発行の郵便番号データの地名を入れるという作業をした際に、join後にデータ増えることがありました。
その原因を注意点として書いておこうと思います。
(「join データ増える」とかで検索しても全然出てこなかったので、備忘録も兼ねて…)
原因
right側のデータフレームに同じキーが存在したから。
郵便局発行のデータには同じ郵便番号で複数の地名が登録されていました。
小さい町や地域は、同じ郵便番号が振られるのですが、これが郵便番号は同じで複数行にわたって登録されているため、joinをするとデータ増えてしまいました。
以下、わかりやすく抜粋したコードを記載します。
データフレームを作成します。
同じ郵便番号(680546)を2行、仕込みました。
df1 = pd.DataFrame({'名前': ['さかた', 'はぎわら', 'いけだ'], '郵便番号': [680546, 9042162, 770013]})
df2 = pd.DataFrame({'郵便番号': [680546, 680546, 770013, 9042162], 'c': ['南部青葉町', '南部菊水町', '潮静', '海邦町']})
print(df1)
print(df2)
名前 郵便番号
0 さかた 680546
1 はぎわら 9042162
2 いけだ 770013
郵便番号 地域名
0 680546 南部青葉町
1 680546 南部菊水町
2 770013 潮静
3 9042162 海邦町
pd.merge(df1, df2, on="郵便番号", how="left")
名前 郵便番号 地域名
0 さかた 680546 南部青葉町
1 さかた 680546 南部菊水町
2 はぎわら 9042162 海邦町
3 いけだ 770013 潮静
joinした後のデータが4行になっています!
さかたさんが、2行あり、郵便番号は同じで、地域名が異なっております。
対策
じゃあ、どうすればよいのか、ということですが、join前に、郵便番号が重複している箇所が存在しないようにしておくのが、オススメです。
例えば、以下のような行にしたり…
680546 南部青葉町, 南部菊水町
現実には、キレイなデータばかりではないので、結果に違和感があれば、データをよく調べてみることが必要だと改めて思いました。
いつもありがとうございます! いただいたサポートは開発費(サーバー運用費)などに使わせていただきます!