पांडा डेटाफ़्रेम में कस्टम छँटाई


93

मेरे पास अजगर पांडा डेटाफ़्रेम है, जिसमें एक कॉलम में महीने का नाम होता है।

उदाहरण के लिए, मैं एक शब्दकोश का उपयोग करके कस्टम प्रकार कैसे कर सकता हूं:

custom_dict = {'March':0, 'April':1, 'Dec':3}  

1
क्या एक कॉलम में महीने का नाम होता है, जिसका एक कॉलम होता है, जिसमें महीने के नाम (मेरे उत्तर के रूप में) होते हैं, या कॉलम के नाम वाले कई कॉलम महीने के नाम (यूमिरो के रूप में) होते हैं?
एंडी हेडन

1
स्वीकृत उत्तर पुराना है, और तकनीकी रूप से भी गलत है, क्योंकि pd.Categoricalयह श्रेणियों की व्याख्या नहीं करता है जैसा कि डिफ़ॉल्ट रूप से आदेश दिया गया है। इस जवाब को देखें ।
CS95

जवाबों:


149

पंडों 0.15 ने श्रेणीबद्ध श्रृंखला पेश की , जो इसे करने के लिए बहुत स्पष्ट तरीका देता है:

पहले महीने के कॉलम को एक श्रेणीबद्ध करें और ऑर्डर करने के लिए उपयोग करने के लिए निर्दिष्ट करें।

In [21]: df['m'] = pd.Categorical(df['m'], ["March", "April", "Dec"])

In [22]: df  # looks the same!
Out[22]:
   a  b      m
0  1  2  March
1  5  6    Dec
2  3  4  April

अब, जब आप महीने के कॉलम को छाँटेंगे तो यह उस सूची के संबंध में छाँटेगा:

In [23]: df.sort_values("m")
Out[23]:
   a  b      m
0  1  2  March
2  3  4  April
1  5  6    Dec

नोट: यदि कोई मूल्य सूची में नहीं है तो उसे NaN में बदल दिया जाएगा।


रुचि रखने वालों के लिए एक पुराना उत्तर ...

आप एक मध्यस्थ श्रृंखला बना सकते हैं, और set_indexउस पर:

df = pd.DataFrame([[1, 2, 'March'],[5, 6, 'Dec'],[3, 4, 'April']], columns=['a','b','m'])
s = df['m'].apply(lambda x: {'March':0, 'April':1, 'Dec':3}[x])
s.sort_values()

In [4]: df.set_index(s.index).sort()
Out[4]: 
   a  b      m
0  1  2  March
1  3  4  April
2  5  6    Dec

जैसा कि टिप्पणी की गई है, नए पंडों में, श्रृंखला में replaceइसे और अधिक सुरुचिपूर्ण ढंग से करने की एक विधि है:

s = df['m'].replace({'March':0, 'April':1, 'Dec':3})

मामूली अंतर यह है कि अगर शब्दकोश के बाहर कोई मूल्य नहीं है तो यह नहीं बढ़ेगा (यह सिर्फ वही रहेगा)।


s = df['m'].replace({'March':0, 'April':1, 'Dec':3})लाइन 2 के लिए भी काम करता है - सिर्फ मेरे जैसे पंडों को सीखने के लिए किसी के लिए
kdauria

@ भदौरिया अच्छी जगह! (जब से मैंने यह लिखा है, तब से कुछ समय पहले!) निश्चित रूप से सबसे अच्छा विकल्प बदलें, एक और उपयोग करना है .apply({'March':0, 'April':1, 'Dec':3}.get):) 0.15 में हमारे पास श्रेणीबद्ध श्रृंखलाएं / कॉलम होंगे, इसलिए सबसे अच्छा तरीका यह होगा कि आप इसका उपयोग करें और फिर बस काम करेंगे।
एंडी हेडन

@AndyHayden मैंने दूसरी पंक्ति को 'बदलें' विधि से बदलने की स्वतंत्रता ली है। मुझे उम्मीद है कि ठीक है।
फहीम मीत

@AndyHayden संपादन अस्वीकार कर दिया गया है, लेकिन मुझे अभी भी लगता है कि यह एक उचित बदलाव है।
फहीम मीठा

7
बस सुनिश्चित करें कि आप df.sort_values("m")नए पांडा (इसके बजाय df.sort("m")) में उपयोग करते हैं , अन्यथा आपको मिलेगा AttributeError: 'DataFrame' object has no attribute 'sort';)
मंथन

22

पांडा> = 1.1

आप जल्द ही तर्क के sort_valuesसाथ उपयोग कर पाएंगे key:

pd.__version__
# '1.1.0.dev0+2004.g8d10bfb6f'

custom_dict = {'March': 0, 'April': 1, 'Dec': 3} 
df

   a  b      m
0  1  2  March
1  5  6    Dec
2  3  4  April

df.sort_values(by=['m'], key=lambda x: x.map(custom_dict))

   a  b      m
0  1  2  March
2  3  4  April
1  5  6    Dec

keyतर्क इनपुट एक श्रृंखला और रिटर्न एक श्रृंखला के रूप में लेता है। यह श्रृंखला आंतरिक रूप से आर्ग्यूज़्ड है और सॉर्ट किए गए सूचकांकों का उपयोग इनपुट डेटाफ्रेम को पुनः व्यवस्थित करने के लिए किया जाता है। यदि सॉर्ट करने के लिए कई कॉलम हैं, तो कुंजी फ़ंक्शन बदले में प्रत्येक को लागू किया जाएगा। कुंजी के साथ छंटनी देखें ।


पांडा <= 1.0.X

एक सरल विधि आउटपुट का उपयोग कर रही है Series.mapऔर Series.argsortअनुक्रमणिका dfका उपयोग कर रही है DataFrame.iloc(क्योंकि argsort सॉर्ट किए गए पूर्णांक पदों का उत्पादन करता है); चूंकि आपके पास एक शब्दकोश है; यह आसान हो जाता है।

df.iloc[df['m'].map(custom_dict).argsort()]

   a  b      m
0  1  2  March
2  3  4  April
1  5  6    Dec

यदि आपको अवरोही क्रम में छंटनी करने की आवश्यकता है , तो मानचित्रण को उल्टा करें।

df.iloc[(-df['m'].map(custom_dict)).argsort()]

   a  b      m
1  5  6    Dec
2  3  4  April
0  1  2  March

ध्यान दें कि यह केवल संख्यात्मक वस्तुओं पर काम करता है। अन्यथा, आपको sort_valuesसूचकांक का उपयोग करके , इसे प्राप्त करने की आवश्यकता होगी :

df.loc[df['m'].map(custom_dict).sort_values(ascending=False).index]

   a  b      m
1  5  6    Dec
2  3  4  April
0  1  2  March

इसके साथ और विकल्प उपलब्ध हैं astype(यह अब हटा दिया गया है), या pd.Categorical, लेकिन आपको ordered=Trueइसे सही ढंग से काम करने के लिए निर्दिष्ट करने की आवश्यकता है

# Older version,
# df['m'].astype('category', 
#                categories=sorted(custom_dict, key=custom_dict.get), 
#                ordered=True)
df['m'] = pd.Categorical(df['m'], 
                         categories=sorted(custom_dict, key=custom_dict.get), 
                         ordered=True)

अब, एक साधारण sort_valuesकॉल चाल करेगा:

df.sort_values('m')
 
   a  b      m
0  1  2  March
2  3  4  April
1  5  6    Dec

groupbyआउटपुट को क्रमबद्ध करने पर श्रेणीबद्ध क्रम को भी सम्मानित किया जाएगा ।


2
आप पहले से ही इस पर जोर दे चुके हैं, लेकिन मैं किसी और के स्किम और मिस करने की स्थिति में इसे दोहराना चाहूंगा: ordered=Noneडिफ़ॉल्ट रूप से पंडस श्रेणीबद्ध सेट । यदि सेट नहीं किया गया है, तो आदेश गलत होगा, या V23 पर विराम होगा। विशेष रूप से मैक्स फ़ंक्शन एक टाइपएरर देता है (ऑपरेशन अधिकतम के लिए श्रेणीबद्ध नहीं है)।
डेव लियू

17

अपडेट करें

चयनित उत्तर का उपयोग करें ! यह इस पोस्ट की तुलना में नया है और पंडों में ऑर्डर किए गए डेटा को बनाए रखने के लिए केवल आधिकारिक तरीका नहीं है, यह हर लिहाज से बेहतर है, जिसमें फीचर्स / परफॉर्मेंस आदि शामिल हैं। मेरे द्वारा बताए गए मेरे हैक करने के तरीके का इस्तेमाल न करें।

मैं केवल इस अपडेट को लिख रहा हूं क्योंकि लोग मेरे जवाब को जारी रखते हैं, लेकिन यह निश्चित रूप से स्वीकार किए गए से भी बदतर है :)

मूल पोस्ट

खेल के लिए थोड़ा देर से, लेकिन यहां एक फ़ंक्शन बनाने का एक तरीका है जो पांडा श्रृंखला, डेटाफ़्रेम और मल्टीएंडेक्स डेटाफ़्रेम वस्तुओं को मनमाने कार्यों का उपयोग करके सॉर्ट करता है।

मैं df.iloc[index]विधि का उपयोग करता हूं , जो किसी श्रृंखला में एक पंक्ति / DataFrame को स्थिति (तुलना में df.loc, जो मूल्य द्वारा संदर्भित करता है) का संदर्भ देता है। इसका उपयोग करते हुए, हमारे पास बस एक ऐसा फंक्शन होना चाहिए जो स्थितिगत तर्कों की एक श्रृंखला लौटाए:

def sort_pd(key=None,reverse=False,cmp=None):
    def sorter(series):
        series_list = list(series)
        return [series_list.index(i) 
           for i in sorted(series_list,key=key,reverse=reverse,cmp=cmp)]
    return sorter

कस्टम छँटाई कार्य बनाने के लिए आप इसका उपयोग कर सकते हैं। यह एंडी हेडन के जवाब में प्रयुक्त डेटाफ्रेम पर काम करता है:

df = pd.DataFrame([
    [1, 2, 'March'],
    [5, 6, 'Dec'],
    [3, 4, 'April']], 
  columns=['a','b','m'])

custom_dict = {'March':0, 'April':1, 'Dec':3}
sort_by_custom_dict = sort_pd(key=custom_dict.get)

In [6]: df.iloc[sort_by_custom_dict(df['m'])]
Out[6]:
   a  b  m
0  1  2  March
2  3  4  April
1  5  6  Dec

यह मल्टीएन्डेक्स डेटाफ्रेम और सीरीज ऑब्जेक्ट्स पर भी काम करता है:

months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']

df = pd.DataFrame([
    ['New York','Mar',12714],
    ['New York','Apr',89238],
    ['Atlanta','Jan',8161],
    ['Atlanta','Sep',5885],
  ],columns=['location','month','sales']).set_index(['location','month'])

sort_by_month = sort_pd(key=months.index)

In [10]: df.iloc[sort_by_month(df.index.get_level_values('month'))]
Out[10]:
                 sales
location  month  
Atlanta   Jan    8161
New York  Mar    12714
          Apr    89238
Atlanta   Sep    5885

sort_by_last_digit = sort_pd(key=lambda x: x%10)

In [12]: pd.Series(list(df['sales'])).iloc[sort_by_last_digit(df['sales'])]
Out[12]:
2    8161
0   12714
3    5885
1   89238

मेरे लिए यह साफ लगता है, लेकिन यह अनुकूलित पंडों के संचालन पर भरोसा करने के बजाय अजगर के संचालन का भारी उपयोग करता है। मैंने कोई तनाव परीक्षण नहीं किया है, लेकिन मुझे लगता है कि यह बहुत बड़े DataFrames पर धीमा हो सकता है। यह निश्चित नहीं है कि प्रदर्शन किसी कॉलम को जोड़ने, छँटाई करने की तुलना कैसे करता है। कोड को गति देने के किसी भी सुझाव की सराहना की जाएगी!


क्या यह कई कॉलम / सूचकांकों को छाँटने के लिए काम करेगा?
कॉननग

हां, लेकिन चयनित उत्तर ऐसा करने का एक बेहतर तरीका है। यदि आपके पास कई सूचकांक हैं, तो उन्हें अपने द्वारा पसंद किए गए क्रम के अनुसार व्यवस्थित करें, फिर df.sort_index()सभी सूचकांक स्तरों को क्रमबद्ध करने के लिए उपयोग करें।
माइकल डेलगाडो

9
import pandas as pd
custom_dict = {'March':0,'April':1,'Dec':3}

df = pd.DataFrame(...) # with columns April, March, Dec (probably alphabetically)

df = pd.DataFrame(df, columns=sorted(custom_dict, key=custom_dict.get))

मार्च, अप्रैल, दिसंबर कॉलम के साथ एक DataFrame लौटाता है


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