python - 对于每一行,找到第 n 个非 NaN 元素的列的最快方法是什么?

标签 python performance pandas dataframe nan

我有一个 Python pandas DataFrame,其中每个元素都是 float 或 NaN。 对于每一行,我需要找到包含该行第 n 个数字的列。也就是说,我需要获取包含非 NaN 的行的第 n 个元素的列。我知道第 n 个这样的列总是存在的。

因此,如果 n 为 4 并且名为 myDF 的 pandas 数据框如下:

      10   20   30   40   50   60  70  80  90  100

'A'  4.5  5.5  2.5  NaN  NaN  2.9 NaN NaN 1.1 1.8
'B'  4.7  4.1  NaN  NaN  NaN  2.0 1.2 NaN NaN NaN
'C'  NaN  NaN  NaN  NaN  NaN  1.9 9.2 NaN 4.4 2.1
'D'  1.1  2.2  3.5  3.4  4.5  NaN NaN NaN 1.9 5.5

我想获得:

'A'  60
'B'  70
'C'  100 
'D'  40

我能做到:

import pandas as pd
import math

n = some arbitrary int
for row in myDF.indexes:
   num_not_NaN = 0   
   for c in myDF.columns:    
      if math.isnan(myDF[c][row]) == False: 
           num_not_NaN +=1
      if num_not_NaN==n:
           print row, c
           break

我敢肯定这很慢而且不是很 Pythonic。如果我要处理非常大的 DataFrame 和很大的 n 值,有没有一种方法会更快?

最佳答案

如果速度是您的目标,那么尽可能使用 Pandas 的矢量化方法是个好主意:

>>> (df.notnull().cumsum(axis=1) == 4).idxmax(axis=1) # replace 4 with any number you like
'A'     60
'B'     70
'C'    100
'D'     40
dtype: object

其他答案都不错,而且在语法上可能更清晰一些。就速度而言,对于您的小例子,它们之间没有太大区别。然而,对于稍大的 DataFrame,矢量化方法已经快了大约 60 倍:

>>> df2 = pd.concat([df]*1000) # 4000 row DataFrame
>>> %timeit df2.apply(lambda row: get_nth(row, n), axis=1)
1 loops, best of 3: 749 ms per loop

>>> %timeit df2.T.apply(lambda x: x.dropna()[n-1:].index[0])
1 loops, best of 3: 673 ms per loop

>>> %timeit (df2.notnull().cumsum(1) == 4).idxmax(axis=1)
100 loops, best of 3: 10.5 ms per loop

关于python - 对于每一行,找到第 n 个非 NaN 元素的列的最快方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31954393/

相关文章:

javascript - react 路由和django url冲突

python - 有没有 "best"方法在 Python 中做某​​事

python - 更改 Pandas 中多个日期时间列的时区信息

python - 我如何实现一个马尔可夫链,当它消耗太多内存时清除旧数据?

python - 在 Nose 中运行与单元测试子类无关的单个测试函数

android - Android SQLite 上的 TEXT vs BLOB 坐标值

r - 在 R 中对大型、非常稀疏的二元矩阵进行聚类

c# - 如何发现处理和内存问题? C#

python - 使用 Pandas 迭代 CSV 行,执行 Selenium 操作

python - 从 MultiIndex 数据框中获取具有命名标签的列