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

我想对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 循环中,与管理整个列表的解决方案相比,这会慢得多。


莫回无
浏览 98回答 2
2回答

幕布斯6054654

迭代提取信息比使用pandas.json_normalize.如示例数据所示, 的值data是一种str类型,必须转换为dict.主要任务是从和中提取每一key value对,以创建单独的记录。 'bid''ask'列表理解执行创建单独记录的任务。import jsonimport pandas# list of tuples, where the value of data, is a stringtransaction_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 listdata_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 dataframedf = pd.DataFrame(data_key_list[1:], columns=data_key_list[0])# display(df.head())     timestamp  receipt_timestamp  delta side   price     size0  1.59932e+09        1.59932e+09   True  bid   338.9  0.064821  1.59932e+09        1.59932e+09   True  bid  338.67  3.955352  1.59932e+09        1.59932e+09   True  ask  339.12  2.475783  1.59932e+09        1.59932e+09   True  ask  339.13  6.431724  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}, ...]

一只斗牛犬

这并不完全是您问题的答案,因为它不是 pandas 或 numpy 的实现,但我认为它应该可以满足您的需求。尝试看看multiprocessing.pool.Pool.map假设您有一个函数从原始列表接收元组并返回您想要的数据字典。可以说它的签名看起来像这样:def tuple_to_dict(input):    # conversion code goes here    return result_dict然后您可以像这样使用 multiprocessing.Pool() :import multiprocessingif __name__ == '__main__':    input_list = [...] # your input list    with multiprocessing.Pool() as pool:        result_list = pool.map(tuple_to_dict, input_list)        print(result_list)笔记:Pool() 对象的创建应该放在一个if __name__ == "__main__"块或从那里调用的函数内(递归) - 否则你会得到一个 RuntimeError放置with ... as... 在那里,以便在使用结束或失败时关闭 Pool 对象。如果您不使用“with / as”语法,请在 try/catch 块内使用它,并pool.close()在其finally块中添加语句以确保池已关闭。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python