Masa-Kawa
@Masa-Kawa (Masa Kawaguchi)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【Pandas】 df.loc[]を用いて文字列の置換をするにはどうしたらよいでしょうか

解決したいこと

pythonのpandasでデータの前処理を行っています。
文字列操作でよくわからないので教えてください。

発生している問題・エラー

データの前処理において文字列操作。置換、消去などを行っています。

Python実践データ分析の本1や文字列説明サイトでは下記の方法が示されています。

df['']= df[''].str.replace('','')
df['']= df[''].str.rstrip('')

実際、快適に働くのですが何やらエラーメッセージが出現します。

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

df.locを使えとのことですが参照ページをみても単なる代入ならともかく、df.loc[]をつかった置換や特定の文字の消去などの方法がわかりません。

よい解決策があれば教えてください。

背景情報

Python, Pandasの初心者です。独学でデータ管理に挑戦しています。
Python 3.8.3
pandas 1.2.1


  1. 秀和システム Python実践データ分析100本ノック 

0

2Answer

結論から言うと、

  • バージョンアップ後の後方互換性を考えないなら、警告を無視する。
  • 後方互換性を考えるなら公式の言う通りlocを使う。

です。


せっかくですから解説的なものも書きましょう。

メッセージはchained indexing/assignmentに関する警告ですね。
続けて[].loc[]を使うことをchained indexingといい、これが予期せぬエラーを引き起こすことが多く、公式が親切に警告を出してくれているようです。

DataFrameのスライスの仕方によって、ビューを返したり、コピーを返したりするため、この予期せぬエラーが引き起こされます。

ビューは、スライス後の変数の参照元が元のDataFrameの要素と同じです。すなわち、直接アクセスして操作するイメージですね。

一方、コピーは値は同じだが元のDataFrameと参照元が異なります。スライスした後のものに操作を行っても元のDataFrameは変化しません。

chained indexingについてさらに詳しく知りたい場合はpandasのSettingWithCopyWarningの対処法を参照してください。

さて、結論の内容に話を戻しましょう。

当該のDataFrameがどのような構造で、質問者さんがどのようなスライスの仕方をしているかはわかりませんが、現状問題が起きていないならばきちんとビューが返されており、元のDataFrameを操作できているのでしょう。

今回のコードが一時的なもので後のことを気にしないなら、警告は無視してかまいません。

コードを年単位で保守する場合は後方互換性を考える必要があるため、公式に従ってlocを用いる書き方をするのが良いですが、当該のDataFrameがどのようなものかわからないので何とも言えません。

ここでは、以下の書き方の何が問題なのかを説明しておきます。

df['']= df[''].str.replace('','')

問題になるのは、代入文の左側のスライスです。
右側は元のDataFrameに代入するので、ビューでもコピーでも何でも構いません。

左側のスライスの仕方によってはコピーを返されてしまうため、元のDataFrameを操作したことにならず、予期せぬ挙動を招きます。

したがって、右側のスライスは何でもいいけど、左側のスライスはloc[row_indexer, col_indexer]のようにしてきちんとビューを返すようにしましょう。

1Like

Comments

  1. @Masa-Kawa

    Questioner

    詳細な解答ありがとうございます。難解な部分もありますがついていこうと思います。
    とりあえず、df.locなしでも当座はOKということで理解しました。

    もう一つ、右側は問題ではなく、左側が問題だということを教えていただきました。
    簡単な例を書いてみますのでお願いします。

例を示します。

import pandas as pd
import numpy as np

ls1 = ["種無しぶどう","りんご","種無しスイカ"]
ls2 = [1200,1500,1400]
df = pd.DataFrame(list(zip(ls1,ls2)), columns = ['果物','金額'])
print(df)

上記のデータフレームから、種無しを抜いた果物の名前にしたいと思います。

df.loc[:,'果物']=df['果物'].str.lstrip('種無し')

print(df)

問題は右側ではなくて、左をしっかりdf.locで示せばよいという理解でよろしいでしょうか。
それなら、置換も文字の消去も問題なくできると考えます。

ありがとうございました。

1Like

Your answer might help someone💌