1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

pandas.queryからの値の更新はできない(chained indexing)

Posted at

numpy & pandasの講座の演習課題でハマったのでメモ。

環境は、anaconda3でまとめてインストールした、python3.6.5、pandas0.23.0

DataFrameの値を変更したいときはqueryではなくlocを使う。

例えばこんなDataFrameがあったとする

In [2]: df = pd.DataFrame({"score":[10, 20, 30],
   ...:                   "address":["Kashiwa", "Matsudo", "Noda"],
   ...:                   "weight":[70, 80, 90]},
   ...:                  columns = ["score", "weight", "address"])
   ...: df.index = ["Taro", "Jiro", "Hanako"]
   ...: df
   ...:                  
Out[2]: 
        score  weight  address
Taro       10      70  Kashiwa
Jiro       20      80  Matsudo
Hanako     30      90     Noda

で、これをlocで絞り込んでから更新するとこう。

In [3]: df.loc["Taro", "weight"]  = 123
   ...: df.loc["Taro", "weight"]
Out[3]: 123.0

これが正解。同じことをDataFrame.queryでできないのかな?と思ってやってみるとこんな感じになる

In [4]: df.loc["Taro", "weight"]  = 70
   ...: 
   ...: df.query("index == 'Taro'").weight = 123
   ...: df.loc["Taro", "weight"]
   ...: 
   ...: 
/anaconda3/lib/python3.6/site-packages/pandas/core/generic.py:4401: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self[name] = value
Out[4]: 70.0

なんかWarningが出て更新されない。

理由

出力されたWarningの中に示されているドキュメントhttp://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copyをみてみると、どうもlocで絞り込んだ場合と [] によるスライスを連続して書いた場合ではインタプリタの評価が違うらしい。chained indexing (インデックスの連鎖?)の問題というらしい。

以下、ドキュメントからの引用。

locだとこんな感じにインタプリタが解釈するが

dfmi.loc[:,('one','second')] = value
# becomes
dfmi.loc.__setitem__((slice(None), ('one', 'second')), value)

[]を連続させるとこう。

dfmi['one']['second'] = value
# becomes
dfmi.__getitem__('one').__setitem__('second', value)

で、こんな感じの説明が書いてある(だいぶ意訳)

__getitem__があるのが分かるだろうか?シンプルな場合を除いては、後者の表現が参照(view)を返すかコピーを返すかを予測するのは難しい。(その時のメモリ配置による。で、その配置についてはpandasは保証できない) よって__setitem__がdfmiを更新するか、一時オブジェクト(その後すぐ捨てられる)を更新するのかは誰にもわからない。そ ん な わ け で SettingWithCopy警告が出るのだ!

今回私がやってしまったようなqueryで絞り込み -> 列名でスライスした場合も同じことが起きると思われる。

ハンズオンの講座でやっていたときはなぜかWarningも出なかったので困った。後でDataFrame.queryのドキュメントを見て、そこから上記のindexingのページhttp://pandas.pydata.org/pandas-docs/stable/indexing.htmlに行って解決。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?