删除熊猫pd.to_dict

时间:2020-06-11 18:18:21

标签: pandas dictionary

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的键已从第三项中删除。这是使用jsonlite时R中的默认行为,我想知道如何从每个条目中删除缺少值的键。

4 个答案:

答案 0 :(得分:3)

我们可以做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}]

答案 1 :(得分:2)

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

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

答案 2 :(得分: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 :(得分:1)

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

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

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