目的
以下のワーニングが出ないようにする!(このWarningが出るコードは以下に示す)
aa.py:5: 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 the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
d['col3']= d['col2'] * 3
col1 col2 col3
0 1 2 6
2 1 2 6
とりあえず、書いてあるリンクを見てみる
dfmi.loc[:,('one','second')] = value
# becomes
dfmi.loc.__setitem__((slice(None), ('one', 'second')), value)
とか書いてある。
問題のコード
aa.py
import pandas as pd
data = pd.DataFrame([[1,2],[2,3],[1,2],[2,3]], columns=['col1','col2'])
d = data[data['col1'] == 1]
d['col3']= d['col2'] * 3
print(d)
これを実行すると上記のWarningが出る。
問題は、以下の一行にある。
d = data[data['col1'] == 1]
ここを、d = data
とすれば、うえのWarningがでない。
原因&解決策1
dataはcol1==1以外の値もあるので、col1==1だけ切り取ってきたDFに新しいColumnを追加しようとすると、おかしなことになるので、Copyしたものにして、予めcol1==1しかないDFを作ればよい。
修正後
d = data[data['aa'] == 2].copy()
原因&解決策2
上記のlink内で言っている支持の通り.loc
を使って、対応するところ部分だけを更新する。
修正後
# col1が1の条件に当てはまるもののcol3(新しいColumn)にValue(右辺)を入れる
data.loc[data['col1'] == 1, 'col3'] = data['col2'] * 3
# dataからcol1が1の部分だけを取り出す
d = data[data['col1'] == 1]
print('data:\n %s' % data)
print('d:\n%s' % d)
結果
data:
col1 col2 col3
0 1 2 6
1 2 3 NaN
2 1 2 6
3 2 3 NaN
d:
col1 col2 col3
0 1 2 6
2 1 2 6