我有一个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 - 对于每一行,查找包含非NaN的第n个元素的列的最快方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31954393/

10-16 17:12
查看更多