Python 如何删除0';s将数据帧转换为记录

Python 如何删除0';s将数据帧转换为记录,python,pandas,Python,Pandas,我正在寻找一种有效的方法,从从pd创建的字典列表中删除零。DataFrame以以下示例为例: df = pd.DataFrame([[1, 2], [0, 4]], columns=['a', 'b'], index=['x', 'y']) df.to_dict('records') [{'a': 1, 'b': 2}, {'a': 0, 'b': 4}] 我想要的是: [{'a': 1, 'b': 2}, {'b': 4}] 我有一个非常大的稀疏数据帧,存储所有的零是低效的。由于数据帧很

我正在寻找一种有效的方法,从从
pd创建的字典列表中删除零。DataFrame
以以下示例为例:

df = pd.DataFrame([[1, 2], [0, 4]], columns=['a', 'b'], index=['x', 'y'])
df.to_dict('records')

[{'a': 1, 'b': 2}, {'a': 0, 'b': 4}]
我想要的是:

[{'a': 1, 'b': 2}, {'b': 4}]
我有一个非常大的稀疏数据帧,存储所有的零是低效的。由于数据帧很大,我正在寻找一种比在字典的数据帧中循环并删除零更快的解决方案,例如,下面的方法虽然有效,但速度非常慢,并且占用大量内存

new_records = []
for record in df.to_dict('records'):
    new_records.append(dict((k, v) for k, v in record.items() if v))

有没有更有效的方法或途径

使用列表理解

[r[r != 0].to_dict() for _, r in df.iterrows()]

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

这似乎是一个x-y问题:只需使用稀疏矩阵表示。唯一的困难是您必须自己跟踪专栏:

In [8]: from scipy import sparse

In [9]: df
Out[9]:
   a  b
x  1  2
y  0  4

In [10]: column_names = df.columns

In [11]: sm = sparse.csc_matrix(df.values)
或者,更简单,正如piRSquared所指出的,
pandas
内置此功能:

df.to_sparse(0)

如果出于某种原因,您决定跳过稀疏的想法(好主意),并且您确实想要一个字典列表,比如从
pd.Dataframe
生成的字典,但缺少零,那么您可以尝试使用
numpy.flatnonzero()
和numpy索引来解决这个问题。我做了一些快速测试,它看起来比您建议的版本快,但不知道差异是否显著

import numpy as np

new_records = []
columns=np.array(df.columns.values)
for record in df.as_matrix():
    idx=np.flatnonzero(record)
    new_records.append( dict( zip( columns[idx], record[idx] ) ) )
输出是您要求的输出:

[{'a': 1, 'b': 2}, {'b': 4}]
细节:
  • 首先检索要用作每个新字典键的列值,并使它们成为numpy数组,以使用numpy数组索引
    np.array(df.columns.values)
  • 接下来,将数据帧转换为numpy矩阵
    df.as\u matrix()
  • 对于每条记录,获取不带零的位置的索引
    np.flatnonzero()
  • 使用列和记录的切片版本制作字典。这里是使用索引的地方
    dict(zip(列[idx],记录[idx]))
  • 将每个新词典附加到新记录中

这不会比for-loop快。实际上,这不会比for-loop快,至少不会明显快。@juanpa.arrivillaga
True
。。。你是否考虑过使用稀疏矩阵?我对稀疏表示不太熟悉,但我相信你是正确的,这将是一种更好的方法。我同意你的看法。然而,熊猫有它自己的稀疏
df。为了_sparse(0)
@piRSquared-Welp,甚至更好!我试过这个,它似乎没有为我删除0值。我做错什么了吗?df.to_sparse(0).to_dict('records')@Kelvin如果您使用
to_dict
它当然会返回零。你需要直接使用稀疏表示,我在这里遇到的问题是,将数据帧转换为稀疏表示非常非常缓慢。比使用for循环或类似方法将数据帧转换为不带零的字典慢得多。这是预期的吗?
[{'a': 1, 'b': 2}, {'b': 4}]