पंडों में एक DataFrame में पंक्तियों पर पुनरावृति कैसे करें?


1943

मेरे पास एक DataFrameपांडा है:

import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df

आउटपुट:

   c1   c2
0  10  100
1  11  110
2  12  120

अब मैं इस फ्रेम की पंक्तियों पर पुनरावृति करना चाहता हूं। हर पंक्ति के लिए मैं कॉलम के नाम से इसके तत्वों (कोशिकाओं में मान) तक पहुंचने में सक्षम होना चाहता हूं। उदाहरण के लिए:

for row in df.rows:
   print row['c1'], row['c2']

क्या पंडों में ऐसा करना संभव है?

मुझे भी ऐसा ही सवाल लगा । लेकिन यह मुझे वह उत्तर नहीं देता जिसकी मुझे आवश्यकता है। उदाहरण के लिए, इसका उपयोग करने के लिए सुझाव दिया गया है:

for date, row in df.T.iteritems():

या

for row in df.iterrows():

लेकिन मुझे समझ नहीं आ रहा है कि rowवस्तु क्या है और मैं इसके साथ कैसे काम कर सकता हूं।


11
Df.iteritems () स्तंभों पर प्रसारित होता है न कि पंक्तियों में। इस प्रकार, पंक्तियों पर इसे पुनरावृत्त करने के लिए, आपको स्थानांतरित करना होगा ("टी"), जिसका अर्थ है कि आप पंक्तियों और स्तंभों को एक दूसरे में बदलते हैं (विकर्ण पर प्रतिबिंबित)। परिणामस्वरूप, जब आप df.T.iteritems ()
Stefan Gruenwald

11
यदि आप इस धागे के लिए नए हैं और पांडा के लिए एक शुरुआत कर रहे हैं, नहीं है !! डेटाफ्रेम पर ओवररिएशन एक एंटी-पैटर्न है, और आपको कुछ ऐसा नहीं करना चाहिए जब तक कि आप बहुत इंतजार करने की आदत न डालें। आप जो करने की कोशिश कर रहे हैं, उसके आधार पर, संभवतः बेहतर विकल्प हैंiter*कार्यों का उपयोग बहुत ही दुर्लभ परिस्थितियों में किया जाना चाहिए। संबंधित भी
cs95

18
सीएस 95 जो कहता है उसके विपरीत, डेटाफ़्रेम पर पुनरावृति करने के लिए पूरी तरह से ठीक कारण हैं, इसलिए नए उपयोगकर्ताओं को हतोत्साहित महसूस नहीं करना चाहिए। एक उदाहरण यदि आप इनपुट के रूप में प्रत्येक पंक्ति के मूल्यों का उपयोग करके कुछ कोड निष्पादित करना चाहते हैं। इसके अलावा, यदि आपकी डेटाफ़्रेम यथोचित रूप से छोटी है (उदाहरण के लिए 1000 से कम आइटम), तो प्रदर्शन वास्तव में कोई समस्या नहीं है।
--ऑलेंज़

1
@oulenz: यदि किसी विषम कारण से आप API का उपयोग करने के लिए उस उद्देश्य के लिए उड़ान भरना चाहते हैं जिसे वह (उच्च-प्रदर्शन डेटा परिवर्तनों) के लिए डिज़ाइन किया गया था, तो मेरे मेहमान बनें। लेकिन बहुत कम से कम, का उपयोग न करें iterrows, एक DataFrame पर पुनरावृति के बेहतर तरीके हैं, आप उस बिंदु पर सूची की सूची पर केवल पुनरावृति कर सकते हैं। यदि आप उस बिंदु पर हैं जहाँ आप डेटाफ़्रेम पर कुछ भी नहीं कर रहे हैं, लेकिन डेटाफ़्रेम का उपयोग करने का वास्तव में कोई लाभ नहीं है (यह मानकर कि आप इसके साथ काम कर रहे हैं, केवल यही है)। बस मेरा 2 सी।
cs95

7
मैं दूसरा @oulenz। जहां तक ​​मैं बता सकता हूं pandasकि डेटासेट छोटा है, तब भी एक सीएसवी फ़ाइल पढ़ने का विकल्प है। यह केवल APIs के साथ डेटा में हेरफेर करने के लिए आसान प्रोग्राम है
क्रिस

जवाबों:


2627

DataFrame.iterrows एक जनरेटर है जो सूचकांक और पंक्ति दोनों का उत्पादन करता है

import pandas as pd
import numpy as np

df = pd.DataFrame([{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}])

for index, row in df.iterrows():
    print(row['c1'], row['c2'])

Output: 
   10 100
   11 110
   12 120

206
नोट: "क्योंकि प्रत्येक पंक्ति के लिए iterrows एक श्रृंखला देता है, यह पंक्तियों में dtypes को संरक्षित नहीं करता है ।" इसके अलावा, "आपको कुछ ऐसी चीजों को संशोधित नहीं करना चाहिए जिन्हें आप देख रहे हैं।" पांडा 0.19.1 डॉक्स के
vidik13

3
@ viddik13 यह एक महान नोट धन्यवाद है। उसकी वजह से मैं एक ऐसे मामले में भाग गया जहाँ संख्यात्मक मान जैसे 431341610650कि जहाँ पढ़ा जाता है 4.31E+11। वहाँ dtypes के संरक्षण के आसपास एक रास्ता है?
अजीज आल्टो

26
@AzizAlto का उपयोग itertuples, जैसा कि नीचे बताया गया है। Pandas.pydata.org/pandas-docs/stable/generated/…
Axel

100
पुनरावृत्तियों का उपयोग न करें। Itertuples तेज है और डेटा प्रकार को संरक्षित करता है। अधिक जानकारी
जेम्स एल।

11
से प्रलेखन : "पांडा वस्तुओं के माध्यम से बार-बार दोहराना आम तौर पर धीमी है कई मामलों में, पंक्तियों पर मैन्युअल रूप से पुनरावृत्ति की जरूरत नहीं है [...]।"। आपका उत्तर सही है (प्रश्न के संदर्भ में) लेकिन इसका कहीं भी उल्लेख नहीं है, इसलिए यह बहुत अच्छा नहीं है।
cs95

450

पंडों में एक DataFrame में पंक्तियों पर पुनरावृति कैसे करें?

उत्तर: नहीं * !

पांडा में गर्भाधान एक विरोधी पैटर्न है, और कुछ ऐसा है जो आपको केवल तभी करना चाहिए जब आपने हर दूसरे विकल्प को समाप्त कर दिया हो। आपको iterकुछ हज़ार से अधिक पंक्तियों के लिए इसके नाम के साथ किसी भी फ़ंक्शन का उपयोग नहीं करना चाहिए या आपको बहुत प्रतीक्षा करने की आदत डालनी होगी।

क्या आप DataFrame प्रिंट करना चाहते हैं? का उपयोग करें DataFrame.to_string()

क्या आप कुछ गणना करना चाहते हैं? उस स्थिति में, इस क्रम में विधियों की खोज करें (सूची यहाँ से संशोधित ):

  1. vectorization
  2. साइथॉन दिनचर्या
  3. सूची समझ (वेनिला forलूप)
  4. DataFrame.apply(): i) साइथन में घटाई जा सकती है, ii) अजगर स्थान में परिवर्तन
  5. DataFrame.itertuples() तथा iteritems()
  6. DataFrame.iterrows()

iterrowsऔर itertuples(इस प्रश्न के उत्तर में कई वोट प्राप्त करने वाले दोनों) का उपयोग बहुत ही दुर्लभ परिस्थितियों में किया जाना चाहिए, जैसे कि क्रमिक प्रसंस्करण के लिए पंक्ति वस्तु / nametuples उत्पन्न करना, जो वास्तव में केवल एक चीज है जो इन कार्यों के लिए उपयोगी है।

प्राधिकरण के पास अपील पर
डॉक्स पृष्ठ में एक बड़ा लाल चेतावनी बॉक्स है जो कहता है:

पंडों की वस्तुओं के माध्यम से Iterating आमतौर पर धीमा है। कई मामलों में, पंक्तियों पर मैन्युअल रूप से पुनरावृत्ति की आवश्यकता नहीं होती है [...]।

* यह वास्तव में "नहीं" की तुलना में थोड़ा अधिक जटिल है। df.iterrows()इस प्रश्न का सही उत्तर है, लेकिन "अपने ऑप्स को वेक्टर करें" बेहतर है। मैं यह स्वीकार करूंगा कि ऐसी परिस्थितियां हैं जहां पुनरावृत्ति से बचा नहीं जा सकता है (उदाहरण के लिए, कुछ संचालन जहां परिणाम पिछली पंक्ति के लिए गणना किए गए मूल्य पर निर्भर करता है)। हालाँकि, यह जानने के लिए पुस्तकालय के साथ कुछ परिचितता लेता है। यदि आपको यकीन नहीं है कि आपको पुनरावृत्त समाधान की आवश्यकता है, तो आप शायद नहीं। पुनश्च: इस उत्तर को लिखने के लिए मेरे औचित्य के बारे में अधिक जानने के लिए, नीचे की ओर जाएं।


लूपिंग की तुलना में तेज़: वेक्टरकरण , साइथन

बुनियादी कार्यों और संगणनाओं की एक अच्छी संख्या पांडा द्वारा (या तो NumPy के माध्यम से, या Cythonized कार्यों के माध्यम से "सदिश" है)। इसमें अंकगणित, तुलनाएं, (अधिकांश) कटौती, पुनर्वसन (जैसे कि धुरी), जुड़ना और समूह संचालन शामिल हैं। अपनी समस्या के लिए एक उपयुक्त सदिश विधि खोजने के लिए आवश्यक बुनियादी कार्यक्षमता पर प्रलेखन के माध्यम से देखें ।

यदि कोई भी मौजूद नहीं है, तो कस्टम साइथन एक्सटेंशन का उपयोग करके अपना स्वयं का लिखने के लिए स्वतंत्र महसूस करें ।


अगली सर्वश्रेष्ठ बात: सूची की समझ *

सूची की समझ आपके कॉल का अगला पोर्ट होना चाहिए अगर 1) कोई सदिश समाधान उपलब्ध नहीं है, 2) प्रदर्शन महत्वपूर्ण है, लेकिन इतना महत्वपूर्ण नहीं है कि आप अपने कोड को साइथोनाइजिंग की परेशानी से गुजरें, और 3) आप तत्व परिवर्तन करने की कोशिश कर रहे हैं अपने कोड पर। कई सामान्य पंडों के कार्यों के लिए यह सुनिश्चित करने के लिए प्रमाणों की एक अच्छी मात्रा है कि सूची की समझ पर्याप्त रूप से तेज (और कभी-कभी तेज भी) है।

सूत्र सरल है,

# iterating over one column - `f` is some function that processes your data
result = [f(x) for x in df['col']]
# iterating over two columns, use `zip`
result = [f(x, y) for x, y in zip(df['col1'], df['col2'])]
# iterating over multiple columns - same data type
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].to_numpy()]
# iterating over multiple columns - differing data type
result = [f(row[0], ..., row[n]) for row in zip(df['col1'], ..., df['coln'])]

यदि आप किसी फ़ंक्शन में अपने व्यावसायिक तर्क को अतिक्रमण कर सकते हैं, तो आप एक सूची समझ का उपयोग कर सकते हैं जो इसे कॉल करता है। आप कच्चे अजगर के सादगी और गति के माध्यम से मनमाने ढंग से जटिल काम कर सकते हैं।

कैविट्स
सूची की समझ यह मानती है कि आपके डेटा के साथ काम करना आसान है - इसका मतलब है कि आपके डेटा प्रकार सुसंगत हैं और आपके पास NaN नहीं हैं, लेकिन यह हमेशा गारंटी नहीं दे सकता है।

  1. पहले वाला अधिक स्पष्ट है, लेकिन NaN के साथ काम करते समय, यदि वे मौजूद हैं (क्योंकि उनके पास बेहतर कॉर्नर-केस हैंडलिंग लॉजिक है) में इन-बिल्ट पांडा तरीके पसंद करते हैं, या सुनिश्चित करें कि आपके व्यावसायिक तर्क में उपयुक्त NaN हैंडलिंग लॉजिक शामिल है।
  2. जब मिश्रित डेटा प्रकार के साथ काम कर तुम पर पुनरावृति करना चाहिए zip(df['A'], df['B'], ...)बजाय df[['A', 'B']].to_numpy()बाद के रूप में परोक्ष सबसे आम प्रकार के डेटा upcasts। एक उदाहरण के रूप में यदि ए संख्यात्मक है और बी स्ट्रिंग है, to_numpy()तो पूरे सरणी को स्ट्रिंग में डाल देगा, जो कि आप नहीं चाहते हैं। सौभाग्य से zipअपने स्तंभों को एक साथ जोड़कर यह सबसे सीधा काम है।

* उपरोक्त केविट्स सेक्शन में उल्लिखित कारणों के लिए YMMV ।


एक स्पष्ट उदाहरण

आइए दो पांडा स्तंभों को जोड़ने के एक सरल उदाहरण के साथ अंतर प्रदर्शित करते हैं A + B। यह एक वेक्टर करने योग्य ऑपरटन है, इसलिए ऊपर चर्चा की गई विधियों के प्रदर्शन के विपरीत करना आसान होगा।

यहां छवि विवरण दर्ज करें

आपके संदर्भ के लिए बेंचमार्किंग कोड।

हालांकि, मुझे यह उल्लेख करना चाहिए कि यह हमेशा यह कटौती और सूखा नहीं है। कभी-कभी "ऑपरेशन के लिए सबसे अच्छा तरीका क्या है" का जवाब "यह आपके डेटा पर निर्भर करता है"। मेरी सलाह है कि किसी एक पर बसने से पहले अपने डेटा पर अलग-अलग तरीकों का परीक्षण करें।


आगे की पढाई

* पंडों स्ट्रिंग विधियों को इस अर्थ में "सदिश" किया जाता है कि वे श्रृंखला पर निर्दिष्ट हैं लेकिन प्रत्येक तत्व पर काम करते हैं। अंतर्निहित तंत्र अभी भी पुनरावृत्त हैं, क्योंकि स्ट्रिंग ऑपरेशनों को वेक्टर करना मुश्किल है।


मैंने यह उत्तर क्यों लिखा

एक सामान्य प्रवृत्ति जो मैं नए उपयोगकर्ताओं से नोटिस करता हूं, वह है फॉर्म के प्रश्न "मैं अपने एक्स पर एक्स करने के लिए कैसे पुनरावृति कर सकता हूं?" कोड दिखा रहा है जो iterrows()लूप के लिए कुछ करने के दौरान कॉल करता है । यहाँ क्यों है। लाइब्रेरी के लिए एक नया उपयोगकर्ता जिसे वैश्वीकरण की अवधारणा के लिए पेश नहीं किया गया है, संभवतः उस कोड की कल्पना करेगा जो कुछ करने के लिए अपने डेटा पर पुनरावृत्ति के रूप में उनकी समस्या को हल करता है। एक DataFrame पर पुनरावृति करना नहीं जानते, पहली बात यह है कि वे इसे Google करते हैं और अंत में, इस सवाल पर। फिर वे स्वीकार किए गए उत्तर को यह बताते हुए देखते हैं कि कैसे, और वे अपनी आँखें बंद कर लेते हैं और इस कोड को बिना पहले प्रश्न किए चलाते हैं कि क्या पुनरावृत्ति करना सही बात नहीं है।

इस उत्तर का उद्देश्य नए उपयोगकर्ताओं को यह समझने में मदद करना है कि पुनरावृत्ति जरूरी नहीं कि हर समस्या का समाधान है, और यह बेहतर, तेज और अधिक मुहावरेदार समाधान मौजूद हो सकता है, और यह कि उन्हें तलाशने में निवेश करने लायक समय है। मैं पुनरावृत्ति बनाम वैश्वीकरण का युद्ध शुरू करने की कोशिश नहीं कर रहा हूं, लेकिन मैं चाहता हूं कि नए उपयोगकर्ताओं को इस पुस्तकालय के साथ उनकी समस्याओं के समाधान के बारे में सूचित किया जाए।


21
यह एकमात्र ऐसा उत्तर है जो मुहावरेदार तकनीकों पर केंद्रित है, जिसका उपयोग पंडों के साथ करना चाहिए, जिससे यह इस सवाल का सबसे अच्छा जवाब बन सके। सही कोड के साथ सही उत्तर प्राप्त करना सीखना ( गलत कोड के साथ सही उत्तर के बजाय - यानी अक्षम, पैमाने नहीं, विशिष्ट डेटा के लिए भी फिट है) सीखने के पांडा (और सामान्य रूप से डेटा) का एक बड़ा हिस्सा है।
लिंकबेरेस्ट

3
मुझे लगता है कि आप पाश के लिए अनुचित हैं, हालांकि, यह देखकर कि वे मेरे परीक्षणों में सूची की समझ की तुलना में केवल थोड़ा धीमा हैं। चाल के zip(df['A'], df['B'])बजाय पाश पर है df.iterrows()
इम्पीरियल नाइट

2
@ImperishableNight बिल्कुल नहीं; इस पोस्ट का बिंदु सामान्य रूप से पुनरावृत्ति को निरूपित करना नहीं है - यह विशेष रूप से उपयोग की निंदा करना है iterrows(), और यदि बेहतर विकल्प मौजूद हैं, तो इसका अर्थ है कि पुनरावृत्ति को निरूपित करना। forअपने आप पर लूप ठीक हैं, लेकिन यदि आप तत्व-वार रूपांतरण कर रहे हैं तो सूची बोध बेहतर है।
cs95

1
@ sdbbs है, अपने डेटा को सॉर्ट करने के लिए Sort_values ​​का उपयोग करें, फिर परिणाम पर to_string () कॉल करें।
CS95

1
सूची समझ के तहत, "कई कॉलम पर पुनरावृत्ति" उदाहरण के लिए एक चेतावनी की जरूरत है: DataFrame.valuesप्रत्येक कॉलम को एक सामान्य डेटा प्रकार में बदल देगा। DataFrame.to_numpy()यह भी करता है। सौभाग्य से हम zipकिसी भी संख्या में कॉलम के साथ उपयोग कर सकते हैं।
डेविड वासरमैन

396

पहले विचार करें कि क्या आपको वास्तव में किसी DataFrame में पंक्तियों पर पुनरावृति करने की आवश्यकता है । विकल्प के लिए यह उत्तर देखें ।

यदि आपको अभी भी पंक्तियों पर पुनरावृति करने की आवश्यकता है, तो आप नीचे दिए गए तरीकों का उपयोग कर सकते हैं। कुछ महत्वपूर्ण चेतावनी पर ध्यान दें, जो अन्य किसी भी उत्तर में उल्लिखित नहीं हैं।

itertuples() से तेज होना चाहिए iterrows()

लेकिन डॉक्स (पांडा 0.24.2 फिलहाल) के अनुसार, जागरूक रहें:

  • iterrows: dtypeपंक्ति से पंक्ति के बीच मेल नहीं हो सकता है

    क्योंकि iterrows प्रत्येक पंक्ति के लिए एक श्रृंखला देता है, यह पंक्तियों के पार dtypes को संरक्षित नहीं करता है (dtypes DataFrames के लिए कॉलम में संरक्षित हैं)। पंक्तियों पर पुनरावृत्ति करते समय dtypes को संरक्षित करने के लिए, itertuples () का उपयोग करना बेहतर होता है, जो मानों के नामितों को लौटाता है और जो पुनरावृत्तियों की तुलना में बहुत तेज़ होता है ()

  • iterrows: पंक्तियों को संशोधित न करें

    आपको कभी भी उस चीज़ को संशोधित नहीं करना चाहिए, जिस पर आप ध्यान दे रहे हैं। यह सभी मामलों में काम करने की गारंटी नहीं है। डेटा प्रकारों के आधार पर, इट्रेटर एक प्रति लौटाता है और एक दृश्य नहीं, और इसे लिखने का कोई प्रभाव नहीं होगा।

    इसके बजाय DataFrame.apply () का उपयोग करें :

    new_df = df.apply(lambda x: x * 2)
  • itertuples:

    यदि वे अमान्य पायथन पहचानकर्ता हैं, तो स्तंभ नाम बदलकर अनधिकृत रूप से पायथन पहचानकर्ताओं को दोहराया जाएगा। बड़ी संख्या में कॉलम (> 255) के साथ, नियमित ट्यूपल्स वापस आ जाते हैं।

देखें यात्रा पर पांडा डॉक्स अधिक जानकारी के लिए।


4
किसी को इस धागे को पूरा होने के इतने लंबे समय बाद पढ़ने से बस एक छोटा सा सवाल: कैसे दक्षता के मामले में df.apply () की तुलना itertuples से की जाती है?
रॉल गुआरिनी

4
नोट: आप for row in df[['c1','c2']].itertuples(index=True, name=None):पंक्ति पुनरावृत्ति में केवल कुछ कॉलमों को शामिल करने के लिए कुछ कह सकते हैं ।
ब्रायन बर्न्स

12
इसके बजाय getattr(row, "c1"), आप बस का उपयोग कर सकते हैं row.c1
विराटपुर

1
मुझे लगभग 90% यकीन है कि यदि आप getattr(row, "c1")इसके बजाय उपयोग करते हैं row.c1, तो आप किसी भी प्रदर्शन लाभ को खो देते हैं itertuples, और यदि आपको वास्तव में एक स्ट्रिंग के माध्यम से संपत्ति प्राप्त करने की आवश्यकता है, तो आपको इसके बजाय इट्रोज़ का उपयोग करना चाहिए।
Noctiphobia

3
मैं इस सवाल पर अड़ गया हूं, क्योंकि मुझे पता था कि स्प्लिट-अप्लाई- कॉम्बिनेशन है, फिर भी मुझे वास्तव में एक DataFrame (जैसा कि प्रश्न कहता है) पर पुनरावृति करने की आवश्यकता है । हर किसी के पास बेहतर करने के लिए लक्जरी नहीं है numbaऔर cython(एक ही डॉक्स का कहना है कि "यह पहले पायथन में हमेशा अनुकूलन के लायक है")। मैंने यह उत्तर दूसरों को बचने में मदद करने के लिए (कभी-कभी निराशाजनक) मुद्दों के रूप में लिखा था, क्योंकि इन जवाबों में से किसी का भी उल्लेख नहीं है। किसी को भी गुमराह करना या "यह सही काम है" यह मेरा इरादा कभी नहीं था। मैंने जवाब में सुधार किया है।
viddik13

201

आपको उपयोग करना चाहिए df.iterrows()। हालांकि पुनरावृति पंक्ति-दर-पंक्ति विशेष रूप से कुशल नहीं है क्योंकि Seriesवस्तुओं का निर्माण किया जाना है।


12
क्या यह DataFrame को एक सुपीरियर सरणी (थ्रू .values) में परिवर्तित करने और सरणी पर सीधे संचालित करने की तुलना में तेज़ है? मेरे पास एक ही समस्या है, लेकिन अंत में एक संख्यात्मक सरणी में परिवर्तित हो गया और फिर साइथन का उपयोग किया गया।
vgoklani

12
@vgoklani यदि पंक्ति-दर-पंक्ति पुनरावृत्त करना अक्षम्य है और आपके पास एक गैर-ऑब्जेक्ट सुपीरियर सरणी है, तो निश्चित रूप से कच्चे खस्ता सरणी का उपयोग तेजी से होगा, विशेष रूप से कई पंक्तियों के साथ सरणियों के लिए। आपको पंक्तियों पर ध्यान देने से बचना चाहिए जब तक कि आपके पास बिल्कुल न हो
फिलिप क्लाउड

7
मैंने df.iterrows (), df.itertuples (), और zip (df ['a]], df [' b ']) के लिए समय की खपत पर थोड़ा परीक्षण किया है और दूसरे के उत्तर में परिणाम पोस्ट किया है प्रश्न: stackoverflow.com/a/34311080/2142098
रिचर्ड वॉन्ग

154

जबकि iterrows()एक अच्छा विकल्प है, कभी कभी itertuples()बहुत तेजी से हो सकता है:

df = pd.DataFrame({'a': randn(1000), 'b': randn(1000),'N': randint(100, 1000, (1000)), 'x': 'x'})

%timeit [row.a * 2 for idx, row in df.iterrows()]
# => 10 loops, best of 3: 50.3 ms per loop

%timeit [row[1] * 2 for row in df.itertuples()]
# => 1000 loops, best of 3: 541 µs per loop

5
आपके दो उदाहरणों में अधिकांश समय का अंतर ऐसा लगता है कि यह इस तथ्य के कारण है कि आप .itrows () कमांड और पूर्णांक-आधारित अनुक्रमण के लिए .itertuples () कमांड के लिए लेबल-आधारित अनुक्रमण का उपयोग करते हुए दिखाई देते हैं।
एलेक्स

2
एक वित्त डेटा आधारित डेटाफ़्रेम (टाइमस्टैम्प, और 4x फ़्लोट) के लिए, इटर्टुपल्स 19,57 गुना अधिक तेज है, फिर मेरी मशीन पर दिखाई देता है। केवल for a,b,c in izip(df["a"],df["b"],df["c"]:लगभग समान रूप से तेज है।
हरबुन

7
क्या आप बता सकते हैं कि यह तेज क्यों है?
अबे मिसेलर

4
@AbeMiessler iterrows()एक श्रृंखला में डेटा की प्रत्येक पंक्ति को बॉक्स itertuples()करता है , जबकि ऐसा नहीं करता है।
मिराडुलो

3
ध्यान दें कि स्तंभों का क्रम वास्तव में अनिश्चित है, क्योंकि dfएक शब्दकोश से बनाया गया है, इसलिए row[1]किसी भी स्तंभ को संदर्भित कर सकता है। जैसा कि यह पता चलता है कि समय पूर्णांक बनाम फ्लोट कॉलम के लिए लगभग समान है।
ब्रायन बर्न्स

88

आप df.apply()पंक्तियों पर पुनरावृति करने और फ़ंक्शन के लिए कई कॉलम तक पहुंचने के लिए भी उपयोग कर सकते हैं ।

डॉक्स: DataFrame.apply ()

def valuation_formula(x, y):
    return x * y * 0.5

df['price'] = df.apply(lambda row: valuation_formula(row['x'], row['y']), axis=1)

क्या df ['मूल्य'] डेटा फ्रेम में एक कॉलम नाम को संदर्भित करता है? मैं एक csv फ़ाइल में कई स्तंभों से अद्वितीय मानों के साथ एक शब्दकोश बनाने की कोशिश कर रहा हूं। मैंने अद्वितीय कुंजियों और मूल्यों के साथ एक शब्दकोश बनाने के लिए आपके तर्क का इस्तेमाल किया और टाइपर्रर
एसआरएस

कोड: df ['वर्कक्लास'] = df.apply (लैम्ब्डा पंक्ति: dic_update (पंक्ति), अक्ष = 1) लाइन आईडी का अंत = पंक्ति के अंत का अंत dic_update (पंक्ति): यदि पंक्ति dic में नहीं है: dic [पंक्ति] = आईडी आईडी = आईडी + १
एसआरएस

कोई बात नहीं, मैं समझ गया। फ़ंक्शन कॉल लाइन को df_new = df में
SRS

2
अक्ष को 0 पर
रखना

9
सूचना जो applyपंक्तियों पर "पुनरावृत्ति" नहीं करती है, बल्कि यह फ़ंक्शन पंक्ति-वार लागू होती है। इसके बाद के संस्करण कोड काम नहीं करता है, तो आप वास्तव में चाहते हैं कर जरूरत पुनरावृत्तियों और indeces, उदाहरण के लिए जब विभिन्न पंक्तियों में मानों की तुलना (उस मामले में आप कुछ भी नहीं लेकिन पुनरावृत्ति कर सकते हैं)।
स्वागत किया

82

आप निम्नानुसार df.iloc फ़ंक्शन का उपयोग कर सकते हैं:

for i in range(0, len(df)):
    print df.iloc[i]['c1'], df.iloc[i]['c2']

1
मुझे पता है कि एक व्यक्ति को पुनरावृत्तियों या पुनरावृत्तियों के पक्ष में इससे बचना चाहिए, लेकिन यह जानना दिलचस्प होगा कि क्यों। कोई विचार?
रोजवराज

12
यह एकमात्र मान्य तकनीक है जो मुझे पता है कि क्या आप डेटा प्रकारों को संरक्षित करना चाहते हैं, और नाम से कॉलम भी देखें। itertuplesडेटा प्रकारों को सुरक्षित रखता है, लेकिन इसे किसी भी नाम से छुटकारा नहीं मिलता है। iterrowsइसके विपरीत करता है।
केन विलियम्स

6
कुछ सरल और अर्थपूर्ण करने के लिए पांडा डेटा संरचनाओं की अज्ञातता के माध्यम से समय बिताने की कोशिश कर रहे घंटे बिताए। इसका परिणाम पठनीय कोड होता है।
सीन एंडरसन

हालांकि for i in range(df.shape[0])इस दृष्टिकोण को थोड़ा गति दे सकता है, फिर भी यह मेरे आवेदन के लिए iterrows () दृष्टिकोण से लगभग 3.5x धीमा है।
किम मिलर

बड़े डेटाफ्रैम पर यह बेहतर लगता है क्योंकि my_iter = df.itertuples()यह मेमोरी को दोगुना कर देता है और इसे कॉपी करने में बहुत समय लगता है। उसी के लिए iterrows()
बस्तियान

33

मैं देख रहा था कि कैसे पंक्तियों और स्तंभों पर चलना है और यहाँ समाप्त हुआ:

for i, row in df.iterrows():
    for j, column in row.iteritems():
        print(column)

18

आप अपने स्वयं के पुनरावृत्ति लिख सकते हैं जो लागू होते हैं namedtuple

from collections import namedtuple

def myiter(d, cols=None):
    if cols is None:
        v = d.values.tolist()
        cols = d.columns.values.tolist()
    else:
        j = [d.columns.get_loc(c) for c in cols]
        v = d.values[:, j].tolist()

    n = namedtuple('MyTuple', cols)

    for line in iter(v):
        yield n(*line)

यह सीधे तुलना करने योग्य है pd.DataFrame.itertuples। मैं एक ही कार्य को अधिक दक्षता के साथ करने का लक्ष्य रख रहा हूं।


मेरे फ़ंक्शन के साथ दिए गए डेटाफ्रेम के लिए:

list(myiter(df))

[MyTuple(c1=10, c2=100), MyTuple(c1=11, c2=110), MyTuple(c1=12, c2=120)]

या साथ pd.DataFrame.itertuples:

list(df.itertuples(index=False))

[Pandas(c1=10, c2=100), Pandas(c1=11, c2=110), Pandas(c1=12, c2=120)]

एक व्यापक परीक्षण
हम सभी कॉलमों को उपलब्ध कराने और कॉलमों को सब्मिट करने का परीक्षण करते हैं।

def iterfullA(d):
    return list(myiter(d))

def iterfullB(d):
    return list(d.itertuples(index=False))

def itersubA(d):
    return list(myiter(d, ['col3', 'col4', 'col5', 'col6', 'col7']))

def itersubB(d):
    return list(d[['col3', 'col4', 'col5', 'col6', 'col7']].itertuples(index=False))

res = pd.DataFrame(
    index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    columns='iterfullA iterfullB itersubA itersubB'.split(),
    dtype=float
)

for i in res.index:
    d = pd.DataFrame(np.random.randint(10, size=(i, 10))).add_prefix('col')
    for j in res.columns:
        stmt = '{}(d)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        res.at[i, j] = timeit(stmt, setp, number=100)

res.groupby(res.columns.str[4:-1], axis=1).plot(loglog=True);

यहां छवि विवरण दर्ज करें

यहां छवि विवरण दर्ज करें


2
उन लोगों के लिए जो कोड नहीं पढ़ना चाहते हैं: नीली रेखा है intertuples, नारंगी रेखा पैदावार ब्लॉक के माध्यम से एक पुनरावृत्त की एक सूची है। interrowsतुलना नहीं है।
जेम्स एल।

18

कुशलता से पुनरावृति कैसे करें?

यदि आपको वास्तव में एक पांडा डेटाफ़्रेम को पुनरावृत्त करना है, तो आप शायद iterrows () का उपयोग करने से बचना चाहेंगे । अलग-अलग विधियां हैं और सामान्य iterrows()सर्वश्रेष्ठ होने से बहुत दूर है। itertuples () 100 गुना तेज हो सकता है।

संक्षेप में:

  • एक सामान्य नियम के रूप में, उपयोग करें df.itertuples(name=None)। विशेष रूप से, जब आपके पास एक निश्चित संख्या कॉलम और 255 से कम कॉलम हैं। देखें बिंदु (3)
  • अन्यथा, df.itertuples()यदि आपके कॉलम में विशेष वर्ण हैं जैसे कि रिक्त स्थान या '-' का उपयोग करें। देखें बिंदु (2)
  • itertuples()यदि अंतिम उदाहरण का उपयोग करके आपके डेटाफ़्रेम में अजीब कॉलम हैं तो भी इसका उपयोग करना संभव है । बिंदु देखें (4)
  • केवल तभी उपयोग करें iterrows()जब आप पिछले समाधान नहीं कर सकते। देखें बिंदु (1)

पंडों के डेटाफ्रेम में पंक्तियों पर पुनरावृति करने के विभिन्न तरीके:

एक लाख पंक्तियों और 4 स्तंभों के साथ एक यादृच्छिक डेटाफ्रेम उत्पन्न करें:

    df = pd.DataFrame(np.random.randint(0, 100, size=(1000000, 4)), columns=list('ABCD'))
    print(df)

1) सामान्य iterrows()सुविधाजनक है, लेकिन बहुत धीमी गति से:

start_time = time.clock()
result = 0
for _, row in df.iterrows():
    result += max(row['B'], row['C'])

total_elapsed_time = round(time.clock() - start_time, 2)
print("1. Iterrows done in {} seconds, result = {}".format(total_elapsed_time, result))

2) डिफ़ॉल्ट itertuples()पहले से ही बहुत तेज है, लेकिन यह स्तंभ नामों के साथ काम नहीं करता है जैसे My Col-Name is very Strange(आपको इस पद्धति से बचना चाहिए यदि आपके कॉलम दोहराए जाते हैं या यदि स्तंभ का नाम केवल एक अजगर चर नाम में परिवर्तित नहीं किया जा सकता है):

start_time = time.clock()
result = 0
for row in df.itertuples(index=False):
    result += max(row.B, row.C)

total_elapsed_time = round(time.clock() - start_time, 2)
print("2. Named Itertuples done in {} seconds, result = {}".format(total_elapsed_time, result))

3) itertuples()नाम का उपयोग करने वाला डिफ़ॉल्ट = कोई भी तेज़ नहीं है लेकिन वास्तव में सुविधाजनक नहीं है क्योंकि आपको प्रति कॉलम एक चर को परिभाषित करना है।

start_time = time.clock()
result = 0
for(_, col1, col2, col3, col4) in df.itertuples(name=None):
    result += max(col2, col3)

total_elapsed_time = round(time.clock() - start_time, 2)
print("3. Itertuples done in {} seconds, result = {}".format(total_elapsed_time, result))

4) अंत में, नाम itertuples()पिछले बिंदु की तुलना में धीमा है लेकिन आपको प्रति कॉलम एक चर को परिभाषित करने की आवश्यकता नहीं है और यह स्तंभ नामों जैसे कि काम करता है My Col-Name is very Strange

start_time = time.clock()
result = 0
for row in df.itertuples(index=False):
    result += max(row[df.columns.get_loc('B')], row[df.columns.get_loc('C')])

total_elapsed_time = round(time.clock() - start_time, 2)
print("4. Polyvalent Itertuples working even with special characters in the column name done in {} seconds, result = {}".format(total_elapsed_time, result))

आउटपुट:

         A   B   C   D
0       41  63  42  23
1       54   9  24  65
2       15  34  10   9
3       39  94  82  97
4        4  88  79  54
...     ..  ..  ..  ..
999995  48  27   4  25
999996  16  51  34  28
999997   1  39  61  14
999998  66  51  27  70
999999  51  53  47  99

[1000000 rows x 4 columns]

1. Iterrows done in 104.96 seconds, result = 66151519
2. Named Itertuples done in 1.26 seconds, result = 66151519
3. Itertuples done in 0.94 seconds, result = 66151519
4. Polyvalent Itertuples working even with special characters in the column name done in 2.94 seconds, result = 66151519

यह लेख iterrows और itertuples के बीच एक बहुत ही दिलचस्प तुलना है


14

एक पंक्ति में सभी पंक्तियों का dataframeउपयोग करने के लिए:

for x in range(len(date_example.index)):
    print date_example['Date'].iloc[x]

1
यह जंजीर अनुक्रमण है। मेरे द्वारा ऐसा करने की सिफारिश नहीं की जाती है।
cs95

@ cs95 इसके बजाय आप क्या सलाह देंगे?
CONvid19

यदि आप यह कार्य करना चाहते हैं, तो दिनांक कॉलम (लूप के बाहर) के पूर्णांक अनुक्रमणिका स्थिति को प्राप्त करने के लिए df.columns.get_loc पर कॉल करें, फिर अंदर एक iloc अनुक्रमण कॉल का उपयोग करें।
सीएस 95

14
 for ind in df.index:
     print df['c1'][ind], df['c2'][ind]

1
बड़े डेटाफ़्रेम (उदाहरण के लिए लाखों पंक्तियों) पर उपयोग किए जाने पर इस विकल्प का प्रदर्शन कैसा है?
बाज़ी देबॉवस्की

ईमानदारी से, मुझे ठीक से पता नहीं है, मुझे लगता है कि सबसे अच्छे उत्तर की तुलना में, बीता हुआ समय उसी के बारे में होगा, क्योंकि दोनों ही मामले "-construction" के लिए उपयोग करते हैं। लेकिन कुछ मामलों में मेमोरी अलग हो सकती है।
ग्रैग २०५

4
यह जंजीर अनुक्रमण है। इस का उपयोग न करें!
CS95

7

कभी-कभी एक उपयोगी पैटर्न होता है:

# Borrowing @KutalmisB df example
df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])
# The to_dict call results in a list of dicts
# where each row_dict is a dictionary with k:v pairs of columns:value for that row
for row_dict in df.to_dict(orient='records'):
    print(row_dict)

जिसके परिणामस्वरूप:

{'col1':1.0, 'col2':0.1}
{'col1':2.0, 'col2':0.2}

6

पाश करने के लिए एक की सभी पंक्तियों dataframeऔर उपयोग प्रत्येक पंक्ति के मूल्यों सुविधा , namedtuplesमें बदला जा सकता ndarrayहै। उदाहरण के लिए:

df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])

पंक्तियों में परिवर्तन:

for row in df.itertuples(index=False, name='Pandas'):
    print np.asarray(row)

का परिणाम:

[ 1.   0.1]
[ 2.   0.2]

कृपया ध्यान दें कि यदि index=True, सूचकांक को टपल के पहले तत्व के रूप में जोड़ा जाता है , जो कुछ अनुप्रयोगों के लिए अवांछनीय हो सकता है।


5

बदले में एक DataFrame प्राप्त करते समय फेंकने वाली पंक्तियों को पुनरावृत्त करने का एक तरीका है, न कि एक श्रृंखला। मुझे यह उल्लेख करते हुए कोई भी नहीं दिखाई देता है कि आप एक सूची के रूप में सूचकांक को पास कर सकते हैं क्योंकि डेटाफ्रेम के रूप में पंक्ति को लौटाया जा सकता है:

for i in range(len(df)):
    row = df.iloc[[i]]

डबल ब्रैकेट के उपयोग पर ध्यान दें। यह एक एकल पंक्ति के साथ एक DataFrame लौटाता है।


छँटाई के बाद एक डेटा फ्रेम में nth सबसे बड़ी पंक्ति प्राप्त करने के लिए यह बहुत मददगार था। धन्यवाद!
जेसन हैरिसन

3

मूल्यों को देखने और संशोधित करने के लिए, मैं उपयोग करूंगा iterrows()। लूप के लिए और टपल अनपैकिंग का उपयोग करके (उदाहरण देखें:) i, row, मैं rowकेवल मान को देखने के लिए उपयोग करता हूं और जब मैं मूल्यों को संशोधित करना चाहता हूं iतो locविधि के साथ उपयोग करता हूं। जैसा कि पिछले उत्तरों में कहा गया है, यहां आपको कुछ ऐसी चीजों को संशोधित नहीं करना चाहिए जिन पर आप अधिक ध्यान दे रहे हैं।

for i, row in df.iterrows():
    df_column_A = df.loc[i, 'A']
    if df_column_A == 'Old_Value':
        df_column_A = 'New_value'  

यहाँ rowलूप में उस पंक्ति की एक प्रति है, न कि इसका एक दृश्य। इसलिए, आपको कुछ लिखना नहीं चाहिए row['A'] = 'New_Value', यह डेटाफ़्रेम को संशोधित नहीं करेगा। हालाँकि, आप कार्य करने के लिए डेटाफ़्रेम का उपयोग iऔर locनिर्दिष्ट कर सकते हैं ।


2

मुझे पता है कि मुझे उत्तर देने वाली पार्टी में देरी हो रही है, लेकिन मैं सिर्फ @ cs95 के उत्तर के ऊपर जोड़ना चाहता था, जो मुझे लगता है कि स्वीकृत उत्तर होना चाहिए। अपने जवाब में, वह दिखाता है कि पांडा वैश्वीकरण डेटाफ़्रेम के साथ सामान की गणना के लिए अन्य पांडा तरीकों को बेहतर बनाते हैं।

मैं यह जोड़ना चाहता था कि यदि आप पहली बार डेटाफ्रेम को एक अफीम सरणी में परिवर्तित करते हैं और फिर वेक्टराइजेशन का उपयोग करते हैं, तो यह पांडा डेटाफ्रेम वेक्टराइजेशन से भी तेज है, (और इसे डेटाफ्रेम श्रृंखला में वापस लाने का समय भी शामिल है)।

यदि आप @ cs95 के बेंचमार्क कोड में निम्नलिखित कार्य जोड़ते हैं, तो यह बहुत स्पष्ट हो जाता है:

def np_vectorization(df):
    np_arr = df.to_numpy()
    return pd.Series(np_arr[:,0] + np_arr[:,1], index=df.index)

def just_np_vectorization(df):
    np_arr = df.to_numpy()
    return np_arr[:,0] + np_arr[:,1]

यहां छवि विवरण दर्ज करें


1

तुम numpyभी अधिक से अधिक गति अप के लिए अनुक्रमण कर सकते हैं । यह वास्तव में पुनरावृत्ति नहीं है, लेकिन कुछ अनुप्रयोगों के लिए पुनरावृत्ति की तुलना में बेहतर काम करता है।

subset = row['c1'][0:5]
all = row['c1'][:]

आप इसे एक सरणी में भी डालना चाहते हैं। ये अनुक्रमणिका / चयन पहले से ही Numpy सरणियों की तरह काम करने वाले हैं, लेकिन मैं मुद्दों में भाग गया और डाली की जरूरत थी

np.asarray(all)
imgs[:] = cv2.resize(imgs[:], (224,224) ) #resize every image in an hdf5 file

1

पांडा डेटाफ्रेम में पंक्तियों पर पुनरावृति करने के लिए बहुत सारे तरीके हैं। एक बहुत ही सरल और सहज तरीका है:

df=pd.DataFrame({'A':[1,2,3], 'B':[4,5,6],'C':[7,8,9]})
print(df)
for i in range(df.shape[0]):
    # For printing the second column
    print(df.iloc[i,1])
    # For printing more than one columns
    print(df.iloc[i,[0,2]])

0

यह उदाहरण डेटा फ्रेम में प्रत्येक अंक को अलग करने के लिए iloc का उपयोग करता है।

import pandas as pd

 a = [1, 2, 3, 4]
 b = [5, 6, 7, 8]

 mjr = pd.DataFrame({'a':a, 'b':b})

 size = mjr.shape

 for i in range(size[0]):
     for j in range(size[1]):
         print(mjr.iloc[i, j])

0

कुछ पुस्तकालयों (उदाहरण के लिए एक जावा इंटरॉप लाइब्रेरी जो मैं उपयोग करता हूं) को एक समय में एक पंक्ति में पारित करने के लिए मूल्यों की आवश्यकता होती है, उदाहरण के लिए, यदि डेटा स्ट्रीमिंग। स्ट्रीमिंग प्रकृति को दोहराने के लिए, मैं अपने डेटाफ्रेम मानों को एक-एक करके 'स्ट्रीम' करता हूं, मैंने नीचे लिखा है, जो समय-समय पर काम में आता है।

class DataFrameReader:
  def __init__(self, df):
    self._df = df
    self._row = None
    self._columns = df.columns.tolist()
    self.reset()
    self.row_index = 0

  def __getattr__(self, key):
    return self.__getitem__(key)

  def read(self) -> bool:
    self._row = next(self._iterator, None)
    self.row_index += 1
    return self._row is not None

  def columns(self):
    return self._columns

  def reset(self) -> None:
    self._iterator = self._df.itertuples()

  def get_index(self):
    return self._row[0]

  def index(self):
    return self._row[0]

  def to_dict(self, columns: List[str] = None):
    return self.row(columns=columns)

  def tolist(self, cols) -> List[object]:
    return [self.__getitem__(c) for c in cols]

  def row(self, columns: List[str] = None) -> Dict[str, object]:
    cols = set(self._columns if columns is None else columns)
    return {c : self.__getitem__(c) for c in self._columns if c in cols}

  def __getitem__(self, key) -> object:
    # the df index of the row is at index 0
    try:
        if type(key) is list:
            ix = [self._columns.index(key) + 1 for k in key]
        else:
            ix = self._columns.index(key) + 1
        return self._row[ix]
    except BaseException as e:
        return None

  def __next__(self) -> 'DataFrameReader':
    if self.read():
        return self
    else:
        raise StopIteration

  def __iter__(self) -> 'DataFrameReader':
    return self

जिसका उपयोग किया जा सकता है:

for row in DataFrameReader(df):
  print(row.my_column_name)
  print(row.to_dict())
  print(row['my_column_name'])
  print(row.tolist())

और पंक्तियों के लिए मान / नाम मैपिंग संरक्षित रखता है। स्पष्ट रूप से, ऊपर बताए अनुसार आवेदन और साइथन का उपयोग करने की तुलना में बहुत धीमा है, लेकिन कुछ परिस्थितियों में आवश्यक है।


0

संक्षेप में

  • यदि संभव हो तो वैश्वीकरण का उपयोग करें
  • यदि ऑपरेशन वेक्टर नहीं किया जा सकता है - सूची समझ का उपयोग करें
  • यदि आपको संपूर्ण पंक्ति का प्रतिनिधित्व करने वाली एक ही वस्तु की आवश्यकता है - इटर्टअप्स का उपयोग करें
  • यदि ऊपर बहुत धीमा है - swifter.apply प्रयास करें
  • यदि यह अभी भी बहुत धीमा है - साइथॉन रूटीन का प्रयास करें

इस वीडियो में विवरण

बेंचमार्क एक पांडा में पंक्तियों पर पुनरावृत्ति की बेंचमार्क DataFrame

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