由于您只有少数列,您可以在数据帧上使用 to_dict() 方法,然后使用字典推导来获得所需的数据结构。
创建嵌套字典不是您可以矢量化的东西,但是通过将迭代步骤移动到较小的字典而不是使用 iterrows() (如 answer 中所示),您应该会看到一些性能提升。
import pandas as pd
from io import StringIO
data = StringIO("""
name filter date value
0 sum_buys 0.5 20200512 6.480628
1 sum_sells 0.5 20200512 5.019421
2 sum_buys 0.6 20200512 7.463128
3 sum_sells 0.6 20200512 5.836488
4 sum_buys 0.7 20200512 8.684414
""")
df = pd.read_csv(data, delim_whitespace=True)
sum_buys_data = (
df[df["name"] == "sum_buys"]
.set_index("filter")[["date", "value"]]
.to_dict(orient="index")
)
sum_buys = {k : {v["date"] : v["value"]} for k, v in sum_buys_data.items()}
sum_buys
{0.5: {20200512: 6.480628},
0.6: {20200512: 7.463128},
0.7: {20200512: 8.684414}}
现在,如果您有很多列或想要更通用的方法怎么办?您仍然需要迭代,但我们可以调整 defaultdict 类,以便工厂知道丢失的键并以同样的方式创建嵌套字典。就时间而言,在我的机器上大约 170 毫秒内将大约 20k 行转换为嵌套字典,大约 780 毫秒内将大约 200k 行转换为嵌套字典。
# extra imports
import numpy as np
from collections import defaultdict
np.random.seed(0)
size = 100000 # let's create a slightly bigger data frame
df = pd.DataFrame(data={
"name" : np.random.choice(["sum_buys", "sum_sells"], size=size),
"filter" : np.random.choice(range(10), size=size),
"date" : np.random.choice(range(1000), size=size),
"value" : np.random.random(size)
}).drop_duplicates(subset=["name", "filter", "date"])
df.shape # (19861, 4)
# define a custom dictionary
class NestedDict(defaultdict):
def __init__(self, f):
super().__init__(None)
self.f = f
def __missing__(self, key):
ret = NestedDict(self.f)
self[key] = ret
return ret
nested_dict = NestedDict(NestedDict)
for index, value in df.set_index(["name", "filter", "date"]).itertuples():
n, f, d = index # unpack index into keys
nested_dict[n][f][d] = value
nested_dict["sum_buys"][0][0] # 0.396...