2016-10-14 6 views
7

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

import pandas as pd 
data = [[112233, 'Rob', 99], [445566, 'John', 88]] 
managers = pd.DataFrame(data) 
managers.columns = ['ManagerId', 'ManagerName', 'ShopId'] 
print managers 

    ManagerId ManagerName ShopId 
0  112233   Rob  99 
1  445566  John  88 


data = [[99, 'Shop1'], [88, 'Shop2']] 
shops = pd.DataFrame(data) 
shops.columns = ['ShopId', 'ShopName'] 
print shops 

    ShopId ShopName 
0  99 Shop1 
1  88 Shop2 

data = [[99, 2000, 3000, 4000], [88, 2500, 3500, 4500]] 
sales = pd.DataFrame(data) 
sales.columns = ['ShopId', 'Year2010', 'Year2011', 'Year2012'] 
print sales 

    ShopId Year2010 Year2011 Year2012 
0  99  2000  3000  4000 
1  88  2500  3500  4500 

तो मैं कस्टम एक्सेल शीट और .pdf रिपोर्ट जबकि डेटा फ्रेम पुनरावृत्ति बनाने के लिए xlsxwriter और reportlab अजगर संकुल का उपयोग करें। सबकुछ बढ़िया दिखता है, और सभी नामित पैकेज अपने काम को वास्तव में अच्छी तरह से करते हैं।

मेरी चिंता हालांकि यह है कि मुझे लगता है कि मेरा कोड बनाए रखने में कठोर हो जाता है क्योंकि मुझे एकाधिक कॉल में एक ही डेटा फ्रेम पंक्तियों को कई बार एक्सेस करने की आवश्यकता होती है।

managers[managers['ShopId'].isin(
    sales[sales['Year2010'] > 1500]['ShopId'])]['ManagerName'].values 
>>> array(['Rob', 'John'], dtype=object) 

मुझे लगता है कि यह देखने के लिए मुश्किल है:

मैं प्रबंधक ऐसे नाम हैं जो दुकानों जो 1500 की तुलना में बिक्री अधिक था साल 2010 में मेरे कोड कॉल के इस प्रकार से भर जाता है के लिए जिम्मेदार हैं प्राप्त करने की आवश्यकता कहो कोड की इस पंक्ति को पढ़ने के दौरान क्या चल रहा है। मैं एकाधिक इंटरमीडिएट चर बना सकता हूं, लेकिन यह कोड की कई पंक्तियों को जोड़ देगा।

डेटाबेस सामान्यीकरण विचारधारा को त्यागना और सभी टुकड़ों को एक अधिक डेटा फ्रेम में एक और डेटा फ्रेम में विलय करना कितना आम है? स्पष्ट रूप से एक डेटा फ्रेम होने का विपक्ष है क्योंकि बाद में अन्य डेटा फ्रेमों को मर्ज करने का प्रयास करते समय यह गन्दा हो सकता है। निश्चित रूप से उन्हें विलय करना डेटा अनावश्यकता की ओर जाता है क्योंकि एक ही प्रबंधक को कई दुकानों को सौंपा जा सकता है।

df[df['Year2010'] > 1500]['ManagerName'].values 
>>> array(['Rob', 'John'], dtype=object) 

हो सकता है कि पांडा काम के इस प्रकार के लिए एक गलत उपकरण है:

df = managers.merge(sales, how='left', on='ShopId'). 
    merge(shops, how='left', on='ShopId') 
print df 

    ManagerId ManagerName ShopId Year2010 Year2011 Year2012 ShopName 
0  112233   Rob  99  2000  3000  4000 Shop1 
1  445566  John  88  2500  3500  4500 Shop2 

कम से कम इस कॉल के छोटे हो जाता है?

सी # डेवलपर्स मेरे कार्यालय में फंसे हुए हैं और मुझे कक्षाओं का उपयोग करने के लिए कहें, लेकिन फिर मेरे पास get_manager_sales(managerid) जैसे तरीकों का एक गुच्छा होगा। रिपोर्टिंग के लिए कक्षा के उदाहरणों को इटरेट करना भी परेशान लगता है क्योंकि मुझे कुछ सॉर्टिंग और इंडेक्सिंग को लागू करने की आवश्यकता होगी (जो मुझे pandas के साथ मुफ्त में मिलती है)।

शब्दकोश काम करेगा, लेकिन यह मौजूदा डेटा को संशोधित करना, विलय आदि करना भी मुश्किल बनाता है। सिंटैक्स या तो बेहतर नहीं होता है।

data_dict = df.to_dict('records') 
[{'ManagerId': 112233L, 
    'ManagerName': 'Rob', 
    'ShopId': 99L, 
    'ShopName': 'Shop1', 
    'Year2010': 2000L, 
    'Year2011': 3000L, 
    'Year2012': 4000L}, 
{'ManagerId': 445566L, 
    'ManagerName': 'John', 
    'ShopId': 88L, 
    'ShopName': 'Shop2', 
    'Year2010': 2500L, 
    'Year2011': 3500L, 
    'Year2012': 4500L}] 

प्राप्त प्रबंधक के नाम जो वर्ष 2010.

[row['ManagerName'] for row in data_dict if row['Year2010'] > 1500] 
>>> ['Rob', 'John'] 

में 1500 की तुलना में बिक्री अधिक था डेटा मैं के साथ काम के साथ इस विशेष मामले में है कि दुकानों के लिए जिम्मेदार हैं, मैं सभी रास्ते जाने चाहिए pandas के साथ या pandas की शक्ति का लाभ उठाने के दौरान क्लीनर कोड लिखने का कोई और तरीका है?

उत्तर

3

मैं पांडों का चयन करूंगा, क्योंकि यह बहुत तेज है, एक उत्कृष्ट और बेहद समृद्ध एपीआई है, एक स्रोत कोड बहुत साफ और बेहतर दिखता है।

BTW निम्न पंक्ति को आसानी से फिर से लिखा जा सकता है:

managers[managers['ShopId'].isin(sales[sales['Year2010'] > 1500]['ShopId'])]['ManagerName'].values 

के रूप में:

ShopIds = sales.ix[sales['Year2010'] > 1500, 'ShopId'] 
managers.query('ShopId in @ShopIds')['ManagerName'].values 

IMO यह बहुत पढ़ने और समझने

पी एस आप भी अपने डाटा स्टोर कर सकते हैं आसान है -able डेटाबेस में और एसक्यूएल का उपयोग करें या इसे एचडीएफ स्टोर में स्टोर करने के लिए और where पैरामीटर का उपयोग करें - दोनों मामलों में आप "खोज" अनुक्रमणित करने से लाभ उठा सकते हैं olumns

+0

कूल, उत्तर के लिए एक टन धन्यवाद, आश्वासन दिया कि रिपोर्ट कार्यक्रम लिखने के लिए पांडा चुनना एक सही काम था। क्या आप सभी सीएसवी फाइलों को डेटा फ्रेम को एक ही में विलय करने पर विचार करेंगे ताकि हर समय क्रॉस-रेफरेंसिंग एकाधिक फ्रेम से बचें? –

+0

@AlexTereshenkov, सुनिश्चित करें कि आप अपनी टेबल को denormalize करने और सब कुछ एक फ्लैट डीएफ में डाल करने की कोशिश कर सकते हैं, लेकिन [संभावित नुकसान] के बारे में पता होना चाहिए (http://stackoverflow.com/questions/40002355/pandas-left- join-why-more -results/40002535 # 40002535) – MaxU

2

डेटाफ्रेम पर चलने वाली कक्षाएं बनाना एक अच्छा विचार नहीं है, क्योंकि यह इस तथ्य को छिपाएगा कि आप डेटा फ्रेम का उपयोग कर रहे हैं, और बहुत खराब निर्णयों के रास्ते को खोलें (जैसे डेटाफ्रेम पर डेटारेट करना for पाश)।

समाधान 1: डेटा को असामान्य करें। आपको अपने डेटा को सामान्य रूप में रखने की आवश्यकता नहीं है। सामान्य रूप से जब आप अपनी प्रविष्टियों को डेटाबेस में सुसंगत रखना चाहते हैं तो सामान्य रूप प्राथमिक होता है। यह डेटाबेस नहीं है, आप निरंतर आवेषण, अद्यतन और हटाना नहीं करते हैं। तो बस इसे denormalize, और एक बड़े डेटा फ्रेम के साथ काम करते हैं, क्योंकि यह स्पष्ट रूप से अधिक सुविधाजनक है, और आपकी आवश्यकताओं के अनुरूप बेहतर है।

समाधान 2: डेटाबेस का उपयोग करें। आप अपने डेटा को SQLite डेटाबेस में डंप कर सकते हैं (पांडा के लिए एक अंतर्निहित फ़ंक्शन है), और उस पर सभी प्रकार के पागल प्रश्न निष्पादित करें। मेरे व्यक्तिगत विकल्प में, आपके द्वारा पोस्ट की गई सामग्री से SQL क्वेरी अधिक पढ़ने योग्य हैं। यदि आप नियमित रूप से इस तरह के विश्लेषण करते हैं, और डेटा संरचना एक ही रहती है, तो यह एक प्राथमिक समाधान हो सकता है। आप डेटा को डीओबी में डंप कर सकते हैं, और फिर इसके साथ काम करने के लिए एसक्लाक्लेमी का उपयोग कर सकते हैं।

समाधान 3. अपना खुद का डाटरम बनाएं। आप pandas.DataFrame से प्राप्त कर सकते हैं और इसमें कस्टम विधियां जोड़ सकते हैं। इसके लिए आपको pandas की गड़बड़ी में खोदने की जरूरत है, हालांकि, उन विधियों को कार्यान्वित करने के तरीके को देखने के लिए। इस तरह आप डेटाफ्रेम के कुछ हिस्सों तक पहुंचने के कस्टम तरीकों को बना सकते हैं।

जब तक कि आप वास्तव में अच्छी तरह से पांडा को नहीं जानते हैं, तो मैं समाधान 1 या 2 के लिए जाऊंगा। यदि आपको अधिक लचीलापन की आवश्यकता है, और डेटा मैनिपुलेशन हर बार अलग होता है, तो 1 का उपयोग करें। यदि आपको हर बार लगभग उसी विश्लेषण को निष्पादित करने की आवश्यकता है , 2 का उपयोग करें (विशेष रूप से यदि आपका डेटा विश्लेषण कोड एक बड़े आवेदन का हिस्सा है)।

इसके अलावा, मुझे समझ में नहीं आता कि "कोड की और रेखाएं जोड़ने" क्यों खराब है। कई अभिव्यक्तियों में एक विशाल एक-लाइनर को तोड़कर, आप वास्तविक जटिलता में वृद्धि नहीं करते हैं, और आप जटिलता को समझते हैं। हो सकता है कि आपको बस इतना करना है कि बस अपना कोड दोबारा दोहराएं, और कुछ परिचालनों को पुन: प्रयोज्य कार्यों में पैक करें?

+0

प्रतिक्रिया के लिए धन्यवाद, बहुत उपयोगी। '1.' कक्षाओं की बात करते हुए, मेरा मतलब उन वर्गों पर था जो पांडा पर आधारित नहीं हैं, फिर भी जिन्हें आप सीएसवी फाइलों से बना सकते हैं (जैसे सीएसवी dictreader)। '2.' 'कुछ संचालन पुन: प्रयोज्य कार्यों में पैक?'कुछ ऐसा है जो मैंने सोचा है, शायद' get_manager_shops() 'और 'get_shops_totalsale()' जैसे कुछ फ़ंक्शंस जोड़ना और उन्हें एक अलग मॉड्यूल में डालने से मेरा जीवन आसान हो सकता है (लेकिन उनके अंदर, यह अभी भी डेटा पर कॉल करेगा फ्रेम, सही?) –

+1

हाँ, आप बस उन कॉल को छुपाएंगे। एक समस्या भी है कि 'पांडा' में कई ऑपरेशन अक्सर डेटाफ्रेम पर एक दृश्य लौटाते हैं। फ़ंक्शन को कॉल करते समय यह स्पष्ट नहीं होगा 'get_shops_totalsale (df) '। इसलिए, आपको इस तरह की चीजों को ध्यान में रखना होगा, जिससे आपके कोड को समझने में कठिनाई होगी। यदि आप कभी इसका ट्रैक खो देते हैं, तो आप अप्रत्याशित दुष्प्रभाव "जादू" प्राप्त कर सकते हैं। –

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