【问题标题】:Convert DataFrame to dictionary with sub-dictionaries将 DataFrame 转换为带有子字典的字典
【发布时间】:2021-01-18 12:29:53
【问题描述】:

这是我的数据框

          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

我需要将其转换为 2 个字典:

sum_buys[filter][date]
sum_sells[filter][date]

所以,例如:

sum_buys[0.5][20200512] = 6.480628
sum_buys[0.7][20200512] = 8.684414

如何在没有迭代的情况下使用 pandas 方法?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    由于您只有少数列,您可以在数据帧上使用 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...
    

    【讨论】:

      猜你喜欢
      • 2019-02-06
      • 2016-10-16
      • 2017-12-26
      • 2014-12-30
      • 2016-05-26
      • 1970-01-01
      • 2022-10-06
      相关资源
      最近更新 更多