1 सवाल: पाइथन और पंडों का उपयोग करके बिक्री के क्रमबद्ध पदानुक्रम से डेटा कैसे निकाला जाए

पर बनाया गया सवाल Wed, May 8, 2019 12:00 AM

सारांश

संक्षेप में, मुझे व्यक्तिगत आदेशों वाले पांडा श्रृंखला से डेटा निकालने की आवश्यकता होती है। अब तक की प्रगति अच्छी रही है लेकिन मैंने अब ठोकर खाई है।

जब मैं स्टैक ओवरफ्लो पर प्रदर्शन के उद्देश्यों के लिए अपनी खुद की डेटाफ्रेम को परिभाषित करता हूं, तो ऑर्डर किए गए डेटा को खोजने के लिए मैं ऑर्डरडीडक्ट इंडेक्सिंग कार्यक्षमता का उपयोग करने में सक्षम हूं। हालांकि, जब मैं वास्तविक डेटा के साथ काम करता हूं, जहां मैं डेटाफ्रेम के भीतर ऑर्डरडीड को परिभाषित नहीं कर रहा हूं, तो मुझे फ़ंक्शन का उपयोग करके मानक Json पैकेज के माध्यम से ऑर्डरडीड को पार्स करना है।

मैं जिन आदेशों के साथ काम कर रहा हूं उनमें कई नेस्टेड पदानुक्रम हैं जो सामान्य तरीके से हेरफेर कर सकते हैं ... //>

from collections import OrderedDict

example = OrderedDict([('attributes', OrderedDict([('type', 'Name'), ('url', 'URLHERE')])), ('UserRole', OrderedDict([('attributes', OrderedDict([('type', 'UserRole'), ('url', 'URLHERE')])), ('Name', 'Telephone Sales')]))])

print(example['UserRole']['Name'])

उपरोक्त कोड का परिणाम 'Telephone Sales' होगा। हालांकि, यह केवल तभी काम करता है जब मैंने उदाहरण के लिए मैन्युअल रूप से DataFrame को परिभाषित किया हो क्योंकि मुझे संग्रह का उपयोग करना है। पार्स किए गए पैकेज को पार्स करने की आवश्यकता के बिना

पृष्ठभूमि

नीचे कुछ कोड मैंने StackOverflow के लिए तैयार किए हैं जो मेरी समस्या को शिथिल रूप से प्रदर्शित करता है।

import pandas as pd
import json
from collections import OrderedDict

# Settings
pd.set_option('display.max_colwidth', -1)


# Functions
def extract_odict_item(odict, key_1, key_2=None):
    data = json.dumps(odict)
    final_data = json.loads(data)

    if key_2 is None:
        if final_data is not None:
            return final_data[key_1]
        else:
            return None

    elif key_2 is not None:
        if final_data is not None:
            return final_data[key_1][key_2]
        else:
            return None

# Data
accounts = [
    OrderedDict([('attributes', OrderedDict([('type', 'Account'), ('url', 'URLHERE')])), ('Name', 'Supermarket'), ('AccountNumber', 'ACC1234'), ('MID__c', '123456789')]),
    OrderedDict([('attributes', OrderedDict([('type', 'Account'), ('url', 'URLHERE')])), ('Name', 'Bar'), ('AccountNumber', 'ACC9876'), ('MID__c', '987654321')]),
    OrderedDict([('attributes', OrderedDict([('type', 'Account'), ('url', 'URLHERE')])), ('Name', 'Florist'), ('AccountNumber', 'ACC1298'), ('MID__c', '123459876')])
]

owner = [
    OrderedDict([('attributes', OrderedDict([('type', 'Name'), ('url', 'URLHERE')])), ('UserRole', OrderedDict([('attributes', OrderedDict([('type', 'UserRole'), ('url', 'URLHERE')])), ('Name', 'Telephoone Sales')]))]),
    OrderedDict([('attributes', OrderedDict([('type', 'Name'), ('url', 'URLHERE')])), ('UserRole', OrderedDict([('attributes', OrderedDict([('type', 'UserRole'), ('url', 'URLHERE')])), ('Name', 'Field Sales')]))]),
    OrderedDict([('attributes', OrderedDict([('type', 'Name'), ('url', 'URLHERE')])), ('UserRole', OrderedDict([('attributes', OrderedDict([('type', 'UserRole'), ('url', 'URLHERE')])), ('Name', 'Online Sale')]))])
]

# Dataframe
df = pd.DataFrame({'ConvertedAccounts': accounts,
                   'Owner': owner
                   })

# Extract data from OrderedDict using usual indexing
df['MerchantID'] = df['ConvertedAccounts'].apply(lambda x: x['MID__c'])
df['UserRole'] = df['Owner'].apply(lambda x: x['UserRole']['Name'])

# Extract data from OrderedDict using function
df['extracted_MerchantID'] = df['ConvertedAccounts'].apply(lambda x: extract_odict_item(x, 'MID__c'))
df['extracted_UserRole'] = df['Owner'].apply(
    lambda x: extract_odict_item(x, 'UserRole', 'Name'))

# Drop junk columns
df = df.drop(columns=['ConvertedAccounts', 'Owner'])

print(df)

ऊपर दिए गए कोड में मेरे पास function extract_odict_item () है, जिसका उपयोग मैं डेटाफ़्रेम के भीतर प्रत्येक अलग-अलग ऑर्डर किए गए ऑर्डर से डेटा निकालने के लिए कर सकता हूं और जब तक मैं निर्दिष्ट कर सकता हूं, तब तक एक नए कॉलम में डाल सकता हूं। हालाँकि, मैं यह सुनिश्चित करने में सक्षम होना चाहता हूं कि मैं जितने घोंसले बनाना चाहता हूं, उसका प्रतिनिधित्व करने के लिए कितने तर्क हैं। मैं अंतिम कुंजी से मूल्य निकालना और निकालना चाहता हूं।

अपेक्षित परिणाम

मैं कई तर्कों को स्वीकार करने और एक नेस्टेड इंडेक्स चयनकर्ता बनाने के लिए नीचे दिए गए फ़ंक्शन का उपयोग करने में सक्षम होना चाहता हूं, जैसे ... //>

# Functions
def extract_odict_item(odict, *args):
    data = json.dumps(odict)
    final_data = json.loads(data)
    if len(args) == 0:
        raise Exception('Requires atleast 1 argument')

    elif len(args) == 1:
        if final_data is not None:
            return final_data[args[0]]
        else:
            return None

    elif len(args) > 1:
        ### Pseudo Code ###
        # if final_data is not None:
        #     return final_data[args[0]][args[1]][args[2]] etc.....
        # else:
        #     return None

इसलिए अगर मैं extract_odict_item

कहता हूं

extract_odict_item(odict, 'item1', 'item2', 'item3')

इसे final_data['item1']['item2']['item3']

वापस करना चाहिए

मेरे पास इससे अधिक जटिल हो सकता है, लेकिन मैं किसी और चीज़ के बारे में नहीं सोच सकता या अगर यह पायथन के भीतर भी संभव है।

उत्तर

ऑर्डर से मुझे जो डेटा चाहिए, उसके चयन को संभालने के लिए मैं एक पुनरावर्ती फ़ंक्शन का उपयोग करने में सक्षम था

import json
from collections import OrderedDict

# Settings
pd.set_option('display.max_colwidth', -10)

# Data
owner = [
    OrderedDict([('attributes', OrderedDict([('type', 'Name'), ('url', 'URLHERE')])), ('UserRole', OrderedDict([('attributes', OrderedDict([('type', 'UserRole'), ('url', 'URLHERE')])), ('Name', 'Telephoone Sales')]))]),
    OrderedDict([('attributes', OrderedDict([('type', 'Name'), ('url', 'URLHERE')])), ('UserRole', OrderedDict([('attributes', OrderedDict([('type', 'UserRole'), ('url', 'URLHERE')])), ('Name', 'Field Sales')]))]),
    OrderedDict([('attributes', OrderedDict([('type', 'Name'), ('url', 'URLHERE')])), ('UserRole', OrderedDict([('attributes', OrderedDict([('type', 'UserRole'), ('url', 'URLHERE')])), ('Name', 'Online Sale')]))])
]

# Functions
def rec_ext(odict, item_list):
    new_list = item_list.copy()
    data = json.dumps(odict)
    final_data = json.loads(data)
    el = new_list.pop()
    if isinstance(final_data[el], dict):
        return rec_ext(final_data[el], new_list)
    else:
        return final_data[el]


# Dataframe
df = pd.DataFrame({'owner': owner
                   })

my_columns = ['UserRole', 'Name']
my_columns.reverse()
df['owner2'] = df['owner'].apply(lambda x: rec_ext(x, my_columns))

print(df['owner2'])
    
1
1 उत्तर                              1                         

यह एक सटीक उत्तर नहीं है - लेकिन आप पुनरावर्तन का प्रयास कर सकते हैं यदि मैं आपके प्रश्न को सही ढंग से समझ रहा हूं -

d = {1: {2: {3: {4: 5}}}}#Arbitrarily nested dict
l = [1, 2, 3, 4]

def rec_ext(my_dict, my_list):
     el = my_list.pop()
     if isinstance(my_dict[el], dict):
         return rec_ext(my_dict[el], my_list)
     else:
         return my_dict[el]

l.reverse() #we reverse because we are "popping" in the function 
rec_ext(d, l)
#Returns 5
    
1
2019-05-08 16: 39: 42Z
  1. धन्यवाद मोर्टज़ आपके उत्तर ने बहुत मदद की है! समस्या यह है कि मुझे एक IndexError मिलती है: खाली सूची से पॉप जब मैं फ़ंक्शन को एक लंबास 060035099111101001035062 0600350991100101035062 0600350991100100135062
    का उपयोग करके करता हूं।
    2019-05-09 09: 38: 20Z
  2. my_columns = ['UserRole', 'Name'] समस्या को अच्छी तरह से प्रदर्शित करता है क्योंकि पंडों की श्रृंखला के भीतर फ़ंक्शन 1 आइटम के लिए कार्य करता है
    2019-05-09 09: 43: 00Z
  3. कारण यह है कि my_columns.reverse() सूची को संशोधित किया गया है - जिसका अर्थ है कि यह आपके डेटाफ़्रेम की पहली पंक्ति और बाद की पंक्तियों के लिए काम करता है, df['owner2'] = df['owner'].apply(lambda x: rec_ext(x, my_columns)) सूची def rec_ext2(odict, column_list): new_list = column_list data = json.dumps(odict) final_data = json.loads(data) try: el = new_list.pop() if isinstance(final_data[el], dict): return rec_ext(final_data[el], new_list) else: return final_data[el] except IndexError: pass है। आप अपने फ़ंक्शन को my_columns पर कॉल करके इस समस्या को हल कर सकते हैं। my_columns यह सुनिश्चित करता है कि आप सूची कॉल की सूची को कॉपी कर रहे हैं और सूची का संदर्भ नहीं। आशा है कि यह मदद करता है
    2019-05-09 10: 45: 27Z
  4. ओह वाह मुझे यह बहुत धन्यवाद नहीं पता था! यह मुझे आश्चर्यचकित करता है अगर .reverse () & [:] चरणों को समारोह में ही बनाया जा सकता है?
    2019-05-09 10: 50: 46Z
  5. ऐसा लगता है कि आप सूची का उपयोग करने से बचने के लिए फ़ंक्शन में एक लिस्ट (कॉपी) शामिल कर सकते हैं [:] स्लाइस 06003509911001001350350 //div>
    2019-05-09 10: 55: 52Z
    []
स्रोत रखा गया यहाँ