コードサンプル
# My code
df.loc[0, 'column_name'] = 'foo bar'
Pandas 20.3のこのコードは、SettingWithCopyWarningをスローし、
「代わりに.loc[row_indexer,col_indexer] = value
を使用してみてください」。
私はすでにそうしています、小さなバグがあるようです。 Jupyterを使用しています。
ありがとうございました! :)
pd.show_versions()
出力コミット:なし
python:3.6.1.final.0
python-ビット:64
OS:Windows
OSリリース:8.1
マシン:AMD64
プロセッサー:Intel64ファミリー6モデル61ステッピング4、GenuineIntel
バイトオーダー:少し
LC_ALL:なし
言語:なし
ローカル:なし。なし
パンダ:0.20.1
pytest:3.0.7
ピップ:9.0.1
setuptools:35.0.2
Cython:0.25.2
numpy:1.12.1
scipy:0.19.0
xarray:なし
IPython:5.3.0
スフィンクス:1.5.6
patsy:0.4.1
dateutil:2.6.0
pytz:2017.2
blosc:なし
ボトルネック:1.2.1
表:3.2.2
numexpr:2.6.2
羽毛:なし
matplotlib:2.0.2
openpyxl:なし
xlrd:1.0.0
xlwt:1.2.0
xlsxwriter:0.9.6
lxml:3.7.3
bs4:4.6.0
html5lib:0.999
sqlalchemy:1.1.9
pymysql:なし
psycopg2:なし
jinja2:2.9.6
s3fs:なし
pandas_gbq:なし
pandas_datareader:なし
@NadiaRom完全な例を提供できますか? 確かに言うのは難しいですが、 df
は、ビューまたはコピーである可能性のある操作からのものであると思われます。 例えば:
In [8]: df = pd.DataFrame({"A": [1, 2], "B": [3, 4], "C": [4, 5]})
In [9]: df1 = df[['A', 'B']]
In [10]: df1.loc[0, 'A'] = 5
/Users/taugspurger/Envs/pandas-dev/lib/python3.6/site-packages/pandas/pandas/core/indexing.py:180: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
self._setitem_with_indexer(indexer, value)
/Users/taugspurger/Envs/pandas-dev/bin/ipython:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
#!/Users/taugspurger/Envs/pandas-dev/bin/python3.6
したがって、 df1
正しく更新しています。 あいまいさは、 df
も更新されるかどうかです。 同様のことがあなたにも起こっていると思いますが、再現可能な例がなければ、確実に言うのは難しいです。
@TomAugspurgerこれがコードです。一般的に、.locなしでパンダに値を割り当てることはありません。
df = pd.read_csv('df_unicities.tsv', sep='\t')
df.replace({'|': '--'}, inplace=True)
df_c = df.loc[df.encountry == country, : ]
df_c['sort'] = (df_c.encities_ua == 'all').astype(int) # new column
df_c['sort'] += (df_c.encities_foreign == 'all').astype(int)
df_c.sort_values(by='sort', inplace=True)
# ---end of chunk, everything is fine ---
if df_c.encities_foreign.str.contains('all').sum() < len(df_c):
df_c.loc[df_c.encities_foreign.str.contains('all'), 'encities_foreign'] = 'other'
df_c.loc[df_c.cities_foreign.str.contains('всі'), 'cities_foreign'] = 'інші'
else:
df_c.loc[df_c.encities_foreign.str.contains('all'), 'encities_foreign'] = country
df_c.loc[df_c.cities_foreign.str.contains('всі'), 'cities_foreign'] = df_c.country.iloc[0]
if df_c.encities_ua.str.contains('all').sum() < len(df_c):
df_c.loc[df_c.encities_ua.str.contains('all'), 'encities_ua'] = 'other'
df_c.loc[df_c.cities_ua.str.contains('всі'), 'cities_ua'] = 'інші'
else:
df_c.loc[df_c.encities_ua.str.contains('all'), 'encities_ua'] = 'Ukraine'
df_c.loc[df_c.cities_ua.str.contains('всі'), 'cities_ua'] = 'Україна'
# Warning after it
迅速な回答ありがとうございます!
ここでの問題は、最初に.loc
行目の
df_c = df.loc[df.encountry == country, :]
Pandasは、 df_c
スライスだけに値を割り当てたいのか、それとも元のdf
まで伝播させたいのかを100%確信していません。 最初にdf_c
を割り当てるときにこれを回避するには、を使用して、パンダにそれが独自のデータフレーム(スライスではない)であることを伝えてください。
df_c = df.loc[df.encountry == country, :].copy()
これを行うと、エラーが修正されます。 多くのユーザーがこの面でパンダに混乱していることに気付いたので、上記を説明するのに役立つ簡単な例を取り上げます。
>>> import pandas as pd
>>> df = pd.DataFrame({'A':[1,2,3,4,5], 'B':list('QQQCC')})
>>> df
A B
0 1 Q
1 2 Q
2 3 Q
3 4 C
4 5 C
>>> df.loc[df['B'] == 'Q', 'new_col'] = 'hello'
>>> df
A B new_col
0 1 Q hello
1 2 Q hello
2 3 Q hello
3 4 C NaN
4 5 C NaN
したがって、上記は期待どおりに機能します。 次に、データで実行しようとしたことを反映した例を試してみましょう。
>>> df = pd.DataFrame({'A':[1,2,3,4,5], 'B':list('QQQCC')})
>>> df_q = df.loc[df['B'] == 'Q']
>>> df_q
A B
0 1 Q
1 2 Q
2 3 Q
>>> df_q.loc[df['A'] < 3, 'new_col'] = 'hello'
/Users/riddellcd/anaconda/lib/python3.6/site-packages/pandas/core/indexing.py:337: 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.obj[key] = _infer_fill_value(value)
>>> df_q
A B new_col
0 1 Q hello
1 2 Q hello
2 3 Q NaN
同じエラーが発生したようです。 しかし、予想どおりdf_q
変更されました。 これは、 df_q
がdf
スライスであるためです。したがって、.loc []を使用していても、 df_q
パンダは変更を伝播しないことを警告しています。 df
。 これを回避するには、より明確にする必要があり、 df_q
は独自のデータフレームであり、明示的に宣言することでdf
は別になります。
df_q
から始めましょうが、今回は.copy()
使用します。
>>> df_q = df.loc[df['B'] == 'Q'].copy()
>>> df_q
A B
0 1 Q
1 2 Q
2 3 Q
Lets try to reassign our value now!
>>> df_q.loc[df['A'] < 3, 'new_col'] = 'hello'
>>> df_q
A B new_col
0 1 Q hello
1 2 Q hello
2 3 Q NaN
df_q
はdf
とは別であるとパンダに伝えたので、これはエラーなしで機能します
実際には、あなたは、これらの変更たい場合はdf_c
最大伝播するdf
thatsの別のポイントを完全にし、必要ならばお答えします。
@CRiddler素晴らしい、ありがとう!
あなたが言ったように、連鎖した.loc
は予期しない結果を返したことはありません。 私が理解しているように、 .copy()
は、選択したdf_sliced_once
を個別のオブジェクトとして扱い、最初の完全なdf
を変更する意図がないことをパンダに保証します。 smthを混同した場合は訂正してください。
ドキュメントはこちらhttp://pandas.pydata.org/pandas-docs/stable/indexing.html#returning-a-view-versus-a-copyで、 @ CRiddlerにはすばらしいinplace
はまったく使用しないでください。
実際には、あなたは、これらの変更たい場合は
df_c
最大伝播するdf
thatsの別のポイントを完全にし、必要ならばお答えします。
@CRiddlerありがとうございます。最初のデータフレームに伝播したり、それがどのように行われるかを示したい場合は、Stack Overflowの回答よりも優れていますか?
@persep一般的に、問題を
元のデータ:
>>>import pandas as pd
>>> df = pd.DataFrame({'A':[1,2,3,4,5], 'B':list('QQQCC')})
>>> df
A B
0 1 Q
1 2 Q
2 3 Q
3 4 C
4 5 C
一時的なデータフレームを作成しても、変更は反映されないことに注意してください
前の例で示したように、これはdf_q
のみに変更を加え、パンダの警告を発生させます(ここではコピー/貼り付けされません)。 ANDは変更をdf
伝播しません
>>> df_q = df.loc[df["B"] == "Q"]
>>> df_q.loc[df["A"] < 3, "new_column"] = "hello"
# df remains unchanged because we only made changes to `df_q`
>>> df
A B
0 1 Q
1 2 Q
2 3 Q
3 4 C
4 5 C
私の知る限り、上記と同じコードを使用して、変更を強制的に元のデータフレームに戻す方法はありません。
ただし、考え方を少し変えて、完全なサブセットではなくマスクを使用すると、目的の結果を得ることができます。 これは必ずしもサブセットから元のデータフレームへの変更を「伝播」するわけではありませんが、元のデータフレームdf
行った変更が確実に行われるようにしています。 これを行うには、最初にマスクを作成し、次にdf
サブセットに変更を加えるときにマスクを適用します。
>>> q_mask = df["B"] == "Q"
>>> a_mask = df["A"] < 3
# Combine masks (in this case we used "&") to achieve what a nested subset would look like
# In the same step we add in our item assignment. Instructing pandas to create a new column in `df` and assign
# the value "hello" to the rows in `df` where `q_mask` & `a_mask` overlap.
>>> df.loc[q_mask & a_mask, "new_col"] = "hello"
# Successful "propagation" of new values to the original dataframe
>>> df
A B new_col
0 1 Q hello
1 2 Q hello
2 3 Q NaN
3 4 C NaN
4 5 C NaN
最後に、df_qがどのように見えるかを確認したい場合は、 q_mask
を使用して元のデータフレームからいつでもサブセット化できます。
>>> df.loc[q_mask, :]
A B new_col
0 1 Q hello
1 2 Q hello
2 3 Q NaN
これは必ずしもdf_q
からdf
への変更を「伝播」するわけではありませんが、同じ結果が得られます。 実際の伝播は明示的に行う必要があり、マスクを使用するよりも効率が低くなります。
@CRiddlerありがとう、あなたはとても役に立ちました
最も参考になるコメント
ここでの問題は、最初に
.loc
行目のPandasは、
df_c
スライスだけに値を割り当てたいのか、それとも元のdf
まで伝播させたいのかを100%確信していません。 最初にdf_c
を割り当てるときにこれを回避するには、を使用して、パンダにそれが独自のデータフレーム(スライスではない)であることを伝えてください。これを行うと、エラーが修正されます。 多くのユーザーがこの面でパンダに混乱していることに気付いたので、上記を説明するのに役立つ簡単な例を取り上げます。
構成されたデータの例
したがって、上記は期待どおりに機能します。 次に、データで実行しようとしたことを反映した例を試してみましょう。
同じエラーが発生したようです。 しかし、予想どおり
df_q
変更されました。 これは、df_q
がdf
スライスであるためです。したがって、.loc []を使用していても、df_q
パンダは変更を伝播しないことを警告しています。df
。 これを回避するには、より明確にする必要があり、df_q
は独自のデータフレームであり、明示的に宣言することでdf
は別になります。df_q
から始めましょうが、今回は.copy()
使用します。df_q
はdf
とは別であるとパンダに伝えたので、これはエラーなしで機能します実際には、あなたは、これらの変更たい場合は
df_c
最大伝播するdf
thatsの別のポイントを完全にし、必要ならばお答えします。