نموذج التعليمات البرمجية
# My code
df.loc[0, 'column_name'] = 'foo bar'
هذا الرمز في Pandas 20.3 يلقي SettingWithCopyWarning ويقترح
"حاول استخدام .loc[row_indexer,col_indexer] = value
بدلاً من ذلك".
أنا أفعل ذلك بالفعل ، يبدو أن هناك القليل من الأخطاء. أنا استخدم Jupyter.
شكرا لك! :)
pd.show_versions()
الالتزام: لا شيء
بيثون: 3.6.1.final.0
بتات الثعبان: 64
نظام التشغيل: Windows
إصدار نظام التشغيل: 8.1
الجهاز: AMD64
المعالج: Intel64 Family 6 Model 61 Stepping 4، GenuineIntel
byteorder: قليلا
LC_ALL: لا شيء
لانغ: لا شيء
LOCALE: لا شيء
الباندا: 0.20.1
بيتيست: 3.0.7
النقطة: 9.0.1
أدوات الإعداد: 35.0.2
سايثون: 0.25.2
numpy: 1.12.1
scipy: 0.19.0
xarray: لا شيء
IPython: 5.3.0
أبو الهول: 1.5.6
باتسي: 0.4.1
داتوتيل: 2.6.0
بيتز: 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 ها هو الكود ، بشكل عام ، لا
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
في السطر 4. محاولة تعيين قيم لتلك الشريحة.
df_c = df.loc[df.encountry == country, :]
Pandas ليس متأكدًا بنسبة 100٪ إذا كنت تريد تعيين قيم لشريحة df_c
، أو جعلها تتكاثر على طول الطريق إلى df
الأصلي. لتجنب ذلك عند تعيين 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
فهذه نقطة أخرى تمامًا وستجيب إذا أردت.
@ CRiddler عظيم ، شكرا لك !
كما ذكرت ، فإن المتسلسلة .loc
لم تُرجع أبدًا نتائج غير متوقعة. كما أفهم ، يضمن .copy()
Pandas أننا نتعامل مع df_sliced_once
ككائن منفصل ولا ننوي تغيير df
بالكامل. من فضلك صحح إذا خلطت
التوثيق هنا http://pandas.pydata.org/pandas-docs/stable/indexing.html#returning -a-view-versus-a-copy و CRiddler لديه شرح لطيف. يجب بشكل عام عدم استخدام inplace
على الإطلاق.
إذا كنت تريد في الواقع نشر هذه التغييرات إلى
df_c
حتىdf
فهذه نقطة أخرى تمامًا وستجيب إذا أردت.
CRiddler شكرًا على إجابتك أفضل من تلك الموجودة في Stack Overflow ، فهل يمكنك إضافتها عندما تريد النشر إلى إطار البيانات الأولي أو إعطاء إشارة إلى كيفية القيام بذلك؟
persep بشكل عام ، لا أحب تحويل المشكلات إلى سلاسل عمليات stackoverflow للحصول على المساعدة ، ولكن يبدو أن هذه المشكلة قد حظيت بقدر لا بأس به من الاهتمام منذ آخر عملية نشر ، لذا
البيانات الأصلية:
>>>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
ويثير تحذيرًا من حيوانات الباندا (لم يتم نسخها / لصقها هنا). ولا ينشر أي تغييرات على 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
في السطر 4. محاولة تعيين قيم لتلك الشريحة.Pandas ليس متأكدًا بنسبة 100٪ إذا كنت تريد تعيين قيم لشريحة
df_c
، أو جعلها تتكاثر على طول الطريق إلىdf
الأصلي. لتجنب ذلك عند تعيينdf_c
لأول مرة ، تأكد من إخبار الباندا أنه إطار بيانات خاص به (وليس شريحة) باستخدامالقيام بذلك سوف يصلح الخطأ الخاص بك. سأتناول مثالًا موجزًا للمساعدة في شرح ما سبق لأنني لاحظت أن الكثير من المستخدمين يشعرون بالارتباك من الباندا في هذا الجانب.
مثال مع البيانات المختلقة
لذلك ما سبق يعمل كما نتوقع! لنجرب الآن مثالاً يعكس ما حاولت فعله ببياناتك.
يبدو أننا وصلنا نفس الخطأ! لكنها تغيرت
df_q
كما توقعنا! هذا لأنdf_q
شريحة منdf
لذلك ، على الرغم من أننا نستخدم الباندا .loc []df_q
يحذرنا من أنه لن ينشر التغييرات إلىdf
. لتجنب ذلك ، نحتاج إلى أن نكون أكثر وضوحًا وأن نقول إنdf_q
هو إطار بيانات خاص به ، منفصل عنdf
بإعلان ذلك صراحة.لنبدأ مرة أخرى من
df_q
لكن استخدم.copy()
هذه المرة.يعمل هذا بدون خطأ لأننا أخبرنا الباندا أن
df_q
منفصل عنdf
إذا كنت تريد في الواقع أن تنتشر هذه التغييرات إلى
df_c
حتىdf
فهذه نقطة أخرى تمامًا وستجيب إذا أردت.