为了账号安全,请及时绑定邮箱和手机立即绑定

使用嵌套 dict 展平 JSON 字符串列表

使用嵌套 dict 展平 JSON 字符串列表

莫回无 2023-07-18 13:41:31
我想对lists进行以下转换tuple:[('1599324732926-0',     {'data': '{"timestamp":1599324732.767,                "receipt_timestamp":1599324732.9256856,                "delta":true,                "bid":{"338.9":0.06482,"338.67":3.95535},                "ask":{"339.12":2.47578,"339.13":6.43172}               }'     } ) ('1599324732926-1',     {'data': '{"timestamp":1599324832.767,                "receipt_timestamp":1599324832.9256856,                "delta":true,                "bid":{"338.8":0.06482,"338.57":3.95535},                "ask":{"340.12":2.47578,"340.13":6.43172}               }'     } )]进入listof dicts 或 Dataframe(无论是其中之一,无论如何从一个到另一个并不复杂):[{  'timestamp': 1599324732.767,  'receipt_timestamp': 1599324732.9256856,  'delta': True,  'side': 'ask',  'price': 338.9,  'size': 0.06482}, {'timestamp': 1599324732.767,  'receipt_timestamp': 1599324732.9256856,  'delta': True,  'side': 'ask',  'price': 338.67,  'size': 3.95535}, {'timestamp': 1599324732.767,  'receipt_timestamp': 1599324732.9256856,  'delta': True,  'side': 'ask',  'price': 338.66,  'size': 16.78636}, {'timestamp': 1599324732.767,  'receipt_timestamp': 1599324732.9256856,  'delta': True,  'side': 'ask',  'price': 338.63,  'size': 2.5}, {'timestamp': 1599324732.767,  'receipt_timestamp': 1599324732.9256856,  'delta': True,  'side': 'ask',  'price': 338.45,  'size': 6.06071}, {'timestamp': 1599324732.767,  'receipt_timestamp': 1599324732.9256856,  'delta': True,  'side': 'ask',  'price': 338.38,  'size': 0.0},所以基本上,第一个 id 被删除(实际上,它被保存在一个单独的列表中)。其中的数据data是一个具有嵌套字典的 JSON 对象。诀窍在于“bid”和“ask”成为结果字典中名为“side”的键的值。嵌套字典“bid”和“ask”的键成为结果字典中名为“price”的键的值。价格的值保留名为“size”的键的值。我能够单独处理列表中的每个 JSON 元素。但列表最多可以有 600k 个元素。我询问是否可以使用一些 pandas 或 numpy 函数来处理整个列表以加快速度?我查看了 pandas json_normalize(),但根据给出的示例,字典的键是系统列,而在这种情况下,“价格”键成为“价格”列的值。你知道我该怎么做吗?有没有办法首先预处理 JSON 列表,以便可以使用json_normalize().仅供参考,这是我可以编写的用于单独处理列表中每个元素的代码,但我认为这不是正确的方向。下一步是将其封装在 for 循环中,与管理整个列表的解决方案相比,这会慢得多。
查看完整描述

2 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

  • 迭代提取信息比使用pandas.json_normalize.

  • 如示例数据所示, 的值data是一种str类型,必须转换为dict.

  • 主要任务是从和中提取每一key value对,以创建单独的记录。 'bid''ask'

    • 列表理解执行创建单独记录的任务。

import json

import pandas


# list of tuples, where the value of data, is a string

transaction_data = [('1599324732926-0', {'data': '{"timestamp":1599324732.767, "receipt_timestamp":1599324732.9256856, "delta":true, "bid":{"338.9":0.06482,"338.67":3.95535}, "ask":{"339.12":2.47578,"339.13":6.43172}}'}),

                    ('1599324732926-1', {'data': '{"timestamp":1599324732.767, "receipt_timestamp":1599324732.9256856, "delta":true, "bid":{"338.9":0.06482,"338.67":3.95535}, "ask":{"339.12":2.47578,"339.13":6.43172}}'}),

                    ('1599324732926-2', {'data': '{"timestamp":1599324732.767, "receipt_timestamp":1599324732.9256856, "delta":true, "bid":{"338.9":0.06482,"338.67":3.95535}, "ask":{"339.12":2.47578,"339.13":6.43172}}'})]


# create a list of lists for each transaction data

# split each side, key value pair into a separate list

data_key_list = [['timestamp', 'receipt_timestamp', 'delta', 'side', 'price', 'size']]


for v in transaction_data:  # # iterate through each transaction

    data = json.loads(v[1]['data'])  # convert the string to a dict

    for side in ['bid', 'ask']:  # extract each key, value pair as a separate record

        data_key_list += [[data['timestamp'], data['receipt_timestamp'], data['delta'], side, float(k), v] for k, v in data[side].items()]


# create a dataframe

df = pd.DataFrame(data_key_list[1:], columns=data_key_list[0])


# display(df.head())

     timestamp  receipt_timestamp  delta side   price     size

0  1.59932e+09        1.59932e+09   True  bid   338.9  0.06482

1  1.59932e+09        1.59932e+09   True  bid  338.67  3.95535

2  1.59932e+09        1.59932e+09   True  ask  339.12  2.47578

3  1.59932e+09        1.59932e+09   True  ask  339.13  6.43172

4  1.59932e+09        1.59932e+09   True  bid   338.9  0.06482

转换为字典列表

df.to_dict(orient='records')


[out]:

[{'timestamp': 1599324732.767,

  'receipt_timestamp': 1599324732.9256856,

  'delta': True,

  'side': 'bid',

  'price': 338.9,

  'size': 0.06482},

 {'timestamp': 1599324732.767,

  'receipt_timestamp': 1599324732.9256856,

  'delta': True,

  'side': 'bid',

  'price': 338.67,

  'size': 3.95535},

 {'timestamp': 1599324732.767,

  'receipt_timestamp': 1599324732.9256856,

  'delta': True,

  'side': 'ask',

  'price': 339.12,

  'size': 2.47578},

 {'timestamp': 1599324732.767,

  'receipt_timestamp': 1599324732.9256856,

  'delta': True,

  'side': 'ask',

  'price': 339.13,

  'size': 6.43172},

 ...]


查看完整回答
反对 回复 2023-07-18
?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

这并不完全是您问题的答案,因为它不是 pandas 或 numpy 的实现,但我认为它应该可以满足您的需求。


尝试看看multiprocessing.pool.Pool.map

假设您有一个函数从原始列表接收元组并返回您想要的数据字典。可以说它的签名看起来像这样:


def tuple_to_dict(input):

    # conversion code goes here

    return result_dict

然后您可以像这样使用 multiprocessing.Pool() :


import multiprocessing



if __name__ == '__main__':


    input_list = [...] # your input list


    with multiprocessing.Pool() as pool:

        result_list = pool.map(tuple_to_dict, input_list)

        print(result_list)

笔记:

  1. Pool() 对象的创建应该放在一个if __name__ == "__main__"块或从那里调用的函数内(递归) - 否则你会得到一个 RuntimeError

  2. 放置with ... as... 在那里,以便在使用结束或失败时关闭 Pool 对象。如果您不使用“with / as”语法,请在 try/catch 块内使用它,并pool.close()在其finally块中添加语句以确保池已关闭。



查看完整回答
反对 回复 2023-07-18
  • 2 回答
  • 0 关注
  • 95 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信