ビュー、コピー、およびその迷惑な設定
すべてのパンダで任意の時間を費やしている場合は、見てきた
どんな警告のようにでも、あなたが理由のためにそれを得るので、それを無視しないことは賢いです:あなたが多分何か間違っていることであるという徴候です.私のケースでは、私は通常、私はいくつかの分析で膝の深いときに、それを修正する方法を考え出すあまりにも多くの時間を過ごすしたくないときに、この警告を得る.
私はいくつかの典型的な例は、この警告が表示されるときに、なぜそれが表示され、どのように迅速に根本的な問題を修正する方法をカバーするつもりです.
まず、例を挙げましょう
どのように我々は再びデータを設定しますか?
まず、データを設定できる方法を確認しましょう
インデクサーの最初の引数は行、2番目は列(または列)です.そして、この式に代入すると、基になる
ここでのインデックスは
この警告はいつですか.
を、今我々は更新している
それで、あなたはそれを修理しなければなりませんか?
これに対処する2つの主要な方法があります、そして、あなたが選ぶものはあなたがあなたのコードで達成しようとしているものに依存します.警告は、道路を混乱またはエラーを引き起こす可能性のあるパスを選択し、データを更新するための最良のプラクティスを使用するように指示していることを伝えている.
オリジナルを更新
あなたの意図は、元のデータを更新する場合は、単に直接更新する必要があります.だからあなたのアップデートを行う代わりに
コピーを更新
あなたの目標は、データのコピーを更新する場合は、警告を排除するには、常にそのコピーをするビューをしたいパンダを教えてください.
間に
発生する1つの一般的な状況は
列のサブセット
また、この警告に遭遇する可能性があります
完全性のために
今、あなたは多くのこの警告について読むことができますother places , そして、あなたが検索エンジンを通してここに来たならば、多分、あなたは多分彼らを混乱させるか、直接あなたの状況に適用できないとわかりました.私はいつもこのエラーを見ている状況を示すために、少し違ったアプローチをとった.しかし、より一般的な理由は、新しいパンダのユーザーがこのエラーに遭遇するときに更新しようとしている
これを連鎖割り当てと呼ぶ.警告の上の課題は、実際にこれを行うことです.
我々が使うならば
郵便Views, Copies, and that annoying SettingWithCopyWarning 最初に現れたwrighters.io .
SettingWithCopyWarning
. ない場合は、すぐに!どんな警告のようにでも、あなたが理由のためにそれを得るので、それを無視しないことは賢いです:あなたが多分何か間違っていることであるという徴候です.私のケースでは、私は通常、私はいくつかの分析で膝の深いときに、それを修正する方法を考え出すあまりにも多くの時間を過ごすしたくないときに、この警告を得る.
私はいくつかの典型的な例は、この警告が表示されるときに、なぜそれが表示され、どのように迅速に根本的な問題を修正する方法をカバーするつもりです.
まず、例を挙げましょう
DataFrame
. 便利なPythonパッケージを使っていますFaker テストデータを作成するには最初にそれをインストールする必要がありますpip
.%pip install Faker # notebook
pip install Faker # commmand line
すぐに、Fakerは、ユニットテスト、テストデータベース、または例のテストデータを構築する素晴らしい方法です.それはすべての偽ですが、それは実際の生活の中で発生する可能性がありますデータの組み合わせを生成する規則に基づいていますので、それは個人的に特定されていない本当の探してデータを生成します.>>> import datetime
>>> import pandas as pd
>>> import numpy as np
>>> from faker import Faker
>>> fake = Faker()
>>> df = pd.DataFrame([
[fake.first_name(),
fake.last_name(),
fake.date_of_birth(),
fake.date_this_year(),
fake.city(),
fake.state_abbr(),
fake.postalcode()]
for _ in range(20)],
columns = ['first_name', 'last_name', 'dob', 'lastupdate', 'city', 'state', 'zip'])
>>> df.head(3)
first_name last_name dob lastupdate city state zip
0 Evan Daniels 1943-05-27 2021-01-11 North Erin AZ 27597
1 Christine Herrera 2019-04-11 2021-01-29 Ellenview AL 28989
2 Michelle Warren 2015-05-29 2021-01-11 Mcknighttown VA 55551
どのように我々は再びデータを設定しますか?
まず、データを設定できる方法を確認しましょう
DataFrame
, 利用loc
or iloc
インデックス.これらはそれぞれラベルベースまたは整数オフセットベースのインデックスです.(参照)this article 二つの方法の詳細についてはインデクサーの最初の引数は行、2番目は列(または列)です.そして、この式に代入すると、基になる
DataFrame
.ここでのインデックスは
RangeIndex
, ラベルは数字です.そのため、私はINT値をloc
, これは相対インデックスではなくラベルで調べています.>>> df.head(1)['zip']
0 27597
Name: zip, dtype: object
>>> df.loc[0, 'zip'] = '60601'
>>> df.head(1)['zip']
0 60601
Name: zip, dtype: object
>>> df.loc[0, ['city', 'state']] = ['Chicago', 'IL']
>>> df.head(1)
first_name last_name dob lastupdate city state zip
0 Evan Daniels 1943-05-27 2021-01-11 Chicago IL 60601
>>> # Here's an example of an iloc update.
>>> df.iloc[0, 0] = 'Josh'
>>> df.head(1)
first_name last_name dob lastupdate city state zip
0 Josh Daniels 1943-05-27 2021-01-11 Chicago IL 60601
今、あなたはまた、配列のインデックスの演算子を使用して更新を行うことができますが、これは非常に混乱を見ることができるので、それを覚えているDataFrame
, あなたが最初に列を選択している.私は、単独でこの理由のためにこれをしないことを勧めます、しかし、あなたがすぐにわかるように、起こることができる他の問題があります.>>> df["first_name"][0] = 'Joshy'
>>> df.head(1)
first_name last_name dob lastupdate city state zip
0 Joshy Daniels 1943-05-27 2021-01-11 Chicago IL 60601
この警告はいつですか.
を、今我々は更新している
DataFrame
首尾よく、それは物事がどこに行くことができるかの例を見る時間です.私にとっては、オリジナルのデータのサブセットを選択するのが非常に一般的です.例えば、2000年以前に人が生まれたデータだけで仕事をすると決めましょう.>>> dob_limit = datetime.date(2000, 1, 1)
>>> sub = df[df['dob'] < dob_limit]
>>> sub.shape
(16, 7)
>>> idx = sub.head(1).index[0] # save the location for update attempts below
>>> sub.head(1)
first_name last_name dob lastupdate city state zip
0 Joshy Daniels 1943-05-27 2021-01-11 Chicago IL 60601
更新しましょうlastupdate
カラム.>>> sub.loc[idx, 'lastupdate'] = datetime.date.today()
/Users/mcw/.pyenv/versions/3.8.6/envs/pandas/lib/python3.8/site-packages/pandas/core/indexing.py:670: 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
iloc._setitem_with_indexer(indexer, value)
<ipython-input-14-5f1769c87aaf>:1: 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
sub.loc[idx, 'lastupdate'] = datetime.date.today()
ブーム!そこでは、私たちは、Aからスライスのコピーに値を設定しようとしていると言われますDataFrame
. ここで何が起こったのか.まあ.sub
が更新されましたがdf
私たちが警告をしていたとしても.>>> sub.loc[idx, 'lastupdate']
datetime.date(2021, 2, 4)
>>> df.loc[idx, 'lastupdate']
datetime.date(2021, 1, 11)
パンダは、あなたが予想したことをしなかったかもしれないとあなたに警告しています.ときに作成sub
, あなたは2007年にデータのコピーで終わりましたdf
. 値を更新すると、オリジナルではなくコピーを更新するだけであることを警告します.それで、あなたはそれを修理しなければなりませんか?
これに対処する2つの主要な方法があります、そして、あなたが選ぶものはあなたがあなたのコードで達成しようとしているものに依存します.警告は、道路を混乱またはエラーを引き起こす可能性のあるパスを選択し、データを更新するための最良のプラクティスを使用するように指示していることを伝えている.
オリジナルを更新
あなたの意図は、元のデータを更新する場合は、単に直接更新する必要があります.だからあなたのアップデートを行う代わりに
sub
, ドゥーイットオンdf
代わりに.>>> df.loc[idx, 'lastupdate'] = datetime.date.today()
>>> df.loc[idx, 'lastupdate']
datetime.date(2021, 2, 4)
これを行うとき、あなたのビューがコピーであるので、それは更新されません.あなたが両方を望むならばsub
and df
一致するには、両方の更新または再作成する必要がありますsub
更新後.このため、それを一時停止し、あなたが更新する任意の時間を考えることが重要ですDataFrame
. 今すぐ更新する必要があるこのデータのビューを作成しましたか?コピーを更新
あなたの目標は、データのコピーを更新する場合は、警告を排除するには、常にそのコピーをするビューをしたいパンダを教えてください.
>>> sub2 = df[df['dob'] < dob_limit].copy()
>>> sub2.loc[idx, 'lastupdate'] = datetime.date.today()
>>> sub2.loc[idx, 'lastupdate']
datetime.date(2021, 2, 4)
間に
発生する1つの一般的な状況は
DataFrame
データをフィルタリングすることによって、はるかに小さい方に絞り込まれます.たぶん、新しい列がいくつかの計算の一部として追加され、最終的な結果として、元のDataFrame
更新する必要があります.それをする一つの方法は、あなたを助けるためにインデックスを使うことです.>>> sub3 = df[df['dob'] < dob_limit].copy() # we'll be updating this DataFrame
>>> sub3['manualupdate'] = datetime.date.today() - datetime.timedelta(days=10) # you can modify this DataFrame
>>> sub3 = sub3.head(3) # or even make it smaller
>>> sub3['manualupdate']
0 2021-01-25
1 2021-01-25
3 2021-01-25
Name: manualupdate, dtype: object
今、我々はその事実を使用しますsub3
インデックスをオリジナルで共有するdf
データを更新するために使用します.列のすべてのマッチング行を更新できますlastupdate
例えば.>>> df.loc[sub3.index, 'lastupdate'] = sub3['manualupdate']
>>> df.loc[sub3.index]
first_name last_name dob lastupdate city state zip
0 Joshy Daniels 1943-05-27 2021-01-25 Chicago IL 60601
3 Vernon Hernandez 1989-04-10 2021-01-25 South Mark NE 05048
4 Mary Munoz 1933-03-16 2021-01-25 Ewingborough OK 31127
さて、これらの行がデータの小さなサブセットから更新されたことがわかります.列のサブセット
また、この警告に遭遇する可能性があります
DataFrame
.>>> df_d = df[['zip']]
>>> df_d.loc[idx, 'zip'] = "00313" # SettingWithCopyWarning
ここで警告を抑制する大きな方法は、完全なスライスを行うことですloc
あなたの初期の選択で.また、使用することができますcopy
.>>> df_d = df.loc[:, ['zip']]
>>> df_d.loc[idx, 'zip'] = "00313"
完全性のために
今、あなたは多くのこの警告について読むことができますother places , そして、あなたが検索エンジンを通してここに来たならば、多分、あなたは多分彼らを混乱させるか、直接あなたの状況に適用できないとわかりました.私はいつもこのエラーを見ている状況を示すために、少し違ったアプローチをとった.しかし、より一般的な理由は、新しいパンダのユーザーがこのエラーに遭遇するときに更新しようとしている
DataFrame
配列インデックス演算子の使用[]
).>>> df[df['dob'] < dob_limit]['lastupdate'] = datetime.date.today()
file.py:1: 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: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
df[df['dob'] < dob_limit]['lastupdate'] = datetime.date.today()
ここでの修正はとても簡単ですloc
. 試してみましょう.>>> df.loc[df['dob'] < dob_limit, 'lastupdate'] = datetime.date.today() - datetime.timedelta(days=1)
>>> df.loc[df['dob'] < dob_limit].head(1)
first_name last_name dob lastupdate city state zip
0 Joshy Daniels 1943-05-27 2021-02-03 Chicago IL 60601
その仕事.ここでの警告は、我々の最初のアップデートが我々のオリジナルデータのコピーに関して(潜在的に)動くと我々に話していました.私は、Pandasが時々コピーを返すのを選ぶいくつかの複雑な理由を持っているので、これが私たちのオープンケースと全く同じくらい明白であると思いません、そして、時々、元のデータに視野を返してください、そして、アップデートが1行にあるとき、これは明らかでないかもしれません.これが起こっていることを検出すると、この警告が発生します.これを連鎖割り当てと呼ぶ.警告の上の課題は、実際にこれを行うことです.
df. __getitem__ (df. __getitem__ ('dob') < dob_limit). __setitem__ ('lastupdate', datetime.date.today())
配列インデックス演算子を使用する場合__getitem__
and __setitem__
メソッドは、それぞれ取得および設定のために呼び出されます.その最初の関数呼び出し__getitem__
はデータのコピーを返して、それからデータを設定しようとして、警告を引き起こします.我々が使うならば
loc
, しかし、それは一時的な見解を返さずにこれをするでしょう.df.loc. __setitem__ ((df. __getitem__ ('dob') < dob_limit, 'lastupdate'), datetime.date.today())
それで、あなたがこの警告を見るときはいつも、あなたのコードを見て、2つのものをチェックしてください.データを更新しようとしましたか[]
? もしそうならばloc
(or iloc
). あなたがそれをしているならばDataFrame
別のDataFrame
. あなたがそれを更新するか、あなたのオリジナルを更新するために植物を植えるならばDataFrame
代わりに.郵便Views, Copies, and that annoying SettingWithCopyWarning 最初に現れたwrighters.io .
Reference
この問題について(ビュー、コピー、およびその迷惑な設定), 我々は、より多くの情報をここで見つけました https://dev.to/wrighter/views-copies-and-that-annoying-settingwithcopywarning-2137テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol