2016-09-08 14 views
8

pandas.factorize इनपुट मानों को एक समेकित प्रकार या स्पष्ट चर के रूप में एन्कोड करता है।pandas.factorize एक संपूर्ण डेटा फ्रेम

लेकिन मैं डेटा फ्रेम के कई स्तंभों को आसानी से और कुशलतापूर्वक कैसे परिवर्तित कर सकता हूं? रिवर्स मैपिंग चरण के बारे में क्या?

उदाहरण: इस डेटा फ्रेम में "टाइप 2" जैसे स्ट्रिंग मान वाले कॉलम होते हैं जिन्हें मैं संख्यात्मक मानों में परिवर्तित करना चाहता हूं - और संभवतः उन्हें बाद में अनुवादित करना।

enter image description here

उत्तर

18

आप apply उपयोग कर सकते हैं अगर आप factorize के लिए अलग से प्रत्येक स्तंभ की जरूरत है:

df = pd.DataFrame({'A':['type1','type2','type2'], 
        'B':['type1','type2','type3'], 
        'C':['type1','type3','type3']}) 

print (df) 
     A  B  C 
0 type1 type1 type1 
1 type2 type2 type3 
2 type2 type3 type3 

print (df.apply(lambda x: pd.factorize(x)[0])) 
    A B C 
0 0 0 0 
1 1 1 1 
2 1 2 1 

आप एक ही स्ट्रिंग मान ही सांख्यिक एक के लिए की जरूरत है:

print (df.stack().rank(method='dense').unstack()) 
    A B C 
0 1.0 1.0 1.0 
1 2.0 2.0 3.0 
2 2.0 3.0 3.0 

यदि आपको केवल फ़ंक्शन को लागू करने की आवश्यकता है dict है, जहां आप drop_duplicates आधार पर डुप्लीकेट हटाने की जरूरत द्वारा map के माध्यम से संभव

stacked = df[['B','C']].stack() 
df[['B','C']] = pd.Series(stacked.factorize()[0], index=stacked.index).unstack() 
print (df) 
     A B C 
0 type1 0 0 
1 type2 1 2 
2 type2 2 2 

उन्हें अनुवाद वापस आ गया है:

df[['B','C']] = df[['B','C']].stack().rank(method='dense').unstack() 
print (df) 
     A B C 
0 type1 1.0 1.0 
1 type2 2.0 3.0 
2 type2 3.0 3.0 

factorize साथ समाधान: कुछ स्तंभ, एक सबसेट का उपयोग

vals = df.stack().drop_duplicates().values 
b = [x for x in df.stack().drop_duplicates().rank(method='dense')] 

d1 = dict(zip(b, vals)) 
print (d1) 
{1.0: 'type1', 2.0: 'type2', 3.0: 'type3'} 

df1 = df.stack().rank(method='dense').unstack() 
print (df1) 
    A B C 
0 1.0 1.0 1.0 
1 2.0 2.0 3.0 
2 2.0 3.0 3.0 

print (df1.stack().map(d1).unstack()) 
     A  B  C 
0 type1 type1 type1 
1 type2 type2 type3 
2 type2 type3 type3 
+0

और अगर मैं सिर्फ कॉलम की एक सूची के लिए, हर स्तंभ के लिए समारोह लागू करने के लिए नहीं करना चाहते? – clstaudt

+0

आप सबसेट का उपयोग कर सकते हैं, मुझे एक सेकंड दें। – jezrael

0

मैं अपना उत्तर रीडायरेक्ट करना चाहता हूं: https://stackoverflow.com/a/32011969/1694714

पुराना जवाब

इस समस्या के लिए एक और पठनीय समाधान, जब आप जिसके परिणामस्वरूप DataFrame भर में लगातार श्रेणियों रखना चाहते हैं की जगह उपयोग कर रहा है: द्वारा

def categorise(df): 
    categories = {k: v for v, k in enumerate(df.stack().unique())} 
    return df.replace(categories) 

निष्पादित उदाहरण की तुलना में थोड़ा बदतर @ जेज़राइल, लेकिन पढ़ने के लिए आसान है। साथ ही, यह बड़े डेटासेट के लिए बेहतर हो सकता है। यदि कोई दिलचस्पी लेता है तो मैं कुछ उचित परीक्षण कर सकता हूं।

2

मैं भी इस सवाल का जवाब काफी उपयोगी पाया: https://stackoverflow.com/a/20051631/4643212

मैं एक पांडा DataFrame में मौजूदा स्तंभ ('SrcIP' नाम IP पतों की सूची) से मान लेते हैं और उन्हें में संख्यात्मक मान मैप करने की कोशिश कर रहा था एक नया कॉलम (इस उदाहरण में 'आईडी' नाम दिया गया है)।

समाधान:

df['ID'] = pd.factorize(df.SrcIP)[0] 

परिणाम:

 SrcIP | ID  
192.168.1.112 | 0 
192.168.1.112 | 0 
192.168.4.118 | 1 
192.168.1.112 | 0 
192.168.4.118 | 1 
192.168.5.122 | 2 
192.168.5.122 | 2 
...