2012-10-24 10 views
11

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

df = pd.DataFrame({'class': ['A', 'B', 'C'], 'count':[1,0,2]}) 

    class count 
0  A  1 
1  B  0 
2  C  2 

तब्दील किया जाना चाहिए करने के लिए:

class 
0  A 
1  C 
2  C 

यह गिनती समारोह के साथ एकत्रीकरण के विपरीत है। क्या पांडा में इसे प्राप्त करने का कोई आसान तरीका है (लूप या सूची समझ के लिए उपयोग किए बिना)?

एक संभावना DataFrame.applymap फ़ंक्शन रिटर्न एकाधिक पंक्तियों (applyGroupBy की विधि) को अनुमति देने की संभावना हो सकती है। हालांकि, मुझे नहीं लगता कि अब पांडा में यह संभव है।

+0

मुझे एक सामान्य कार्य भी है जो 'गिनती' कॉलम में मानों के आधार पर एकाधिक, एक या शून्य पंक्तियों को वापस करने की अनुमति देगा। – btel

+0

यदि आप 2017+ में इस प्रश्न पर आ रहे हैं, तो मेरे उत्तर को अधिक कुशल और सीधा समाधान के लिए देखें। –

उत्तर

17

आप GroupBy इस्तेमाल कर सकते हैं:

def f(group): 
    row = group.irow(0) 
    return DataFrame({'class': [row['class']] * row['count']}) 
df.groupby('class', group_keys=False).apply(f) 

ताकि आप

In [25]: df.groupby('class', group_keys=False).apply(f) 
Out[25]: 
    class 
0  A 
0  C 
1  C 

आप परिणाम के सूचकांक ठीक कर सकते हैं लेकिन आप

+0

जो मेरी समस्या हल करता है! धन्यवाद वेस – btel

+1

अच्छा जवाब! यदि मेरे पास दर्जनों अन्य कॉलम हैं, तो क्या उन कॉलम को 'एफ' के परिणामस्वरूप उन सभी को स्पष्ट रूप से टाइप करने के अलावा सुरक्षित रखने का कोई आसान तरीका है? –

1
repeated_items = [list(row[1]*row[2]) for row in df.itertuples()] 

एक नेस्टेड सूची प्रदान करेगी:

[['A'], [], ['C', 'C']] 

जिसे फिर आप नए डेटा फ्रेम बनाने के लिए सूची comprehensions साथ अधिक पुनरावृति कर सकते हैं:

new_df = pd.DataFrame({"class":[j for i in repeated_items for j in i]}) 
बेशक

, आप यह कर सकते यदि आप चाहें तो एक पंक्ति में:

new_df = pd.DataFrame({"class":[j for i in [list(row[1]*row[2]) for row in df.itertuples()] for j in i]}) 
3

मैं जानता हूँ कि यह एक पुराने सवाल यह है की तरह मिलता है, लेकिन मैं हो रही थी डेटाफ्रेम में एकाधिक कॉलम के लिए काम करने के लिए वेस का जवाब प्राप्त करने में परेशानी है इसलिए मैंने अपना कोड थोड़ा और सामान्य बना दिया। सोचा कि अगर मैं किसी और समस्या को एक ही समस्या के साथ इस सवाल पर ठोकर खाऊंगा तो मैं साझा करूंगा।

आप मूल रूप से निर्दिष्ट करते हैं कि इसमें किस कॉलम की गणना है और आपको बदले में विस्तारित डेटाफ्रेम मिलता है।

import pandas as pd 
df = pd.DataFrame({'class 1': ['A','B','C','A'], 
        'class 2': [ 1, 2, 3, 1], 
        'count': [ 3, 3, 3, 1]}) 
print df,"\n" 

def f(group, *args): 
    row = group.irow(0) 
    Dict = {} 
    row_dict = row.to_dict() 
    for item in row_dict: Dict[item] = [row[item]] * row[args[0]] 
    return pd.DataFrame(Dict) 

def ExpandRows(df,WeightsColumnName): 
    df_expand = df.groupby(df.columns.tolist(), group_keys=False).apply(f,WeightsColumnName).reset_index(drop=True) 
    return df_expand 


df_expanded = ExpandRows(df,'count') 
print df_expanded 

रिटर्न:

class 1 class 2 count 
0  A  1  3 
1  B  2  3 
2  C  3  3 
3  A  1  1 

    class 1 class 2 count 
0  A  1  1 
1  A  1  3 
2  A  1  3 
3  A  1  3 
4  B  2  3 
5  B  2  3 
6  B  2  3 
7  C  3  3 
8  C  3  3 
9  C  3  3 
के साथ गति के संबंध

, मेरी आधार df से 10 कॉलम 6k पंक्तियों है ~ और जब विस्तार 100,000 पंक्तियों ~ 7 सेकंड लेता है ~ है। मुझे इस मामले में निश्चित नहीं है कि समूहांकन आवश्यक है या बुद्धिमान है क्योंकि यह सभी कॉलम समूह रूप में ले रहा है, लेकिन हे जो कुछ भी 7 सेकंड है।

0

यह प्रश्न बहुत पुराना है और उत्तर पांडा आधुनिक क्षमताओं को प्रतिबिंबित नहीं करते हैं। आप प्रत्येक पंक्ति पर लूप के लिए iterrows का उपयोग कर सकते हैं और फिर पंक्तियों की सही संख्या के साथ नए डेटाफ्रेम बनाने के लिए डेटाफ्रेम कन्स्ट्रक्टर का उपयोग कर सकते हैं। अंत में, सभी पंक्तियों को एकसाथ जोड़ने के लिए pd.concat का उपयोग करें।

pd.concat([pd.DataFrame(data=[row], index=range(row['count'])) 
      for _, row in df.iterrows()], ignore_index=True) 

    class count 
0  A  1 
1  C  2 
2  C  2 

इसका किसी भी आकार डेटाफ्रेम के साथ काम करने का लाभ है।

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