2

我有一个 pandas DataFrame,以这种方式创建:

import pandas as pd
wb = pd.io.parsers.ExcelFile('/path/to/data.xlsx')
df = wb.parse(wb.sheet_names[0])

生成的数据帧有大约十几个列,所有列的长度完全相同(大约 150K)。

对于大多数列,以下操作几乎是瞬时的

aset = set(df.acolumn)

但是对于某些列,相同的操作,例如

aset = set(df.weirdcolumn)

需要> 10分钟!(或者更确切地说,操作在 10 分钟超时期限到期之前无法完成。)相同数量的元素!

还是很陌生:

In [106]: set([type(c) for c in df.weirdcolumn])
Out[106]: set([numpy.float64])

In [107]: df.weirdcolumn.value_counts()
Out[107]: []

看来该列的内容都是nans

In [118]: all(np.isnan(df.weirdcolumn.values))
Out[118]: True

但这并不能解释前面提到的减速,因为下面的操作只需要几秒钟:

In [121]: set([np.nan for _ in range(len(data))])
Out[121]: set([nan])

我已经没有办法找出上述大幅放缓的原因。欢迎提出建议。

4

1 回答 1

4

关于 nans 的一件奇怪的事情是它们的比较不相等。这意味着将为集合单独插入“不同”的 nan 对象:

>>> float('nan') == float('nan')
False
>>> float('nan') is float('nan')
False
>>> len(set([float('nan') for _ in range(1000)]))
1000

这不会发生在您的测试中np.nan,因为它一遍又一遍地是同一个对象:

>>> np.nan == np.nan
False
>>> np.nan is np.nan
True
>>> len(set([np.nan for _ in range(1000)]))
1

这可能是你的问题;您正在制作一个包含 150,000 个元素的集合,其中每个元素都具有完全相同的哈希 ( hash(float('nan')) == 0)。这意味着将新的 nan 插入到已经有 nan 的集合中n至少需要O(n)时间,因此构建一组nanN至少需要O(N^2)时间。150k^​​2 是……大。

所以,是的,nans很糟糕。你可以通过做类似的事情来解决这个问题

nan_idx = np.isnan(df.weirdcolumn)
s = set(df.weirdcolumn[~nan_idx])
if np.any(nan_idx):
    s.add(np.nan)
于 2013-02-13T04:10:13.037 回答