python - 如何使用 Python 和 Pandas 从 salesforceordereddict 层次结构中提取数据

标签 python json pandas ordereddictionary ordereddict

摘要

简而言之,我需要从包含各个 OrderedDicts 的 pandas 系列中提取数据。到目前为止,进展顺利,但我现在遇到了绊脚石。

当我在 Stack Overflow 上出于演示目的定义自己的数据帧时,我可以使用 OrderedDict 索引功能在 OrderedDict 中查找我想要的数据。但是,当我处理真实数据时,我没有在数据框中定义 OrderedDict,我必须使用函数通过标准 Json 包解析 OrderedDict。

我正在使用的 OrderedDicts 有多个嵌套层次结构,可以按照通常的方式进行操作......

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'])

以上代码将生成“电话销售”。但是,这仅在我为示例手动定义 DataFrame 时才有效,因为我必须使用 collections.OrderedDict 包而无需解析。

背景

下面是我为 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)

在上面的代码中,我有函数 extract_odict_item(),只要我指定我想要的内容,我就可以使用它从数据框中的每个单独的 OrderedDict 中提取数据并将其放入新列中。但是,我希望能够通过 *args 指定尽可能多的参数来表示我想要遍历并从最终键中提取值的嵌套数。

预期结果

我希望能够使用下面的函数接受多个参数并创建一个嵌套索引选择器,如下所示...

# 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']

我可能把这个弄得太复杂了,但我想不出其他任何东西,或者这在 Python 中是否可能。

回答

我能够使用递归函数来处理从ordereddict中选择我需要的数据

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'])

最佳答案

这不是一个确切的答案 - 但如果我正确理解你的问题,你可以尝试递归 -

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

关于python - 如何使用 Python 和 Pandas 从 salesforceordereddict 层次结构中提取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56044849/

相关文章:

java - 如何将 json 反序列化为字典或键值对?

javascript - 如何使用 JSON 中的值填充 UL 列表项而不创建重复项?

python - 在 Python 中比较样本均值与随机分类

Python - 从另一个文件写入新文件

python,混淆装饰和关闭

python - 将一分钟的分钟数转换为小时数和分钟数python

python - 如何使用python一一打印原始行和重复行

python - 在docker-py中公开网络上的端口

javascript - 如何动态遍历 JSON 数据并进行更改..?

python - 将空行添加到 python 数据框中