2017-04-04 4 views
5

dataframe पर विचार करें dfमैं एक कॉलम द्वारा परिभाषित विभाजनों के भीतर कैसे क्रमबद्ध कर सकता हूं लेकिन वे विभाजन जहां वे हैं?

df = pd.DataFrame(dict(
     A=list('XXYYXXYY'), 
     B=range(8, 0, -1) 
    )) 

print(df) 

    A B 
0 X 8 
1 X 7 
2 Y 6 
3 Y 5 
4 X 4 
5 X 3 
6 Y 2 
7 Y 1 
'X' समूह कॉलम 'A' द्वारा परिभाषित के साथ

, मैं उम्मीद [3, 4, 7, 8] को [8, 7, 4, 3] क्रमबद्ध करना चाहते हैं। हालांकि, मैं उन पंक्तियों को छोड़ना चाहता हूं जहां वे हैं।

A B 
5 X 3 <-- Notice all X are in same positions 
4 X 4 <-- However, `[3, 4, 7, 8]` have shifted 
7 Y 1 
6 Y 2 
1 X 7 <-- 
0 X 8 <-- 
3 Y 5 
2 Y 6 
+0

मैं इसके लिए वास्तव में क्षमा चाहता हूं। अगर मैं अधिक सामान्य समाधान (डॉट और '.eq (1)' के साथ) जोड़ना चाहता हूं तो इस जवाब में मैं टिप्पणी जोड़ता हूं, लेकिन ऐसा लगता है कि आपको नहीं लगता कि यह आवश्यक है। (मैं गलत हूँ? या नहीं?) इसलिए इस कारण से मैं इसे अपने उत्तर में जोड़ता हूं। लेकिन मुझे लगता है कि आप मुझे जानते हैं कि यह आपके लिए समस्या है, तो मैं जवाब के इस हिस्से को हटा देता हूं। यदि भविष्य में यह समस्या है, तो कृपया मुझे हमेशा बताएं, खासकर अगर मेरे और आपके समाधान के बीच पतली सीमा। बहुत अफसोस। – jezrael

+0

मैं इसके बारे में बहुत सोच रहा हूं और मेरी मुख्य समस्या यह नहीं थी कि मुझे पता नहीं है कि यह आपके लिए समस्या है। लेकिन मुझे छोटी दयालुता है। क्या आप मेरी मदद कर सकते हैं टिप्पणी में लिंक में जवाब कैसे बदलते हैं? मुझे कुछ नमूना चाहिए कि 'क्रेडिट किसी अन्य उपयोगकर्ता से संबंधित वाक्य कैसे लिखें:' (या कुछ अलग होना आवश्यक है (मेरी अंग्रेजी इतनी अच्छी नहीं है, दुर्भाग्य से))। धन्यवाद। – jezrael

उत्तर

3

आप transform का उपयोग वापस अपने नए इच्छित सूचकांक आदेश मिलता है, तो reindex उपयोग करने के लिए अपने DataFrame को पुन: व्यवस्थित करने के लिए कर सकते हैं:

# Use transform to return the new ordered index values. 
new_idx = df.groupby('A')['B'].transform(lambda grp: grp.sort_values().index) 

# Reindex. 
df = df.reindex(new_idx.rename(None)) 

आप int से ऊपर की दो पंक्तियों को जोड़ सकते हैं ओ एक लंबी लाइन, अगर वांछित है।

जिसके परिणामस्वरूप उत्पादन:

A B 
5 X 3 
4 X 4 
7 Y 1 
6 Y 2 
1 X 7 
0 X 8 
3 Y 5 
2 Y 6 

ध्यान दें कि अगर आप अपने पुराने सूचकांक maintaing के बारे में परवाह नहीं है, तो आप सीधे transform से पुन: असाइन कर सकते हैं:

df['B'] = df.groupby('A')['B'].transform(lambda grp: grp.sort_values()) 

कौन सा पैदावार:

A B 
0 X 3 
1 X 4 
2 Y 1 
3 Y 2 
4 X 7 
5 X 8 
6 Y 5 
7 Y 6 
+0

मुझे काम करने की उम्मीद नहीं थी! मुझे उम्मीद है कि सूचकांक ऑटो रीयलिन होगा। 'ट्रांसफॉर्म' ऐसा नहीं करता है! जानना बहुत अच्छा है।अब मुझे इसका परीक्षण करना होगा :-) – piRSquared

+0

मैंने यह भी अपेक्षा नहीं की थी कि यह बड़े डेटा सेट पर भी प्रदर्शन करे। मुझे कुछ और सोचने की ज़रूरत है कि यह कैसे नापसंद के साथ किया जाए। – piRSquared

2

एकमात्र तरीका मैंने पाया कि यह कुशलतापूर्वक हल करने के लिए कैसे दो बार सॉर्ट करना और एक बार खोलना था।

v = df.values 

# argsort just first column with kind='mergesort' to preserve subgroup order 
a1 = v[:, 0].argsort(kind='mergesort') 

# Fill in an un-sort array to unwind the `a1` argsort 
a_ = np.empty_like(a1) 
a_[a1] = np.arange(len(a1)) 

# argsort by both columns... not exactly what I want, yet. 
a2 = np.lexsort(v.T[::-1]) 

# Sort with `a2` then unwind the first layer with `a_` 
pd.DataFrame(v[a2][a_], df.index[a2][a_], df.columns) 

    A B 
5 X 3 
4 X 4 
7 Y 1 
6 Y 2 
1 X 7 
0 X 8 
3 Y 5 
2 Y 6 

परीक्षण

कोड

def np_intra_sort(df): 
    v = df.values 
    a1 = v[:, 0].argsort(kind='mergesort') 
    a_ = np.empty_like(a1) 
    a_[a1] = np.arange(len(a1)) 
    a2 = np.lexsort(v.T[::-1]) 
    return pd.DataFrame(v[a2][a_], df.index[a2][a_], df.columns) 

def pd_intra_sort(df): 

    def sub_sort(x): 
     return x.sort_values().index 

    idx = df.groupby('A').B.transform(sub_sort).values 

    return df.reindex(idx) 

छोटे डेटा

Enter image description here

बड़े डेटा

df = pd.DataFrame(dict(
     A=list('XXYYXXYY') * 10000, 
     B=range(8 * 10000, 0, -1) 
    )) 

Enter image description here

संबंधित मुद्दे