我正在使用pandas groupby并申请从包含以下列的1.5亿行的DataFrame中获取数据:
Id Created Item Stock Price
1 2019-01-01 Item 1 200 10
1 2019-01-01 Item 2 100 15
2 2019-01-01 Item 1 200 10
列出如下所示的220万条记录:
[{
"Id": 1,
"Created": "2019-01-01",
"Items": [
{"Item":"Item 1", "Stock": 200, "Price": 10},
{"Item":"Item 2", "Stock": 100, "Price": 5}
]
},
{
"Id": 2,
"Created": "2019-01-01",
"Items": [
{"Item":"Item 1", "Stock": 200, "Price": 10}
]
}]
主要使用以下代码行:
df.groupby(['Id', 'Created']).apply(lambda x: x[['Item', 'Stock', 'Price']].to_dict(orient='records'))
这需要花费很多时间,据我了解,像这样的操作对于熊猫来说很繁重。有没有熊猫可以做到相同但性能更高的方法?
编辑:该操作需要55分钟,我正在AWS中使用ScriptProcessor,可以让我指定所需的电量。
编辑2:
因此,使用artonas解决方案,我越来越接近:
这是我现在设法生产的:
defaultdict(<function __main__.<lambda>()>,
{'1': defaultdict(list,
{'Id': '1',
'Created':'2019-01-01',
'Items': [{'Item': Item2, 'Stock': 100, 'Price': 15},
{'Item': Item1, 'Stock': 200, 'Price': 10}]
})
},
{'2': defaultdict(list,
{'Id': '2',
'Created':'2019-01-01',
'Items': [{'Item': Item1, 'Stock': 200, 'Price': 10}]
})
},
但是如何从上面转到这一点呢?
[{
"Id": 1,
"Created": "2019-01-01",
"Items": [
{"Item":"Item 1", "Stock": 200, "Price": 10},
{"Item":"Item 2", "Stock": 100, "Price": 5}
]
},
{
"Id": 2,
"Created": "2019-01-01",
"Items": [
{"Item":"Item 1", "Stock": 200, "Price": 10}
]
}]
基本上,对于所有记录,Im只对“ defaultdict(list,”)后面的部分感兴趣。我需要将其放在不依赖于ID作为键的列表中。
编辑3:包含我的生产数据集结果的最新更新。
有了artona提供的公认答案,我设法从55分钟缩短到7(!)分钟。而且我的代码没有任何重大变化。 Phung Duy Phong提供的解决方案使我从55分钟缩短到17分钟,也不错。
最佳答案
使用collections.defaultdict和itertuples。它仅在行上迭代一次。
In [105]: %timeit df.groupby(['Id', 'Created']).apply(lambda x: x[['Item', 'Stock', 'Price']].to_dict(orient='records'))
10.1 s ± 44.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [107]:from collections import defaultdict
...:def create_dict():
...: dict_ids = defaultdict(lambda : defaultdict(list))
...: for row in df.itertuples():
...: dict_ids[row.Id][row.Created].append({"Item": row.Item, "Stock": row.Stock, "Price": row.Price})
...: list_of_dicts = [{"Id":key_id, "Created":key_created, "Items": values} for key_id, value_id in dict_ids.items() for key_created, values in value_id.items()]
...: return list_of_dicts
In [108]: %timeit create_dict()
4.58 s ± 417 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)