見出し画像

Python実践データ分析100本ノック ~11 - 20本目~



Python実践データ分析100本ノックをはじめました。

https://amzn.to/3kFLfku

ノックして気付いたことや応用したことなどを、残していこうかと思います。

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 南部青葉町, 南部菊水町 

現実には、キレイなデータばかりではないので、結果に違和感があれば、データをよく調べてみることが必要だと改めて思いました。








いつもありがとうございます! いただいたサポートは開発費(サーバー運用費)などに使わせていただきます!