【问题标题】:Remove blank key entries in Pandas pd.to_dict删除 Pandas pd.to_dict 中的空白键条目
【发布时间】:2020-10-01 11:35:56
【问题描述】:

Pandas 有一个非常好的功能,可以通过pd.to_dict('records') 将我们的数据帧导出到字典列表。

例如:

d = pd.DataFrame({'a':[1,2,3], 'b':['a', 'b', None]}) 
d.to_dict('records')

返回

[{'a': 1, 'b': 'a'}, {'a': 2, 'b': 'b'}, {'a': 3, 'b': None}]

对于我的用例,我更喜欢以下条目:

[{'a': 1, 'b': 'a'}, {'a': 2, 'b': 'b'}, {'a': 3}]

您可以看到b 的键已从第三个条目中删除。这是 R 中使用 jsonlite 时的默认行为,我想知道如何从每个条目中删除缺少值的键。

【问题讨论】:

    标签: pandas dictionary


    【解决方案1】:

    这是applyseries.dropna() 的另一种方法(如果性能不是问题)

    d.apply(lambda x: x.dropna().to_dict(),axis=1).tolist()
    

    [{'a': 1, 'b': 'a'}, {'a': 2, 'b': 'b'}, {'a': 3}]
    

    【讨论】:

      【解决方案2】:

      将所有内容转储到字典中,它应该更快,更容易使用列表理解:

      [{key:value
       for key,value in entry.items() 
      if value is not None}
       for entry in d.to_dict('records')]
      
      
      [{'a': 1, 'b': 'a'}, {'a': 2, 'b': 'b'}, {'a': 3}]
      

      【讨论】:

        【解决方案3】:

        更新:使用列表推导和 itertuples 和嵌套字典推导。这是最快的

        l = [{k: v for k, v in tup._asdict().items() if v is not None} 
                                               for tup in d.itertuples(index=False)]
        
        Out[74]: [{'a': 1, 'b': 'a'}, {'a': 2, 'b': 'b'}, {'a': 3}]
        

        时间:

        d1 = pd.concat([d]*5000, ignore_index=True)
        
        In [76]: %timeit [{k: v for k, v in tup._asdict().items() if v is not None} for
            ...:  tup in d1.itertuples(index=False)]
        442 ms ± 28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
        

        另一种方法是使用列表理解和iterrows

        l = [row.dropna().to_dict() for k, row in d.iterrows()]
        
        Out[33]: [{'a': 1, 'b': 'a'}, {'a': 2, 'b': 'b'}, {'a': 3}]
        

        iterrows 以性能缓慢着称。我对 15000 行样本进行了测试,以与 stack 进行比较

        In [49]: d1 = pd.concat([d]*5000, ignore_index=True)
        
        In [50]: %timeit d1.stack().groupby(level=0).agg(lambda x : x.reset_index(level
            ...: =0,drop=True).to_dict()).tolist()
        7.52 s ± 370 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
        
        In [51]: %timeit [row.dropna().to_dict() for k, row in d1.iterrows()]
        6.45 s ± 60.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
        

        有趣的结果。但是,我认为如果数据更大,它会比stack

        【讨论】:

        • 哇,这里的东西太棒了。
        【解决方案4】:

        我们可以stack

        l=d.stack().groupby(level=0).agg(lambda x : x.reset_index(level=0,drop=True).to_dict()).tolist()
        Out[142]: [{'a': 1, 'b': 'a'}, {'a': 2, 'b': 'b'}, {'a': 3}]
        

        【讨论】:

        • 有意思,我不经常想用stack
        猜你喜欢
        • 2016-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-06
        • 2013-08-09
        • 2014-09-24
        • 1970-01-01
        • 2017-09-06
        相关资源
        最近更新 更多