A. *_*rpi 6 python performance nan dataframe pandas
我有一个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
Run Code Online (Sandbox Code Playgroud)
我想得到:
'A' 60
'B' 70
'C' 100
'D' 40
Run Code Online (Sandbox Code Playgroud)
我可以:
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
Run Code Online (Sandbox Code Playgroud)
我确信这很慢,而且不是非常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
Run Code Online (Sandbox Code Playgroud)
其他答案都很好,也许在语法上更清晰一些.就速度而言,对于你的小例子,它们之间没有太大区别.但是,对于稍微大一点的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
Run Code Online (Sandbox Code Playgroud)