पंक्ति द्वारा पंक्ति पुनरावृति करते हुए पंडों में एक डेटाफ्रेम अद्यतन करें


213

मेरे पास एक पंडों का डेटा फ्रेम है जो इस तरह दिखता है (यह एक बहुत बड़ा है)

           date      exer exp     ifor         mat  
1092  2014-03-17  American   M  528.205  2014-04-19 
1093  2014-03-17  American   M  528.205  2014-04-19 
1094  2014-03-17  American   M  528.205  2014-04-19 
1095  2014-03-17  American   M  528.205  2014-04-19    
1096  2014-03-17  American   M  528.205  2014-05-17 

अब मैं पंक्ति द्वारा पंक्ति को पुनरावृत्त करना चाहूंगा और जैसा कि मैं प्रत्येक पंक्ति से गुजरता हूं, प्रत्येक पंक्ति का मूल्य ifor कुछ शर्तों के आधार पर बदल सकता है और मुझे एक और डेटाफ़्रेम देखने की आवश्यकता है।

अब, मैं इसे I iterate के रूप में कैसे अपडेट करूं। कुछ चीजों की कोशिश की उनमें से कोई भी काम नहीं किया।

for i, row in df.iterrows():
    if <something>:
        row['ifor'] = x
    else:
        row['ifor'] = y

    df.ix[i]['ifor'] = x

इनमें से कोई भी दृष्टिकोण काम नहीं करता है। मुझे डेटाफ़्रेम में अपडेट किए गए मान दिखाई नहीं देते हैं।


2
मुझे लगता है कि आप चाहते हैं df.ix[i,'ifor']df.ix[i]['ifor']समस्याग्रस्त है क्योंकि यह जंजीर अनुक्रमण है (जो पांडा में विश्वसनीय नहीं है)।
कार्ल डी।

1
आप के रूप में अच्छी तरह से अन्य फ्रेम प्रदान कर सकते हैं <something>। आपका कोड वेक्टर किया जा सकता है या नहीं, यह उन चीजों पर निर्भर करेगा। सामान्य तौर पर, से बचें iterrows। आपके मामले में, आपको निश्चित रूप से इससे बचना चाहिए क्योंकि प्रत्येक पंक्ति एक objectdtype होगी Series
फिलिप क्लाउड

आप अपनी स्थिति के लिए बूलियन मास्क बनाने से बेहतर होंगे, उन सभी पंक्तियों को अपडेट करें और फिर बाकी को अन्य मूल्य पर सेट करें
EdChum

कृपया iterrows () का उपयोग न करें। यह पंडों के इतिहास में सबसे खराब प्रतिमान का एक कुंद प्रलाप है।
cs95

जवाबों:


232

आप df.set_value का उपयोग करके लूप में मान निर्दिष्ट कर सकते हैं:

for i, row in df.iterrows():
    ifor_val = something
    if <condition>:
        ifor_val = something_else
    df.set_value(i,'ifor',ifor_val)

यदि आपको पंक्ति मूल्यों की आवश्यकता नहीं है, तो आप केवल df के सूचकांकों पर पुनरावृति कर सकते हैं, लेकिन मैंने मूल फॉर-लूप को उस स्थिति में रखा है जब आपको यहां दिखाई न देने वाली चीज़ के लिए पंक्ति मूल्य की आवश्यकता होती है।

अपडेट करें

df.set_value () को संस्करण 0.21.0 के बाद से हटा दिया गया है। आप इसके बजाय df.at () का उपयोग कर सकते हैं:

for i, row in df.iterrows():
    ifor_val = something
    if <condition>:
        ifor_val = something_else
    df.at[i,'ifor'] = ifor_val

6
Pandas.pydata.org/pandas-docs/stable/generated/… , दूसरी बुलेट देखें : "2. आपको कभी भी किसी चीज को संशोधित नहीं करना चाहिए जो आप पर निर्भर हैं"
जोसफोविक

32
मुझे यकीन नहीं है कि अगर हम इसे बिल्कुल वैसा ही पढ़ें। यदि आप मेरे छद्म कोड में देखते हैं, तो मैं डेटाफ़्रेम पर संशोधन करता हूं, न कि इटिटर से मान पर। इटरेटर मान का उपयोग केवल मूल्य / वस्तु के सूचकांक के लिए किया जाता है। क्या विफल होगा पंक्ति ['ifor'] = some_thing, प्रलेखन में उल्लिखित कारणों के लिए।
रकके

3
स्पष्टीकरण के लिए धन्यवाद।
जोसफोविक

8
अब set_value भी सही हो गया है, और .at (या .iat) का उपयोग करना चाहिए, इसलिए मेरा लूप इस तरह दिखता है: i, i के लिए पंक्ति में df.iterrows (): ifor_val = something if <कंडीशन>: ifor_yro = something_else df.at [ i, 'ifor'] = ifor_val
complexM

2
set_value को हटा दिया गया है और भविष्य में रिलीज़ में हटा दिया जाएगा। कृपया इसके बजाय .at [] या .iat [] एक्सेसर्स का उपयोग करें
रॉयउमिक्स

75

पंडों डेटाफ्रेम वस्तु को एक श्रृंखला श्रृंखला के रूप में सोचा जाना चाहिए। दूसरे शब्दों में, आपको कॉलम के संदर्भ में सोचना चाहिए। इस कारण से यह महत्वपूर्ण है क्योंकि जब आप उपयोग pd.DataFrame.iterrowsकरते हैं तो आप श्रृंखला के रूप में पंक्तियों के माध्यम से पुनरावृत्त होते हैं। लेकिन ये वे श्रृंखलाएँ नहीं हैं जिन्हें डेटा फ़्रेम संग्रहीत कर रहा है और इसलिए वे नई श्रृंखलाएँ हैं जो आपके लिए पुनरावृति करते समय आपके लिए बनाई गई हैं। इसका मतलब यह है कि जब आप उन्हें निर्दिष्ट करने का प्रयास करते हैं, तो वे संपादन मूल डेटा फ़्रेम में दिखाई नहीं देंगे।

ठीक है, अब जो कि बाहर है: हम क्या करते हैं?

इस पोस्ट से पहले के सुझावों में शामिल हैं:

  1. pd.DataFrame.set_valueको पंडों के संस्करण 0.21 के रूप में चित्रित किया गया है
  2. pd.DataFrame.ixहै पदावनत
  3. pd.DataFrame.locठीक है, लेकिन ऐरे इंडेक्स पर काम कर सकते हैं और आप बेहतर कर सकते हैं

मेरी सिफारिश का
उपयोग करेंpd.DataFrame.at

for i in df.index:
    if <something>:
        df.at[i, 'ifor'] = x
    else:
        df.at[i, 'ifor'] = y

आप इसे यहां तक ​​बदल सकते हैं:

for i in df.index:
    df.at[i, 'ifor'] = x if <something> else y

टिप्पणी करने के लिए प्रतिक्रिया

और क्या होगा अगर मुझे पिछली पंक्ति के मान का उपयोग करने की आवश्यकता है तो क्या शर्त है?

for i in range(1, len(df) + 1):
    j = df.columns.get_loc('ifor')
    if <something>:
        df.iat[i - 1, j] = x
    else:
        df.iat[i - 1, j] = y

और क्या होगा अगर मुझे पिछली पंक्ति के मान का उपयोग करने की आवश्यकता है तो क्या शर्त है? OG df में एक लैग्ड कॉलम जोड़ें?
युका

दक्षता के लिहाज से, क्या आपका दृष्टिकोण बेहतर है बनाम एक लंबित स्तंभ जोड़ना या छोटे डेटासेट के लिए प्रभाव नगण्य है? (<10k पंक्तियों)
युका

वह निर्भर करता है। मैं एक लैग्ड कॉलम का उपयोग करने के लिए जाऊंगा। यह उत्तर दिखा रहा है कि यदि आपको लूप करना है तो क्या करना है। लेकिन अगर आपको लूप नहीं करना है, तो न करें।
piRSquared

समझ गया, अगर यह संभव है कि आपकी प्रतिक्रिया stackoverflow.com/q/51753001/9754169 पर हो तो यह बहुत बढ़िया होगा: D
Yuca

पुराने विकल्पों के साथ .at [] के लिए अच्छा है
Justas

35

एक विधि itertuples()जिसका आप उपयोग कर सकते हैं , यह डेटाफ़्रेम पंक्तियों पर नामांकित के रूप में पुनरावृत्त करता है , टुपल के पहले तत्व के रूप में सूचकांक मूल्य के साथ। और इसकी तुलना में बहुत अधिक तेज है iterrows()। इसके लिए itertuples(), प्रत्येक rowमें IndexDataFrame होता है, और आप locमान सेट करने के लिए उपयोग कर सकते हैं ।

for row in df.itertuples():
    if <something>:
        df.at[row.Index, 'ifor'] = x
    else:
        df.at[row.Index, 'ifor'] = x

    df.loc[row.Index, 'ifor'] = x

ज्यादातर मामलों में, itertuples()की तुलना में तेज है iatया at

धन्यवाद @SantiStSupery, का उपयोग करने .atकी तुलना में बहुत तेज हैloc


3
चूंकि आप केवल एक सटीक इंडेक्स पर इंगित करते हैं, आप अपने प्रदर्शन को बेहतर बनाने के लिए .loc के बजाय .at का उपयोग करने के बारे में सोच सकते हैं। इस बारे में अधिक जानकारी के लिए इस प्रश्न को देखें
SantiStSupery

अजीब लगता है, लेकिन df.loc[row.Index, 3] = xकाम नहीं करता है। दूसरी ओर, df.loc[row.Index, 'ifor'] = xकाम करता है!
सर्वलोक

19

आपको इसके बजाय df.ix[i, 'exp']=Xया df.loc[i, 'exp']=Xइसके द्वारा मान असाइन करना चाहिए df.ix[i]['ifor'] = x

अन्यथा आप एक दृश्य पर काम कर रहे हैं, और एक वार्मिंग प्राप्त करना चाहिए:

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

लेकिन निश्चित रूप से, लूप शायद बेहतर होना चाहिए कुछ वेक्टराइज्ड एल्गोरिथ्म द्वारा प्रतिस्थापित किया जाए DataFrameजैसा कि @Phillip क्लाउड ने सुझाव दिया है।


10

ठीक है, अगर आप किसी भी तरह से पुनरावृत्ति करने जा रहे हैं, तो सभी का सरलतम तरीका क्यों न अपनाएँ, df['Column'].values[i]

df['Column'] = ''

for i in range(len(df)):
    df['Column'].values[i] = something/update/new_value

या यदि आप नए मूल्यों की तुलना पुराने या उस जैसे किसी भी चीज़ से करना चाहते हैं, तो उसे किसी सूची में संग्रहीत क्यों न करें और अंत में संलग्न करें।

mylist, df['Column'] = [], ''

for <condition>:
    mylist.append(something/update/new_value)

df['Column'] = mylist


0

उपयोग करने वाले lambdaकार्यों का उपयोग करना बेहतर है df.apply()-

df["ifor"] = df.apply(lambda x: {value} if {condition} else x["ifor"], axis=1)

-3

एक कॉलम से MAX नंबर बढ़ाएँ। उदाहरण के लिए :

df1 = [sort_ID, Column1,Column2]
print(df1)

मेरा आउटपुट:

Sort_ID Column1 Column2
12         a    e
45         b    f
65         c    g
78         d    h

MAX = df1['Sort_ID'].max() #This returns my Max Number 

अब, मुझे df2 में एक कॉलम बनाने और अधिकतम मानों को भरने की आवश्यकता है जो MAX बढ़ाता है।

Sort_ID Column1 Column2
79      a1       e1
80      b1       f1
81      c1       g1
82      d1       h1

नोट: df2 में प्रारंभ में केवल Column1 और Column2 होंगे। हमें df1 से MAX के वृद्धिशील कॉलम बनाने और बढ़ाने की आवश्यकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.