熊猫 - 找到没有Nan值的最长伸展

时间:2017-01-05 20:48:23

标签: python pandas numpy

我有一个pandas数据帧“df”,其示例如下:

   time  x
0  1     1
1  2     Nan 
2  3     3
3  4     Nan
4  5     8
5  6     7
6  7     5
7  8     Nan

真实的框架要大得多。我试图在“x”系列中找到最长的非NaN值,并打印出该帧的起始和结束索引。这可能吗?

谢谢

5 个答案:

答案 0 :(得分:6)

这是使用NumPy工具的矢量化方法 -

a = df.x.values  # Extract out relevant column from dataframe as array
m = np.concatenate(( [True], np.isnan(a), [True] ))  # Mask
ss = np.flatnonzero(m[1:] != m[:-1]).reshape(-1,2)   # Start-stop limits
start,stop = ss[(ss[:,1] - ss[:,0]).argmax()]  # Get max interval, interval limits

示例运行 -

In [474]: a
Out[474]: 
array([  1.,  nan,   3.,  nan,  nan,  nan,  nan,   8.,   7.,   5.,   2.,
         5.,  nan,  nan])

In [475]: start, stop
Out[475]: (7, 12)

设置间隔使得每个开始和停止之间的差异将给出每个间隔的长度。因此,如果您想要获取非零元素的最后一个索引,请ending index,我们需要从stop中减去一个。

答案 1 :(得分:4)

因此,您可以通过以下方式获取NaN的索引值:

import numpy as np

index = df['x'].index[df['x'].apply(np.isnan)]
df_index = df.index.values.tolist()
[df_index.index(indexValue) for indexValue in index]

>>> [0, 1, 3, 7]

然后一个解决方案是查看后续索引值之间的最大差异,这将为您提供最长的非NaN值。

答案 2 :(得分:3)

pandas

f = dict(
    Start=pd.Series.first_valid_index,
    Stop=pd.Series.last_valid_index,
    Stretch='count'
)

agged = df.x.groupby(df.x.isnull().cumsum()).agg(f)
agged.loc[agged.Stretch.idxmax(), ['Start', 'Stop']].values

array([ 4.,  6.])

numpy

def pir(x):
    # pad with np.nan
    x = np.append(np.nan, np.append(x, np.nan))
    # find where null
    w = np.where(np.isnan(x))[0]
    # diff to find length of stretch
    # argmax to find where largest stretch
    a = np.diff(w).argmax()
    # return original positions of boundary nulls
    return w[[a, a + 1]] + np.array([0, -2])

<强> 演示

pir(df.x.values)

array([4, 6])
a = np.array([1, np.nan, 3, np.nan, np.nan, np.nan, np.nan, 8, 7, 5, 2, 5, np.nan, np.nan])
pir(a)

array([ 7, 11])

答案 3 :(得分:2)

也许更快的方式是以下(假设你说你有一个很长的数据帧,速度很重要):

In [19]: df = pd.DataFrame({'time':[1,2,3,4,5,6,7,8],'x':[1,np.NAN,3,np.NAN,8,7,5,np.NAN]})

In [20]: index = df['x'].isnull()

In [21]: df[index].index.values
Out[21]: array([1, 3, 7])

答案 4 :(得分:1)

另一种方法是使用scipy.ndimage.measurements.label。它将执行非空索引到有效组的分段,并以不同方式标记它们。然后,您可以使用标签对数据框进行分组,并选择最大的组。

设置向上

import pandas as pd
import numpy as np
from scipy.ndimage.measurements import label
df = pd.DataFrame({'time':[1,2,3,4,5,6,7,8],'x':[1,np.NAN,3,np.NAN,8,7,5,np.NAN]})

检索没有纳米的最长拉伸

valid_rows = ~df.isnull().any(axis=1)
label, num_feature = label(valid_rows)
label_of_biggest_group =  valid_rows.groupby(label).count().drop(0).argmax()
print df.loc[label == label_of_biggest_group]

<强>结果

   time    x
4     5  8.0
5     6  7.0
6     7  5.0

注意

标签0在我们的例子中包含nan值的背景数据,如果你的数量大于或等于最大组的大小,则必须删除它。 num_feature是没有nan的同质延伸数。