পান্ডসে সেটিংবিথকপি ওয়ার্নিংয়ের সাথে কীভাবে কাজ করবেন?


629

পটভূমি

আমি মাত্র আমার পান্ডাকে 0.11 থেকে 0.13.0rc1 তে আপগ্রেড করেছি। এখন, অ্যাপ্লিকেশনটি অনেকগুলি নতুন সতর্কতা পপ করছে। তাদের মধ্যে একটি:

E:\FinReporter\FM_EXT.py:449: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
  quote_df['TVol']   = quote_df['TVol']/TVOL_SCALE

আমি জানতে চাই এর সঠিক অর্থ কি? আমার কি কিছু বদলাতে হবে?

যদি আমি ব্যবহারের জন্য জিদ করি তবে কীভাবে আমি সতর্কতা স্থগিত করব quote_df['TVol'] = quote_df['TVol']/TVOL_SCALE?

ত্রুটি দেয় যে ফাংশন

def _decode_stock_quote(list_of_150_stk_str):
    """decode the webpage and return dataframe"""

    from cStringIO import StringIO

    str_of_all = "".join(list_of_150_stk_str)

    quote_df = pd.read_csv(StringIO(str_of_all), sep=',', names=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg')) #dtype={'A': object, 'B': object, 'C': np.float64}
    quote_df.rename(columns={'A':'STK', 'B':'TOpen', 'C':'TPCLOSE', 'D':'TPrice', 'E':'THigh', 'F':'TLow', 'I':'TVol', 'J':'TAmt', 'e':'TDate', 'f':'TTime'}, inplace=True)
    quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]
    quote_df['TClose'] = quote_df['TPrice']
    quote_df['RT']     = 100 * (quote_df['TPrice']/quote_df['TPCLOSE'] - 1)
    quote_df['TVol']   = quote_df['TVol']/TVOL_SCALE
    quote_df['TAmt']   = quote_df['TAmt']/TAMT_SCALE
    quote_df['STK_ID'] = quote_df['STK'].str.slice(13,19)
    quote_df['STK_Name'] = quote_df['STK'].str.slice(21,30)#.decode('gb2312')
    quote_df['TDate']  = quote_df.TDate.map(lambda x: x[0:4]+x[5:7]+x[8:10])

    return quote_df

আরও ত্রুটি বার্তা

E:\FinReporter\FM_EXT.py:449: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
  quote_df['TVol']   = quote_df['TVol']/TVOL_SCALE
E:\FinReporter\FM_EXT.py:450: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
  quote_df['TAmt']   = quote_df['TAmt']/TAMT_SCALE
E:\FinReporter\FM_EXT.py:453: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
  quote_df['TDate']  = quote_df.TDate.map(lambda x: x[0:4]+x[5:7]+x[8:10])


2
আপনি df.set_valueএখানে ডক্স ব্যবহার করতে পারেন - pandas.pydata.org/pandas-docs/stable/generated/…
লিওনপ্রো

1
pandas.pydata.org/pandas-docs/stable/… অফিসিয়াল ডকুমেন্ট বিস্তারিতভাবে ব্যাখ্যা করেছে
wyx

3
@ লিওনপ্রো অবমূল্যায়ন df.set_valueকরা হয়েছে। পান্ডস এখন ব্যবহার করার পরামর্শ দেয়.at[] বা .iat[]তার পরিবর্তে । ডক্স এখানে pandas.pydata.org/pandas-docs/stable/generated/…
কাইল সি

আমি বিস্মিত কেউ পান্ডাস 'উল্লেখ option_contextএখানে: pandas.pydata.org/pandas-docs/stable/user_guide/options.html যেমন, ব্যবহারwith pd.option_context("mode.chained_assignment", None): [...]
M-Dz

উত্তর:


793

SettingWithCopyWarningপতাকা তৈরি করা হয়েছে সম্ভাব্য বিভ্রান্তিকর "শৃঙ্খলিত" এই ধরনের অনুসরণযোগ্য যার ওপরে সবসময় আশানুরূপ কাজ করে, বিশেষ করে যখন প্রথম নির্বাচনকে একটি ফেরৎ যেমন বরাদ্দকরণ, কপি । [ পটভূমি আলোচনার জন্য GH5390 এবং GH5597 দেখুন ]]

df[df['A'] > 2]['B'] = new_val  # new_val not set in df

সতর্কতাটি নীচে পুনরায় লেখার জন্য একটি প্রস্তাব দেয়:

df.loc[df['A'] > 2, 'B'] = new_val

তবে এটি আপনার ব্যবহারের সাথে খাপ খায় না যা এর সমতুল্য:

df = df[df['A'] > 2]
df['B'] = new_val

যদিও এটি স্পষ্ট যে আপনি লেখার বিষয়ে এটিকে মূল ফ্রেমে ফিরিয়ে আনার বিষয়ে চিন্তা করেন না (যেহেতু আপনি এটির উল্লেখটি ওভাররাইট করছেন), দুর্ভাগ্যক্রমে এই প্যাটার্নটি প্রথম শৃঙ্খলিত অ্যাসাইনমেন্ট উদাহরণ থেকে আলাদা করা যায় না। সুতরাং (মিথ্যা পজিটিভ) সতর্কতা। মিথ্যা ধনাত্মক হওয়ার সম্ভাবনাটি সূচীকরণের ডক্সগুলিতে সম্বোধন করা হয়েছে , যদি আপনি আরও পড়তে চান। নিম্নলিখিত অ্যাসাইনমেন্ট সহ আপনি এই নতুন সতর্কতাটি নিরাপদে অক্ষম করতে পারেন।

import pandas as pd
pd.options.mode.chained_assignment = None  # default='warn'

34
আমি মনে করি আমি বেশিরভাগ ক্ষেত্রে এ সম্পর্কে কোনও সতর্কতা না দেওয়ার পক্ষে থাকব। যদি আপনি চেইন অ্যাসাইনমেন্ট সিনট্যাক্সের সাথে কাজ করেন তবে আপনি অবশ্যই নির্ধারিত ক্রমটি নির্ধারণ করতে পারেন যা কোনও প্রদত্ত পরিস্থিতিতে প্রত্যাশা অনুযায়ী কাজ করার জন্য ঘটতে হবে। আমি মনে করি এটি অত্যধিক বিড়ম্বনার বিষয় যে এটি সম্পর্কে এইগুলি সম্পূর্ণ সতর্কতা রয়েছে। 'প্রাইভেট' শ্রেণির পদ্ধতি বা বৈশিষ্ট্যগুলি সম্পর্কে "প্রত্যেককে বড় হতে দেওয়া" হিসাবে একই চেতনায়, আমি মনে করি পান্ডাদের পক্ষে শৃঙ্খলিত কার্যাদি সম্পর্কে ব্যবহারকারীদের বৃদ্ধ হতে দেওয়া ভাল। আপনি কী করছেন তা যদি আপনি জানেন তবে কেবল সেগুলি ব্যবহার করুন।
এলী

48
বিকল্পের জন্য হ্যাকিং করতে যাওয়া লোকেরা সতর্ক করার চেষ্টা করা কিছুটা অযৌক্তিক। অ্যাক্সেসের জন্য নতুন-স্টাইলের পান্ডাস পদ্ধতিগুলি (উন্নত .ix, উন্নত .ilocইত্যাদি) অবশ্যই অন্যান্য উপায় সম্পর্কে অবিচ্ছিন্নভাবে সতর্ক না করে অবশ্যই "প্রাথমিক উপায়" হিসাবে দেখা যেতে পারে। পরিবর্তে তাদের বড় হতে দিন এবং তারা যদি শৃঙ্খলিত কার্যাদি করতে চান তবে তাই হয়ে যান। যাইহোক আমার দুটি সেন্ট। এখানে পান্ড দেবগণের অসন্তুষ্ট মন্তব্যগুলি প্রায়শই দেখা যায় যখন শৃঙ্খলিত কার্যাদি কোনও সমস্যা সমাধানের জন্য কাজ করবে, তবে এটি করার জন্য "প্রাথমিক" উপায় হিসাবে বিবেচিত হবে না।
এলী

8
@ ইএমএসের সমস্যাটি হ'ল কোডটি থেকে কোনও প্রতিলিপি বনাম একটি ভিউ তৈরি করা হচ্ছে এবং এই সমস্যাটি থেকে প্রচুর বাগ / বিভ্রান্তি দেখা দেয় তা সর্বদা পরিষ্কার নয় । আমরা স্বয়ংক্রিয়ভাবে কনফিগারেশন করার জন্য একটি আরসি ফাইল / বিকল্পগুলি রাখার কথা ভাবছিলাম, যা অনুলিপি সহ সতর্কতার সাথে সেটিংস কীভাবে কাজ করছে তা দেওয়া আরও কার্যকর হতে পারে।
জেফ ট্রেটনার

3
সতর্ক করার কারণ হ'ল লোকেরা অবশ্যই পুরাতন কোড আপগ্রেড করছে for এবং আমার অবশ্যই একটি সতর্কতা দরকার, কারণ আমি কিছু খুব কুৎসিত পুরাতন কোড নিয়ে কাজ করছি।
থমাস অ্যান্ড্রুজ

15
পার্শ্ব নোটে, আমি দেখতে পেয়েছি যে শৃঙ্খলযুক্ত_অ্যাসাইনমেন্ট সতর্কতাটি অক্ষম করা: pd.options.mode.chained_assignment = Noneএর ফলে আমার কোডটি প্রায় 6 গুণ দ্রুত গতিতে চলেছে । অন্য কেউ অনুরূপ ফলাফল অভিজ্ঞ?
মুন

208

SettingWithCopyWarningপান্ডাদের সাথে কীভাবে ডিল করবেন ?

এই পোস্টটি পাঠকদের জন্য যাঁরা,

  1. এই সতর্কতার অর্থ কী তা বুঝতে চাই
  2. এই সতর্কতাটি দমন করার বিভিন্ন উপায় বুঝতে চাই
  3. ভবিষ্যতে এই সতর্কতাটি এড়াতে কীভাবে তাদের কোডটি উন্নত করতে হবে এবং ভাল অভ্যাসগুলি অনুসরণ করতে হবে তা বুঝতে চাই।

সেটআপ

np.random.seed(0)
df = pd.DataFrame(np.random.choice(10, (3, 5)), columns=list('ABCDE'))
df
   A  B  C  D  E
0  5  0  3  3  7
1  9  3  5  2  4
2  7  6  8  8  1

কি SettingWithCopyWarning?

এই সতর্কতাটি কীভাবে মোকাবেলা করতে হবে তা জানতে, এটির অর্থ কী এবং কেন এটি প্রথম স্থানে উত্থাপিত হয়েছিল তা বোঝা গুরুত্বপূর্ণ।

ডেটাফ্রেমগুলি ফিল্টার করার সময়, কোনও ভিউ , বা একটি অনুলিপি ফেরানোর জন্য কোনও ফ্রেমকে স্লাইস / ইনডেক্স করা সম্ভব করার সময় অভ্যন্তরীণ বিন্যাস এবং বিভিন্ন বাস্তবায়নের বিশদের উপর নির্ভর করে । একটি "ভিউ" শব্দটি হিসাবে বোঝা যায়, মূল ডেটাতে একটি ভিউ, সুতরাং ভিউটি সংশোধন করা মূল বস্তুকে পরিবর্তন করতে পারে। অন্যদিকে, একটি "অনুলিপি" মূল থেকে প্রাপ্ত তথ্যের অনুলিপি, এবং অনুলিপিটি পরিবর্তন করে আসলটির উপর কোনও প্রভাব ফেলেনি।

অন্যান্য উত্তর দ্বারা উল্লিখিত হিসাবে, এই SettingWithCopyWarning"চেইন অ্যাসাইনমেন্ট" ক্রিয়াকলাপ পতাকাঙ্কিত করা হয়েছিল। dfউপরের সেটআপে বিবেচনা করুন । ধরুন আপনি কলাম "বি" তে সমস্ত মান নির্বাচন করতে চান যেখানে কলাম "এ" এর মান> 5 রয়েছে। পান্ডা আপনাকে বিভিন্ন উপায়ে এটি করতে দেয়, অন্যের চেয়ে কিছুটা সঠিক। উদাহরণ স্বরূপ,

df[df.A > 5]['B']

1    3
2    6
Name: B, dtype: int64

এবং,

df.loc[df.A > 5, 'B']

1    3
2    6
Name: B, dtype: int64

এগুলি একই ফলস্বরূপ প্রত্যাবর্তন করে, তাই আপনি যদি কেবলমাত্র এই মানগুলি পড়ছেন তবে এটি কোনও পার্থক্য করে না। তাই সমস্যা কি? শৃঙ্খলাবদ্ধ অ্যাসাইনমেন্টের সমস্যাটি হ'ল সাধারণত কোনও দৃশ্য বা অনুলিপি ফিরে এসেছে কিনা তা ভবিষ্যদ্বাণী করা কঠিন, সুতরাং আপনি যখন মানগুলি ফেরত দেওয়ার চেষ্টা করছেন তখন এটি মূলত একটি সমস্যা হয়ে দাঁড়ায় পূর্ববর্তী উদাহরণটি তৈরি করতে, দোভাষী দ্বারা এই কোডটি কীভাবে কার্যকর করা হয় তা বিবেচনা করুন:

df.loc[df.A > 5, 'B'] = 4
# becomes
df.__setitem__((df.A > 5, 'B'), 4)

সাথে একক __setitem__কল df। ওটো, এই কোডটি বিবেচনা করুন:

df[df.A > 5]['B'] = 4
# becomes
df.__getitem__(df.A > 5).__setitem__('B", 4)

এখন, __getitem__কোনও দর্শন বা অনুলিপি ফিরে এসেছে কিনা তার উপর নির্ভর করে __setitem__অপারেশনটি কাজ করতে পারে না

সাধারণভাবে, আপনার locলেবেল-ভিত্তিক অ্যাসাইনমেন্ট এবং ilocপূর্ণসংখ্যার / অবস্থান ভিত্তিক অ্যাসাইনমেন্টের জন্য ব্যবহার করা উচিত , কারণ স্পেসটি গ্যারান্টি দেয় যে তারা সর্বদা আসলটিতে কাজ করে। অতিরিক্তভাবে, একটি একক ঘর সেট করার জন্য, আপনার ব্যবহার করা উচিত atএবংiat

ডকুমেন্টেশনে আরও পাওয়া যাবে ।

দ্রষ্টব্য
সমস্ত বুলিয়ান ইনডেক্সিং অপারেশনগুলি দিয়ে সম্পন্নও করা locযেতে পারে iloc। পার্থক্য কেবল এটিইiloc সূচকের জন্য পূর্ণসংখ্যা / অবস্থান বা বুলিয়ান মানগুলির একটি অল্প অ্যারে এবং কলামগুলির জন্য পূর্ণসংখ্যা / অবস্থান সূচকগুলি প্রত্যাশা করে।

উদাহরণ স্বরূপ,

df.loc[df.A > 5, 'B'] = 4

নাস লেখা যেতে পারে

df.iloc[(df.A > 5).values, 1] = 4

এবং,

df.loc[1, 'A'] = 100

হিসাবে লেখা যেতে পারে

df.iloc[1, 0] = 100

ইত্যাদি।


শুধু আমাকে কীভাবে সতর্কতা দমন করতে বলুন!

এর "এ" কলামে একটি সাধারণ অপারেশন বিবেচনা করুন df। "এ" নির্বাচন করা এবং 2 দিয়ে ভাগ করা সতর্কতা বাড়িয়ে তুলবে, তবে ক্রিয়াকলাপটি কার্যকর হবে।

df2 = df[['A']]
df2['A'] /= 2
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/IPython/__main__.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

df2
     A
0  2.5
1  4.5
2  3.5

এই সতর্কতাটি সরাসরি নিঃশব্দ করার কয়েকটি উপায় রয়েছে:

  1. একটি করা deepcopy

    df2 = df[['A']].copy(deep=True)
    df2['A'] /= 2
  2. পরিবর্তনpd.options.mode.chained_assignment
    সেট করা যেতে পারে None, "warn"অথবা "raise""warn"ডিফল্ট হয়। Noneসতর্কতা পুরোপুরি দমন করবে, এবং "raise"একটি নিক্ষেপ করবে SettingWithCopyError, অপারেশনটি চালিয়ে যাওয়া থেকে বিরত রাখবে।

    pd.options.mode.chained_assignment = None
    df2['A'] /= 2

@ পিটার কটন মন্তব্যগুলিতে একটি কনটেক্সট ম্যানেজার ব্যবহার করে মোড ( এই সংক্ষিপ্তসার থেকে সংশোধিত ) মোড পরিবর্তন করার একটি দুর্দান্ত উপায় নিয়ে এসেছিলেন, মোডটি যতক্ষণ প্রয়োজন ঠিক ততক্ষণ সেট করতে এবং এটিকে আবার রিসেট করুন আসল অবস্থা শেষ হলে।

class ChainedAssignent:
    def __init__(self, chained=None):
        acceptable = [None, 'warn', 'raise']
        assert chained in acceptable, "chained must be in " + str(acceptable)
        self.swcw = chained

    def __enter__(self):
        self.saved_swcw = pd.options.mode.chained_assignment
        pd.options.mode.chained_assignment = self.swcw
        return self

    def __exit__(self, *args):
        pd.options.mode.chained_assignment = self.saved_swcw

ব্যবহার নিম্নলিখিত:

# some code here
with ChainedAssignent():
    df2['A'] /= 2
# more code follows

বা, ব্যতিক্রম বাড়াতে

with ChainedAssignent(chained='raise'):
    df2['A'] /= 2

SettingWithCopyError: 
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

"এক্সওয়াই সমস্যা": আমি কী ভুল করছি?

বেশিরভাগ সময়, ব্যবহারকারীরা কেন প্রথম স্থানে উত্থাপিত হয়েছিল তা পুরোপুরি না বুঝেই এই ব্যতিক্রমটিকে দমন করার উপায়গুলি অনুসন্ধান করার চেষ্টা করেন। এটি একটি ভাল উদাহরণ এক্সওয়াই সমস্যাটির , যেখানে ব্যবহারকারীরা একটি সমস্যা "ওয়াই" সমাধান করার চেষ্টা করেন যা আসলে গভীরতর মূল সমস্যা "এক্স" এর লক্ষণ। এই সতর্কতার মুখোমুখি হওয়া সাধারণ সমস্যাগুলির ভিত্তিতে প্রশ্ন উত্থাপিত হবে এবং এরপরে সমাধানগুলি উপস্থাপন করা হবে।

প্রশ্ন 1
আমার একটি ডেটা ফ্রেম আছে

df
       A  B  C  D  E
    0  5  0  3  3  7
    1  9  3  5  2  4
    2  7  6  8  8  1

আমি কল "A"> 5 থেকে 1000 এ মান নির্ধারণ করতে চাই My আমার প্রত্যাশিত আউটপুট

      A  B  C  D  E
0     5  0  3  3  7
1  1000  3  5  2  4
2  1000  6  8  8  1

এটি করার ভুল উপায়:

df.A[df.A > 5] = 1000         # works, because df.A returns a view
df[df.A > 5]['A'] = 1000      # does not work
df.loc[df.A  5]['A'] = 1000   # does not work

সঠিকভাবে ব্যবহার loc:

df.loc[df.A > 5, 'A'] = 1000


প্রশ্ন 2 1
আমি ঘরটিতে মান (1, 'ডি') 12345 এ সেট করার চেষ্টা করছি My আমার প্রত্যাশিত আউটপুট

   A  B  C      D  E
0  5  0  3      3  7
1  9  3  5  12345  4
2  7  6  8      8  1

আমি এই ঘরের অ্যাক্সেসের বিভিন্ন উপায়ে চেষ্টা করেছি df['D'][1]। এই কাজ করতে সবচেয়ে ভালো উপায় কি?

১. এই প্রশ্নটি বিশেষত সতর্কবার্তার সাথে সম্পর্কিত নয়, তবে কীভাবে সঠিকভাবে এই বিশেষ ক্রিয়াকলাপটি করা যায় তা বোঝা ভাল যাতে ভবিষ্যতে সতর্কতাটি সম্ভাব্যরূপে উদ্ভূত হতে পারে এমন পরিস্থিতি এড়ানো যায়।

এটি করতে আপনি নীচের যে কোনও পদ্ধতি ব্যবহার করতে পারেন।

df.loc[1, 'D'] = 12345
df.iloc[1, 3] = 12345
df.at[1, 'D'] = 12345
df.iat[1, 3] = 12345


প্রশ্ন 3
আমি কিছু শর্তের ভিত্তিতে মানগুলি সাবসেট করার চেষ্টা করছি। আমার একটি ডেটা ফ্রেম আছে

   A  B  C  D  E
1  9  3  5  2  4
2  7  6  8  8  1

আমি "ডি" তে 123 এর মতো "সি" == 5 মান নির্ধারণ করতে চাই I আমি চেষ্টা করেছি

df2.loc[df2.C == 5, 'D'] = 123

যা সূক্ষ্ম বলে মনে হয় কিন্তু আমি এখনও পেয়ে SettingWithCopyWarning! আমি কিভাবে এটা ঠিক করব?

এটি সম্ভবত আপনার পাইপলাইনে কোড উচ্চতর হওয়ার কারণে। আপনি কি আরও df2বড় কিছু থেকে তৈরি করেছেন , যেমন

df2 = df[df.A > 5]

? এই ক্ষেত্রে, বুলিয়ান সূচীকরণ একটি দর্শন ফিরিয়ে df2দেবে , সুতরাং আসলটি উল্লেখ করবে। আপনার যা করতে হবে তা হ'ল df2একটি অনুলিপি :

df2 = df[df.A > 5].copy()
# Or,
# df2 = df.loc[df.A > 5, :]


প্রশ্ন 4
আমি স্থান থেকে "সি" কলামটি বাদ দেওয়ার চেষ্টা করছি

   A  B  C  D  E
1  9  3  5  2  4
2  7  6  8  8  1

কিন্তু ব্যবহার করছি

df2.drop('C', axis=1, inplace=True)

ছোঁড়ার SettingWithCopyWarning। ইহা কি জন্য ঘটিতেছে?

এর কারণ হ'ল df2কিছু অন্যান্য কাটাকাটি অপারেশন থেকে দৃশ্য হিসাবে তৈরি করা হয়েছে, যেমন

df2 = df[df.A > 5]

এখানে সমাধানটি হয় আগের মতো একটি copy()তৈরি করা dfবা ব্যবহার করা loc


6
পিএস: আপনার পরিস্থিতিটি প্রশ্নের ধারা 3-এর আওতাভুক্ত না হলে আমাকে জানান। আমি আমার পোস্ট সংশোধন করব।
সিএস 95

150

সাধারণভাবে এর বিন্দুটি SettingWithCopyWarningহল ব্যবহারকারীদের (এবং বিশেষত নতুন ব্যবহারকারীদের) দেখাতে হবে যে তারা কোনও অনুলিপি ব্যবহার করতে পারে এবং তারা যেমন ভাবেন তত মূল নয়। সেখানে হয় মিথ্যা positives (IOW আপনি যদি জানেন আপনি কি করছেন এটা হতে পারে ঠিক )। একটি সম্ভাবনা হ'ল @ গ্যারেটের পরামর্শ অনুসারে (ডিফল্ট অনুসারে সতর্কতা ) বন্ধ করা ।

এখানে আরও একটি বিকল্প রয়েছে:

In [1]: df = DataFrame(np.random.randn(5, 2), columns=list('AB'))

In [2]: dfa = df.ix[:, [1, 0]]

In [3]: dfa.is_copy
Out[3]: True

In [4]: dfa['A'] /= 2
/usr/local/bin/ipython:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
  #!/usr/local/bin/python

আপনি is_copyপতাকাটিকে সেট করতে পারেন False, যা সেই বস্তুর জন্য কার্যকরভাবে চেকটি বন্ধ করে দেবে :

In [5]: dfa.is_copy = False

In [6]: dfa['A'] /= 2

আপনি যদি স্পষ্টভাবে অনুলিপি করেন তবে আর কোনও সতর্কতা ঘটবে না:

In [7]: dfa = df.ix[:, [1, 0]].copy()

In [8]: dfa['A'] /= 2

ওপি ওপি কোড উপরে প্রদর্শন করছে, বৈধ হওয়ার সময় এবং সম্ভবত আমিও কিছু করি, প্রযুক্তিগতভাবে এই সতর্কতার জন্য একটি মামলা, এবং মিথ্যা ইতিবাচক নয়। সতর্কতা না পাওয়ার আরেকটি উপায় হ'ল নির্বাচনের কাজটি reindexউদাহরণস্বরূপ করা

quote_df = quote_df.reindex(columns=['STK', ...])

অথবা,

quote_df = quote_df.reindex(['STK', ...], axis=1)  # v.0.21

তথ্য এবং আলোচনার জন্য ধন্যবাদ, আমি কনসোলকে এ বিষয়ে চুপ করে থাকতে সতর্কতাটি বন্ধ করে দিয়েছি। এটি এসকিউএল ডাটাবেসে ভিউ এবং টেবিলের মতো মনে হচ্ছে। 'অনুলিপি' ধারণাটি চালু করার সুবিধা সম্পর্কে আমার আরও জানতে হবে, তবে সূক্ষ্ম শব্দার্থ-সিনট্যাক্স পার্থক্যের যত্ন নিতে আইএমএইচও কিছুটা বোঝা ..
বিগব্যাগ

19
আমি অনুলিপি () এর সাথে একমত; এটি পরিষ্কার এবং এটি আমার সমস্যা স্থির করেছে (যা একটি মিথ্যা ইতিবাচক ছিল)।
আরডিচেম্বার্স

5
আপডেটের পরে 0.16আমি আরও অনেক মিথ্যা ধনাত্মকতা দেখেছি, মিথ্যা ধনাত্মক সমস্যাটি কখনও কখনও এটিকে বৈধ হওয়া সত্ত্বেও এটিকে উপেক্ষা করতে শেখে।
ছদ্মবেশী

3
@ দাশী আপনি পয়েন্টটি মিস করছেন। কখনও কখনও এমনকি বেশিরভাগ সময় এটি কাজ করতে পারে। তবে এটি উদাহরণস্বরূপ ঘটতে পারে যদি ফ্রেমটি বড় / ছোট হয় বা আপনি কোনও কলামে কোনও আলাদা টাইপ বলে যে এটি কাজ করে না । এটাই আসল কথা. আপনি এমন কিছু করছেন যা কাজ করতে পারে তবে গ্যারান্টিযুক্ত নয়। এটি অবমূল্যায়নের সতর্কবার্তার চেয়ে খুব আলাদা। আপনি যদি এটির ব্যবহার চালিয়ে যেতে চান এবং এটি কার্যকর হয় তবে দুর্দান্ত। তবে আগে থেকে সাবধান!
জেফ

3
@ জেফ এখন বুঝতে পারেন, তাই এটি একটি undefinedআচরণ। যদি কিছু হয় তবে এটির ত্রুটি ছুঁড়ে ফেলা উচিত (এতে দেখা দুর্যোগগুলি এড়ানোর জন্য C), যেহেতু apiসতর্কতার বর্তমান ব্যবহার হিমশীতল পশ্চাদপদ সামঞ্জস্যের জন্য অর্থবোধ করে। এবং আমি আমার প্রোডাকশন কোডে ত্রুটি হিসাবে তাদের ধরে ফেলতে সক্ষম করব ( warnings.filterwarnings('error', r'SettingWithCopyWarning)। এছাড়াও .locকখনও কখনও ব্যবহারের পরামর্শটি কোনওভাবেই সহায়তা করে না (যদি এটি কোনও গ্রুপে থাকে)।
ছদ্মবেশী

41

পান্ডাস ডাটাফ্রেমের অনুলিপি সতর্কতা

আপনি যখন যান এবং এরকম কিছু করেন:

quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]

pandas.ix এক্ষেত্রে একটি নতুন, একা দাঁড়িয়ে ডেটাফ্রেম দেয় returns

এই ডেটাফ্রেমে আপনি যে মানগুলি পরিবর্তন করার সিদ্ধান্ত নিয়েছেন তা মূল ডেটাফ্রেমে পরিবর্তন করবে না।

প্যান্ডাস এটি সম্পর্কে আপনাকে সতর্ক করার চেষ্টা করে।


কেন .ixখারাপ ধারণা

.ixবস্তুর একটির বেশি জিনিস করতে চেষ্টা করে, এবং যারা পরিষ্কার কোড সম্পর্কে কিছু পড়েছেন জন্য, এই একটি শক্তিশালী গন্ধ হয়।

এই ডেটাফ্রেম দেওয়া:

df = pd.DataFrame({"a": [1,2,3,4], "b": [1,1,2,2]})

দুটি আচরণ:

dfcopy = df.ix[:,["a"]]
dfcopy.a.ix[0] = 2

আচরণ এক: dfcopyএখন একা একা ডেটাফ্রেম। এটি পরিবর্তন করলে কোনও পরিবর্তন হবে নাdf

df.ix[0, "a"] = 3

আচরণ দুটি: এটি আসল ডেটাফ্রেমে পরিবর্তন করে।


.locপরিবর্তে ব্যবহার করুন

পান্ডাস বিকাশকারীরা স্বীকৃতি দিয়েছিলেন যে এই .ixবস্তুটি বেশ গন্ধযুক্ত [অনুমানমূলকভাবে] এবং সুতরাং দুটি নতুন অবজেক্ট তৈরি করেছে যা ডেটা অ্যাক্সেস এবং অ্যাসাইনমেন্টে সহায়তা করে। (অন্য সত্তা .iloc)

.loc এটি দ্রুততর, কারণ এটি ডেটার একটি অনুলিপি তৈরি করার চেষ্টা করে না।

.loc আপনার বিদ্যমান ডেটা ফ্রেম ইনপ্লেসটি সংশোধন করে বোঝানো হচ্ছে যা আরও বেশি মেমরির দক্ষ।

.loc অনুমানযোগ্য, এটির একটি আচরণ রয়েছে।


সমাধান

আপনি আপনার কোড উদাহরণে যা করছেন তা হ'ল প্রচুর কলাম সহ একটি বড় ফাইল লোড হচ্ছে, তারপরে এটি আরও ছোট করে সংশোধন করা হবে।

pd.read_csvফাংশন এই অনেক সঙ্গে আপনি সাহায্য করতে পারেন এবং ফাইল অনেক দ্রুত লোড করুন।

সুতরাং এটি না করে বরং

quote_df = pd.read_csv(StringIO(str_of_all), sep=',', names=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg')) #dtype={'A': object, 'B': object, 'C': np.float64}
quote_df.rename(columns={'A':'STK', 'B':'TOpen', 'C':'TPCLOSE', 'D':'TPrice', 'E':'THigh', 'F':'TLow', 'I':'TVol', 'J':'TAmt', 'e':'TDate', 'f':'TTime'}, inplace=True)
quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]

এটা কর

columns = ['STK', 'TPrice', 'TPCLOSE', 'TOpen', 'THigh', 'TLow', 'TVol', 'TAmt', 'TDate', 'TTime']
df = pd.read_csv(StringIO(str_of_all), sep=',', usecols=[0,3,2,1,4,5,8,9,30,31])
df.columns = columns

এটি কেবল আপনার আগ্রহী কলামগুলি পড়বে এবং সেগুলি সঠিকভাবে নামকরণ করবে। .ixMagন্দ্রজালিক জিনিসগুলি করার জন্য অশুভ বস্তুটি ব্যবহার করার দরকার নেই ।


"পান্ডাস বিকাশকারীরা স্বীকৃতি দিয়েছিলেন যে .ix বস্তুটি বেশ গন্ধযুক্ত [অনুমানমূলকভাবে] এবং এভাবে দুটি নতুন বস্তু তৈরি হয়েছিল" - অন্যটি কী?
jf328

3
@ jf328 .iloc আমি মনে করি
ব্রায়ান বিয়েন

1
হ্যাঁ, এটা .iloc। পান্ডাস ডেটা স্ট্রাকচারের সূচকের জন্য এটি দুটি প্রাথমিক পদ্ধতি। ডকুমেন্টেশন আরও পড়ুন।
নিনজাকাননন

তারিখের সময় অবজেক্ট বা স্ট্রিংয়ের সাথে টাইমস্ট্যাম্পগুলির সাহায্যে ডেটাফ্রেম কলামটি কীভাবে প্রতিস্থাপন করা উচিত?
বোল্ডনিক

@boldnik এই উত্তর চেক করুন stackoverflow.com/a/37453925/3730397
firelynx

20

এখানে আমি সরাসরি প্রশ্নের উত্তর। কিভাবে এটি মোকাবেলা?

.copy(deep=False)আপনি টুকরো টুকরো করার পরে একটি তৈরি করুন । পান্ডাস.ডাটাফ্রেমকপি দেখুন ।

অপেক্ষা করুন, একটি টুকরা একটি অনুলিপি ফিরে না? সর্বোপরি, এই কি সতর্কতা বার্তা বলতে চেষ্টা করছে? দীর্ঘ উত্তর পড়ুন:

import pandas as pd
df = pd.DataFrame({'x':[1,2,3]})

এটি একটি সতর্কতা দেয়:

df0 = df[df.x>2]
df0['foo'] = 'bar'

এটি করে না:

df1 = df[df.x>2].copy(deep=False)
df1['foo'] = 'bar'

উভয় df0এবং df1হয় DataFrameবস্তু, কিন্তু তাদের সম্পর্কে ভিন্ন কিছু পান্ডাস সম্ভব সতর্কতাটি প্রিন্ট হয়। আসুন এটি কী তা খুঁজে বার করুন।

import inspect
slice= df[df.x>2]
slice_copy = df[df.x>2].copy(deep=False)
inspect.getmembers(slice)
inspect.getmembers(slice_copy)

আপনার পছন্দের বিভিন্ন সরঞ্জামটি ব্যবহার করে আপনি দেখতে পাবেন যে কয়েকটি ঠিকানা ছাড়িয়ে কেবলমাত্র উপাদানগত পার্থক্যটি হ'ল:

|          | slice   | slice_copy |
| _is_copy | weakref | None       |

সতর্কতা অবলম্বন করা উচিত কিনা তা DataFrame._check_setitem_copyপরীক্ষা করে এমন পদ্ধতিটি _is_copy। সুতরাং এখানে আপনি যান। এমন একটি তৈরি করুন copyযাতে আপনার ডেটা ফ্রেম না হয়_is_copy

সতর্কতাটি ব্যবহারের পরামর্শ দিচ্ছে .loc, তবে আপনি যদি .locকোনও ফ্রেমে এটি ব্যবহার করেন তবে আপনি _is_copyএখনও একই সতর্কতা পাবেন। বিভ্রান্তিকর? হ্যাঁ. বিরক্তিকর? আপনি বাজি ধরুন। সহায়ক? সম্ভাব্য, যখন চেইন অ্যাসাইনমেন্ট ব্যবহার করা হয়। তবে এটি চেইন অ্যাসাইনমেন্টটি সঠিকভাবে সনাক্ত করতে পারে এবং সতর্কতাটিকে নির্বিচারে মুদ্রণ করতে পারে।


11

এই বিষয়টি পান্ডাদের সাথে সত্যই বিভ্রান্তিকর। ভাগ্যক্রমে, এর তুলনামূলক সহজ সমাধান রয়েছে।

সমস্যাটি হ'ল ডেটা ফিল্টারিং অপারেশনগুলি (উদাহরণস্বরূপ লোকাল) কোনও অনুলিপি বা ডেটা ফ্রেমের একটি দৃশ্য ফিরিয়ে দেয় কিনা তা সর্বদা পরিষ্কার হয় না। ফিল্টারযুক্ত ডেটা ফ্রেমের আরও ব্যবহার বিভ্রান্তিকর হতে পারে।

এর সহজ সমাধানটি হ'ল (যদি না আপনার খুব বড় ডেটার সেটগুলির সাথে কাজ করার প্রয়োজন হয়):

যখনই আপনাকে কোনও মান আপডেট করার দরকার আছে, সর্বদা নিশ্চিত হয়ে নিন যে আপনি কার্যভারের পূর্বে অবশ্যই কার্যকরভাবে ডেটাফ্রেমটি অনুলিপি করেছেন।

df  # Some DataFrame
df = df.loc[:, 0:2]  # Some filtering (unsure whether a view or copy is returned)
df = df.copy()  # Ensuring a copy is made
df[df["Name"] == "John"] = "Johny"  # Assignment can be done now (no warning)

একটি টাইপো রয়েছে: স্পষ্টতই স্পষ্টভাবে হওয়া উচিত
s9527

7

কোনও সন্দেহ দূর করার জন্য, আমার সমাধানটি ছিল নিয়মিত কপির পরিবর্তে স্লাইসের একটি গভীর অনুলিপি করা। এটি আপনার প্রসঙ্গের উপর নির্ভর করে প্রযোজ্য নাও হতে পারে (স্মৃতি সীমাবদ্ধতা / স্লাইজের আকার, পারফরম্যান্স অবক্ষয়ের সম্ভাবনা - বিশেষত যদি অনুলিপিটি আমার মতো করে থাকে তবে ...)

স্পষ্টতই, আমি যে সতর্কতা পেয়েছি তা এখানে:

/opt/anaconda3/lib/python3.6/site-packages/ipykernel/__main__.py:54:
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

চিত্রণ

আমার সন্দেহ ছিল যে আমি একটি কলামটি স্লাইসের অনুলিপিটিতে ফেলে দিচ্ছিলাম বলে এই সতর্কতাটি ছুঁড়ে দেওয়া হয়েছিল। প্রযুক্তিগতভাবে স্লাইসের অনুলিপিটিতে একটি মান সেট করার চেষ্টা না করার পরে, এটি এখনও স্লাইসের অনুলিপিটির একটি পরিবর্তন ছিল। সন্দেহটি নিশ্চিত করতে নীচে আমি (সরল) পদক্ষেপ নিয়েছি, আমি আশা করি এটি আমাদের মধ্যে যারা সতর্কতাটি বোঝার চেষ্টা করছেন তাদের সহায়তা করবে।

উদাহরণ 1: মূলটিতে কলামটি ফেলে দেওয়া অনুলিপিটিকে প্রভাবিত করে

আমরা জানতাম যে ইতিমধ্যে তবে এটি একটি স্বাস্থ্যকর অনুস্মারক। এই না কি সতর্কবার্তা সম্পর্কে।

>> data1 = {'A': [111, 112, 113], 'B':[121, 122, 123]}
>> df1 = pd.DataFrame(data1)
>> df1

    A   B
0   111 121
1   112 122
2   113 123


>> df2 = df1
>> df2

A   B
0   111 121
1   112 122
2   113 123

# Dropping a column on df1 affects df2
>> df1.drop('A', axis=1, inplace=True)
>> df2
    B
0   121
1   122
2   123

Df2 প্রভাবিত করতে df1 এ করা পরিবর্তনগুলি এড়ানো সম্ভব

>> data1 = {'A': [111, 112, 113], 'B':[121, 122, 123]}
>> df1 = pd.DataFrame(data1)
>> df1

A   B
0   111 121
1   112 122
2   113 123

>> import copy
>> df2 = copy.deepcopy(df1)
>> df2
A   B
0   111 121
1   112 122
2   113 123

# Dropping a column on df1 does not affect df2
>> df1.drop('A', axis=1, inplace=True)
>> df2
    A   B
0   111 121
1   112 122
2   113 123

উদাহরণ 2: অনুলিপিটিতে কলামটি ফেলে দেওয়া মূলটিকে প্রভাবিত করতে পারে

এটি আসলে সতর্কতার চিত্র তুলে ধরেছে।

>> data1 = {'A': [111, 112, 113], 'B':[121, 122, 123]}
>> df1 = pd.DataFrame(data1)
>> df1

    A   B
0   111 121
1   112 122
2   113 123

>> df2 = df1
>> df2

    A   B
0   111 121
1   112 122
2   113 123

# Dropping a column on df2 can affect df1
# No slice involved here, but I believe the principle remains the same?
# Let me know if not
>> df2.drop('A', axis=1, inplace=True)
>> df1

B
0   121
1   122
2   123

Df1 এ প্রভাবিত করতে df2 এ করা পরিবর্তনগুলি এড়ানো সম্ভব

>> data1 = {'A': [111, 112, 113], 'B':[121, 122, 123]}
>> df1 = pd.DataFrame(data1)
>> df1

    A   B
0   111 121
1   112 122
2   113 123

>> import copy
>> df2 = copy.deepcopy(df1)
>> df2

A   B
0   111 121
1   112 122
2   113 123

>> df2.drop('A', axis=1, inplace=True)
>> df1

A   B
0   111 121
1   112 122
2   113 123

চিয়ার্স!


4

এই কাজ করা উচিত:

quote_df.loc[:,'TVol'] = quote_df['TVol']/TVOL_SCALE

4

কেউ কেউ কেবল সতর্কতা দমন করতে চাইতে পারেন:

class SupressSettingWithCopyWarning:
    def __enter__(self):
        pd.options.mode.chained_assignment = None

    def __exit__(self, *args):
        pd.options.mode.chained_assignment = 'warn'

with SupressSettingWithCopyWarning():
    #code that produces warning

3

আপনি যদি স্লাইসটি কোনও ভেরিয়েবলের জন্য বরাদ্দ করে থাকেন এবং নীচের মত চলকটি ব্যবহার করে সেট করতে চান:

df2 = df[df['A'] > 2]
df2['B'] = value

এবং আপনি জেফস সমাধানটি ব্যবহার করতে চান না কারণ আপনার শর্তের কম্পিউটিং df2দীর্ঘস্থায়ী বা অন্য কোনও কারণে, তবে আপনি নিম্নলিখিতটি ব্যবহার করতে পারেন:

df.loc[df2.index.tolist(), 'B'] = value

df2.index.tolist() df2- এ সমস্ত এন্ট্রি থেকে সূচকগুলি প্রদান করে, যা পরে মূল ডেটাফ্রেমে বি কলাম সেট করতে ব্যবহৃত হবে।


এটি 9 বার বেশি ব্যয়বহুল পরে df ["B"] = মান
ক্লাদিউ ক্রেঙ্গা

আপনি কি আরও গভীরভাবে @ ক্লাউডিউক্রেনা ব্যাখ্যা করতে পারেন?
gies0r

2

আমার জন্য এই সমস্যাটি নিম্নলিখিত> সরলীকৃত <উদাহরণে ঘটেছে। এবং আমি এটি সমাধান করতে সক্ষম হয়েছি (আশা করি সঠিক সমাধান সহ):

সতর্কতা সহ পুরানো কোড:

def update_old_dataframe(old_dataframe, new_dataframe):
    for new_index, new_row in new_dataframe.iterrorws():
        old_dataframe.loc[new_index] = update_row(old_dataframe.loc[new_index], new_row)

def update_row(old_row, new_row):
    for field in [list_of_columns]:
        # line with warning because of chain indexing old_dataframe[new_index][field]
        old_row[field] = new_row[field]  
    return old_row

এটি লাইনের জন্য সতর্কতা মুদ্রণ করেছে old_row[field] = new_row[field]

আপডেট_রো পদ্ধতির সারিগুলি যেহেতু প্রকৃতপক্ষে টাইপ করা হয়েছে তাই Seriesআমি লাইনটি এর সাথে প্রতিস্থাপন করেছি:

old_row.at[field] = new_row.at[field]

অ্যাক্সেস করার জন্য অর্থ পদ্ধতি / দেখার জন্য Series। ঘটনাচক্রে উভয়ই ঠিক কাজ করে এবং ফলাফল একই, এইভাবে আমাকে সতর্কতাগুলি অক্ষম করতে হবে না (= অন্য চেইনের সূচক ইস্যুগুলির জন্য অন্য কোথাও এগুলি রাখুন)।

আমি আশা করি এটি কারও সাহায্য করতে পারে।


2

আপনি পুরো সমস্যাটি এড়ানোতে পারতেন, আমি বিশ্বাস করি:

return (
    pd.read_csv(StringIO(str_of_all), sep=',', names=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg')) #dtype={'A': object, 'B': object, 'C': np.float64}
    .rename(columns={'A':'STK', 'B':'TOpen', 'C':'TPCLOSE', 'D':'TPrice', 'E':'THigh', 'F':'TLow', 'I':'TVol', 'J':'TAmt', 'e':'TDate', 'f':'TTime'}, inplace=True)
    .ix[:,[0,3,2,1,4,5,8,9,30,31]]
    .assign(
        TClose=lambda df: df['TPrice'],
        RT=lambda df: 100 * (df['TPrice']/quote_df['TPCLOSE'] - 1),
        TVol=lambda df: df['TVol']/TVOL_SCALE,
        TAmt=lambda df: df['TAmt']/TAMT_SCALE,
        STK_ID=lambda df: df['STK'].str.slice(13,19),
        STK_Name=lambda df: df['STK'].str.slice(21,30)#.decode('gb2312'),
        TDate=lambda df: df.TDate.map(lambda x: x[0:4]+x[5:7]+x[8:10]),
    )
)

বরাদ্দ ব্যবহার করে। ডকুমেন্টেশন থেকে : নতুন কলামগুলি একটি ডেটা ফ্রেমে বরাদ্দ করুন, নতুন সামগ্রীর পাশাপাশি সমস্ত মূল কলাম সহ একটি নতুন অবজেক্ট (একটি অনুলিপি) ফিরিয়ে দিন।

পান্ডাসে শৃঙ্খলাবদ্ধ পদ্ধতি সম্পর্কে টম অগস্পারগার নিবন্ধটি দেখুন: https://tomaugspurger.github.io/method-chaining


2

ফলোআপ শুরুর প্রশ্ন / মন্তব্য

আমার মতো অন্যান্য নতুনদের জন্যও স্পষ্টতা থাকতে পারে (আমি আর থেকে এসেছি যা মনে হয় হুডের নীচে কিছুটা আলাদাভাবে কাজ করবে)। নিম্নলিখিত নিরীহ-চেহারা এবং কার্যকরী কোডটি সেটিংউইথকপি সতর্কতা উত্পাদন করে চলেছে এবং আমি কেন এটি বুঝতে পারি না। আমি "চেইনড ইনডেক্সিং" দিয়ে জারি করা উভয়কেই বুঝতে এবং বুঝতে পেরেছিলাম, তবে আমার কোডটিতে কোনওটি নেই:

def plot(pdb, df, title, **kw):
    df['target'] = (df['ogg'] + df['ugg']) / 2
    # ...

তবে, পরে, অনেক দেরিতে, আমি প্লট () ফাংশনটি কোথায় ডাকা হয়েছে তার দিকে তাকিয়েছিলাম:

    df = data[data['anz_emw'] > 0]
    pixbuf = plot(pdb, df, title)

সুতরাং "ডিএফ" কোনও ডেটা ফ্রেম নয় বরং এমন একটি অবজেক্ট যা কোনওরকম মনে রাখে যে এটি একটি ডেটা ফ্রেমকে সূচীকরণের মাধ্যমে তৈরি করা হয়েছিল (সুতরাং এটি কী একটি দৃশ্য?) যা প্লট () এ রেখাটি তৈরি করবে)

 df['target'] = ...

সমতুল্য

 data[data['anz_emw'] > 0]['target'] = ...

এটি একটি শৃঙ্খলিত সূচক। আমি কি অধিকার পেয়েছি?

যাই হোক,

def plot(pdb, df, title, **kw):
    df.loc[:,'target'] = (df['ogg'] + df['ugg']) / 2

ঠিক কর.


1

যেহেতু এই প্রশ্নটি ইতিমধ্যে সম্পূর্ণরূপে বিদ্যমান জবাবগুলিতে সম্পূর্ণ ব্যাখ্যা করা হয়েছে এবং আলোচনা করা হয়েছে আমি কেবল pandasপ্রসঙ্গ ব্যবস্থাপককে ব্যবহার করে একটি পরিষ্কার ঝলক সরবরাহ করব pandas.option_context( ডক্স এবং উদাহরণের লিঙ্কগুলি) ) - সমস্ত ডেনার পদ্ধতি এবং অন্যান্য ঘন্টার সাথে একটি কাস্টম ক্লাস তৈরি করার একেবারেই দরকার নেই এবং হুইসেলস

প্রথমে কনটেক্সট ম্যানেজারের কোড নিজেই:

from contextlib import contextmanager

@contextmanager
def SuppressPandasWarning():
    with pd.option_context("mode.chained_assignment", None):
        yield

তারপরে একটি উদাহরণ:

import pandas as pd
from string import ascii_letters

a = pd.DataFrame({"A": list(ascii_letters[0:4]), "B": range(0,4)})

mask = a["A"].isin(["c", "d"])
# Even shallow copy below is enough to not raise the warning, but why is a mystery to me.
b = a.loc[mask]  # .copy(deep=False)

# Raises the `SettingWithCopyWarning`
b["B"] = b["B"] * 2

# Does not!
with SuppressPandasWarning():
    b["B"] = b["B"] * 2

মূল্যবান লক্ষ্য করার বিষয় হ'ল উভয় অ্যাপ্রোকস সংশোধন করে না a, যা আমার কাছে খানিকটা অবাক করার মত বিষয় এবং এমনকি একটি অগভীর ডিএফ অনুলিপিও .copy(deep=False)এই সতর্কতাটি বাড়াতে বাধা দিতে পারে (যতদূর আমি বুঝতে পারি যে অগভীর অনুলিপিটিও কমপক্ষে aপাশাপাশি সংশোধন করা উচিত , তবে এটি কার্যকর হয়নি) 'টি। pandasযাদু।)।


হুঁ, আমি যদি বুঝতে পারি যে যদি সতর্কতা উত্থাপিত কিছু ভুল হয় তবে স্পষ্টভাবে সতর্ক করা থেকে দূরে থাকাই এটিকে চাপ দেওয়ার মতো, তাই কি মনে হয়?
jezrael

না, সতর্কতা কেবল একটি সতর্কতা। এখানে যেমন, এটি আপনাকে সতর্ক করে দিচ্ছে এমন কিছু ভুল হতে পারে যা জানার জন্য দুর্দান্ত তবে আপনি যদি জানেন এবং আপনি কী করছেন তবে তাদের কিছুকে দমন করার পক্ষে এটি ঠিক আছে fine রেফারেন্সগুলি পুনরায় অর্পণ সম্পর্কে stackoverflow.com/a/20627316/4272484 এ ব্যাখ্যা দেখুন ।
এম-ডিজে

1

আমি এই পদ্ধতিটি .apply()ব্যবহার করেছি এমন প্রাক-বিদ্যমান ডেটাফ্রেম থেকে একটি নতুন ডেটাফ্রেম নির্ধারণের সাথে আমি এই সমস্যাটি পেয়ে আসছিলাম .query()। এই ক্ষেত্রে:

prop_df = df.query('column == "value"')
prop_df['new_column'] = prop_df.apply(function, axis=1)

এই ত্রুটি ফিরে আসবে। এই ক্ষেত্রে ত্রুটিটি সমাধান করার জন্য যে সমস্যাটি মনে হচ্ছে তা হ'ল এটিতে পরিবর্তন করে:

prop_df = df.copy(deep=True)
prop_df = prop_df.query('column == "value"')
prop_df['new_column'] = prop_df.apply(function, axis=1)

যাইহোক, এটি কার্যকর নয় বিশেষত যখন একটি নতুন অনুলিপি তৈরি করার কারণে বড় ডেটাফ্রেমগুলি ব্যবহার করা হয়।

আপনি ব্যবহার করেন, তাহলে .apply()একটি নতুন কলাম এবং তার মূল্যবোধ, একটি ফিক্স যে ত্রুটি সমাধান করা এবং যোগ করে বেশি দক্ষ হয় উৎপাদিত পদ্ধতি .reset_index(drop=True):

prop_df = df.query('column == "value"').reset_index(drop=True)
prop_df['new_column'] = prop_df.apply(function, axis=1)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.