लेबल द्वारा चयन करने वाले पंडास कभी-कभी श्रृंखला लौटाते हैं, कभी-कभी डेटाफ़्रेम लौटाते हैं


95

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

ऐसा क्यों है? क्या यह सुनिश्चित करने का एक तरीका है कि मुझे हमेशा डेटा फ्रेम वापस मिले?

In [1]: import pandas as pd

In [2]: df = pd.DataFrame(data=range(5), index=[1, 2, 3, 3, 3])

In [3]: type(df.loc[3])
Out[3]: pandas.core.frame.DataFrame

In [4]: type(df.loc[1])
Out[4]: pandas.core.series.Series

जवाबों:


101

यह माना जाता है कि व्यवहार असंगत है, लेकिन मुझे लगता है कि ऐसे मामलों की कल्पना करना आसान है जहां यह सुविधाजनक है। वैसे भी, हर बार एक DataFrame पाने के लिए, बस एक सूची को पास करें loc। अन्य तरीके भी हैं, लेकिन मेरी राय में यह सबसे साफ है।

In [2]: type(df.loc[[3]])
Out[2]: pandas.core.frame.DataFrame

In [3]: type(df.loc[[1]])
Out[3]: pandas.core.frame.DataFrame

6
धन्यवाद। यह देखते हुए कि लेबल सूचकांक में नहीं है, भले ही यह डेटाफ़्रेम लौटाता है।
नौकरीपेशा लोग

7
FYI करें, एक नॉन-डुप्लिकेट इंडेक्स के साथ, और एक इंडेक्सर (उदाहरण के लिए एक सिंगल लेबल) के साथ, आप हमेशा एक सीरीज को वापस ले लेंगे, इसकी केवल इसलिए कि आपके पास इंडेक्स में डुप्लिकेट है कि यह एक DataFrame है।
जेफ

1
ध्यान दें कि अभी तक एक और गोचर है: यदि सुझाए गए वर्कअराउंड का उपयोग कर रहे हैं, और कोई मिलान पंक्तियाँ नहीं हैं, तो परिणाम एक एकल पंक्ति, सभी NaN के साथ एक DataFrame होगा।
पॉल ऑयस्टर

2
पॉल, आप किस संस्करण के पांडा का उपयोग कर रहे हैं? नवीनतम संस्करण में, मुझे एक KeyErrorकोशिश करने पर मिलता है .loc[[nonexistent_label]]
डैन एलन

2
.locइसके बिना की तुलना में एक सूची का उपयोग करना बहुत धीमा है। अभी भी पठनीय है, लेकिन बहुत तेजी से, बेहतर उपयोग करने के लिएdf.loc[1:1]
जोनाथन

15

आपके पास तीन इंडेक्स आइटम के साथ एक इंडेक्स है 3। इस कारण df.loc[3]से डेटाफ्रेम वापस आ जाएगा।

कारण यह है कि आप कॉलम निर्दिष्ट नहीं करते हैं। इसलिए df.loc[3]सभी कॉलम के तीन आइटम का चयन करता है (जो कॉलम है 0), जबकि df.loc[3,0]एक श्रृंखला वापस करेगा। उदाहरण के लिए df.loc[1:2]एक डेटाफ्रेम भी देता है, क्योंकि आप पंक्तियों को काटते हैं।

df.loc[1]इंडेक्स के रूप में कॉलम नामों के साथ एक एकल पंक्ति (एस ) का चयन एक श्रृंखला देता है।

यदि आप हमेशा एक DataFrame रखना सुनिश्चित करना चाहते हैं, तो आप जैसे स्लाइस कर सकते हैं df.loc[1:1]। एक अन्य विकल्प बूलियन इंडेक्सिंग ( df.loc[df.index==1]) या ले विधि है ( df.take([0])लेकिन यह उपयोग किया गया स्थान लेबल नहीं है!)।


3
मैं जिस व्यवहार की उम्मीद करता हूं। मैं एक पंक्ति में परिवर्तित होने के लिए एकल पंक्तियों के लिए डिज़ाइन निर्णय नहीं समझता - एक पंक्ति के साथ डेटा फ्रेम क्यों नहीं?
नौकरीपेशा लोग

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

6

TLDR

उपयोग करते समय loc

df.loc[:]= डेटाफ्रेम

df.loc[int]= डेटाफ़्रेम यदि आपके पास एक से अधिक कॉलम और सीरीज़ हैं तो आपके पास डेटाफ़्रेम में केवल 1 कॉलम है

df.loc[:, ["col_name"]]= डेटाफ्रेम

df.loc[:, "col_name"]= श्रृंखला

उपयोग नही कर रहा loc

df["col_name"]= श्रृंखला

df[["col_name"]]= डेटाफ्रेम


5

df['columnName']एक श्रृंखला प्राप्त करने के लिए और df[['columnName']]एक डेटाफ़्रेम प्राप्त करने के लिए उपयोग करें ।


1
खबरदार जो मूल df की एक प्रति लेता है।
एसएमसीआई

3

आपने जॉरिस के जवाब के लिए एक टिप्पणी में लिखा है:

"मैं एक पंक्ति में परिवर्तित होने के लिए एकल पंक्तियों के लिए डिज़ाइन निर्णय को नहीं समझता - एक पंक्ति के साथ डेटा फ्रेम क्यों नहीं?"

एक एकल पंक्ति एक श्रृंखला में परिवर्तित नहीं होती है ।
यह है एक श्रृंखला:No, I don't think so, in fact; see the edit

पांडा डेटा संरचनाओं के बारे में सोचने का सबसे अच्छा तरीका कम आयामी डेटा के लिए लचीले कंटेनर हैं। उदाहरण के लिए, DataFrame Series के लिए एक कंटेनर है, और पैनल DataFrame ऑब्जेक्ट्स के लिए एक कंटेनर है। हम इन कंटेनरों से ऑब्जेक्ट्स को डिक्शनरी जैसे अंदाज में डालना और निकालना चाहते हैं।

http://pandas.pydata.org/pandas-docs/stable/overview.html#why-more-than-1-data-structure

पंडों की वस्तुओं का डेटा मॉडल इस तरह चुना गया है। कारण निश्चित रूप से इस तथ्य में निहित है कि यह कुछ फायदे सुनिश्चित करता है जो मुझे नहीं पता है (मैं उद्धरण के अंतिम वाक्य को पूरी तरह से नहीं समझता हूं, शायद यह कारण है)

संपादित करें: मैं मेरे साथ सहमत नहीं हूं

एक DataFrame तत्वों को होगा से बना नहीं किया जा सकता हो , सीरीज क्योंकि निम्नलिखित कोड एक ही प्रकार के "सीरीज" के साथ-साथ के लिए एक कॉलम के लिए के रूप में एक पंक्ति देता है:

import pandas as pd

df = pd.DataFrame(data=[11,12,13], index=[2, 3, 3])

print '-------- df -------------'
print df

print '\n------- df.loc[2] --------'
print df.loc[2]
print 'type(df.loc[1]) : ',type(df.loc[2])

print '\n--------- df[0] ----------'
print df[0]
print 'type(df[0]) : ',type(df[0])

परिणाम

-------- df -------------
    0
2  11
3  12
3  13

------- df.loc[2] --------
0    11
Name: 2, dtype: int64
type(df.loc[1]) :  <class 'pandas.core.series.Series'>

--------- df[0] ----------
2    11
3    12
3    13
Name: 0, dtype: int64
type(df[0]) :  <class 'pandas.core.series.Series'>

तो, यह दिखाने का कोई अर्थ नहीं है कि एक DataFrame श्रृंखला से बना है क्योंकि इन श्रृंखलाओं को क्या कहा जाएगा: कॉलम या पंक्तियाँ? मूर्खतापूर्ण प्रश्न और दृष्टि।

तो फिर DataFrame क्या है?

इस उत्तर के पिछले संस्करण में, मैंने यह प्रश्न पूछा था, Why is that?ओपी के प्रश्न के उत्तर और इसी तरह की पूछताछ के उत्तर को खोजने की कोशिश कर रहा था single rows to get converted into a series - why not a data frame with one row?,
जबकि इस Is there a way to ensure I always get back a data frame?भाग का उत्तर दान एलन द्वारा दिया गया है।

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

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

फिर एक DataFrame ऑब्जेक्ट क्या है?

DataFrame वर्ग उदाहरणों कि है एक विशेष संरचना में जन्म लिया है पैदा करता है NDFrame आधार वर्ग, जो अपने आप से प्राप्त PandasContainer आधार वर्ग भी की एक माता पिता के वर्ग है कि सीरीज वर्ग।
ध्यान दें कि यह पंडों के लिए 0.12 संस्करण तक सही है। आगामी संस्करण 0.13 में, श्रृंखला केवल NDFrame वर्ग से निकलेगी

# with pandas 0.12

from pandas import Series
print 'Series  :\n',Series
print 'Series.__bases__  :\n',Series.__bases__

from pandas import DataFrame
print '\nDataFrame  :\n',DataFrame
print 'DataFrame.__bases__  :\n',DataFrame.__bases__

print '\n-------------------'

from pandas.core.generic import NDFrame
print '\nNDFrame.__bases__  :\n',NDFrame.__bases__

from pandas.core.generic import PandasContainer
print '\nPandasContainer.__bases__  :\n',PandasContainer.__bases__

from pandas.core.base import PandasObject
print '\nPandasObject.__bases__  :\n',PandasObject.__bases__

from pandas.core.base import StringMixin
print '\nStringMixin.__bases__  :\n',StringMixin.__bases__

परिणाम

Series  :
<class 'pandas.core.series.Series'>
Series.__bases__  :
(<class 'pandas.core.generic.PandasContainer'>, <type 'numpy.ndarray'>)

DataFrame  :
<class 'pandas.core.frame.DataFrame'>
DataFrame.__bases__  :
(<class 'pandas.core.generic.NDFrame'>,)

-------------------

NDFrame.__bases__  :
(<class 'pandas.core.generic.PandasContainer'>,)

PandasContainer.__bases__  :
(<class 'pandas.core.base.PandasObject'>,)

PandasObject.__bases__  :
(<class 'pandas.core.base.StringMixin'>,)

StringMixin.__bases__  :
(<type 'object'>,)

तो मेरी समझ अब यह है कि DataFrame उदाहरण में कुछ विधियाँ हैं जो डेटा को पंक्तियों और स्तंभों से निकाले जाने के तरीके को नियंत्रित करने के लिए तैयार की गई हैं।

इस पेज में काम करने के तरीके बताए गए हैं: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing
हम इसे दान एलन और अन्य तरीकों द्वारा दी गई विधि में पाते हैं।

ये निकालने के तरीके क्यों उकेरे गए हैं?
यह निश्चित रूप से है क्योंकि उन्हें डेटा विश्लेषण में बेहतर संभावनाएं और आसानी देने वाले लोगों के रूप में मूल्यांकित किया गया है।
यह ठीक वही है जो इस वाक्य में व्यक्त किया गया है:

पांडा डेटा संरचनाओं के बारे में सोचने का सबसे अच्छा तरीका कम आयामी डेटा के लिए लचीले कंटेनर हैं।

क्यों एक DataFRame उदाहरण से डेटा की निकासी की नहीं इसकी संरचना में निहित है, यह में निहित है क्यों इस संरचना का। मुझे लगता है कि पंडों की डेटा संरचना की संरचना और कार्यप्रणाली को अधिक से अधिक बौद्धिक रूप से सहज होने के लिए छेनी गई है, और विवरण को समझने के लिए, किसी को वेस मैककिनी के ब्लॉग को पढ़ना चाहिए।


1
FYI करें, DataFrame एक ndarray उप-वर्ग नहीं है, न ही एक श्रृंखला है (0.13 से शुरू, इससे पहले कि यह हालांकि था)। ये कुछ ज्यादा ही हुक्मरान हैं।
जेफ

मुझे सूचित करने के लिए धन्यवाद। मैं वास्तव में सराहना करता हूं क्योंकि मैं पंडों की शिक्षा में नया हूं। लेकिन मुझे अच्छी तरह समझने के लिए अधिक जानकारी चाहिए। डॉक्स में यह क्यों लिखा जाता है कि एक श्रृंखला ndarray का उपवर्ग है?
आंखों की रोशनी

यह 0.13 से पहले था (शीघ्र ही जारी), यहाँ देव डॉक्स हैं: pandas.pydata.org/pandas-docs/dev/dsintro.html#series
Jeff

ठीक है। आपका बहुत बहुत धन्यवाद। हालाँकि यह मेरे तर्क और समझ के आधार को नहीं बदलता है, क्या यह है? - पंडों में ०.१३ से हीन, डाटाफ्रैम और अन्य पंडों की वस्तुएं श्रृंखला से अलग हैं: वे उपवर्ग क्या हैं?
आंखों की रोशनी

@ जेफ धन्यवाद। मैंने आपकी जानकारी के बाद अपना जवाब संशोधित किया। मुझे यह जानकर प्रसन्नता होगी कि आप मेरे संपादन के बारे में क्या सोचते हैं।
आंखों की रोशनी

1

यदि उद्देश्य सूचकांक का उपयोग करके डेटा सेट का सबसेट प्राप्त करना है, तो इसका उपयोग करने से बचना सबसे अच्छा है locया iloc। इसके बजाय आपको इसके समान सिंटैक्स का उपयोग करना चाहिए:

df = pd.DataFrame(data=range(5), index=[1, 2, 3, 3, 3])
result = df[df.index == 3] 
isinstance(result, pd.DataFrame) # True

result = df[df.index == 1]
isinstance(result, pd.DataFrame) # True

0

यदि आप डेटाफ्रेम के सूचकांक पर भी चयन करते हैं तो परिणाम एक डाटाफ्रेम या एक श्रृंखला हो सकता है या यह एक श्रृंखला या स्केलर (एकल मूल्य) हो सकता है।

यह फ़ंक्शन सुनिश्चित करता है कि आपको हमेशा अपने चयन से एक सूची मिलती है (यदि df, सूचकांक और स्तंभ मान्य हैं)

def get_list_from_df_column(df, index, column):
    df_or_series = df.loc[index,[column]] 
    # df.loc[index,column] is also possible and returns a series or a scalar
    if isinstance(df_or_series, pd.Series):
        resulting_list = df_or_series.tolist() #get list from series
    else:
        resulting_list = df_or_series[column].tolist() 
        # use the column key to get a series from the dataframe
    return(resulting_list)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.