猿问

对于数据帧的每一列,大熊猫会掉落在第一个有效索引之前和最后一个有效索引之后

我有一个这样的数据框:


df = pd.DataFrame({'timestamp':pd.date_range('2018-01-01', '2018-01-02', freq='2h', closed='right'),'col1':[np.nan, np.nan, np.nan, 1,2,3,4,5,6,7,8,np.nan], 'col2':[np.nan, np.nan, 0, 1,2,3,4,5,np.nan,np.nan,np.nan,np.nan], 'col3':[np.nan, -1, 0, 1,2,3,4,5,6,7,8,9], 'col4':[-2, -1, 0, 1,2,3,4,np.nan,np.nan,np.nan,np.nan,np.nan]

              })[['timestamp', 'col1', 'col2', 'col3', 'col4']]

看起来像这样:


             timestamp  col1  col2  col3  col4

0  2018-01-01 02:00:00   NaN   NaN   NaN  -2.0

1  2018-01-01 04:00:00   NaN   NaN  -1.0  -1.0

2  2018-01-01 06:00:00   NaN   0.0   NaN   0.0

3  2018-01-01 08:00:00   1.0   1.0   1.0   1.0

4  2018-01-01 10:00:00   2.0   NaN   2.0   2.0

5  2018-01-01 12:00:00   3.0   3.0   NaN   3.0

6  2018-01-01 14:00:00   NaN   4.0   4.0   4.0

7  2018-01-01 16:00:00   5.0   NaN   5.0   NaN

8  2018-01-01 18:00:00   6.0   NaN   6.0   NaN

9  2018-01-01 20:00:00   7.0   NaN   7.0   NaN

10 2018-01-01 22:00:00   8.0   NaN   8.0   NaN

11 2018-01-02 00:00:00   NaN   NaN   9.0   NaN

现在,我想找到一种有效且有效的方法来删除第一个有效索引之前和之后的有效索引(对于每一列!不计算时间戳)。在此示例中,我有4列,但实际上,我有更多列,大约600列。我正在寻找一种方法来斩波第一个有效索引之前的所有NaN值,以及最后一个有效索引之后的所有NaN值。


我猜一种方法是循环遍历。但是还有更好的方法吗?这种方式必须有效。我试图使用melt“取消透视图”数据框,但这无济于事。


明显的一点是,斩波后每一列的行数会有所不同。因此,我希望结果是一个带有时间戳和相关列的数据帧列表(每列一个)。例如:


             timestamp  col1   

3  2018-01-01 08:00:00   1.0  

4  2018-01-01 10:00:00   2.0   

5  2018-01-01 12:00:00   3.0   

6  2018-01-01 14:00:00   NaN   

7  2018-01-01 16:00:00   5.0   

8  2018-01-01 18:00:00   6.0   

9  2018-01-01 20:00:00   7.0   

10 2018-01-01 22:00:00   8.0    

我的尝试


我这样尝试过:


final = []

columns = [c for c in df if c !='timestamp']

for col in columns:

    first = df.loc[:, col].first_valid_index()

    last = df.loc[:, col].last_valid_index()

    final.append(df.loc[:, ['timestamp', col]].iloc[first:last+1, :])


喵喵时光机
浏览 167回答 3
3回答

慕田峪7331174

您可以使用函数式编程的功能,并将函数应用于每一列。这可能会加快速度。同样,当您timestamps看起来已排序时,可以将它们用作Datarame的索引。df.set_index('timestamp', inplace=True)final = []def func(col):    first = col.first_valid_index()    last = col.last_valid_index()    final.append(col.loc[first:last])    returndf.apply(func)另外,您可以将所有东西压紧在一个衬里中:final = []df.apply(lambda col: final.append(col.loc[col.first_valid_index() : col.last_valid_index()]))

慕村225694

一种想法是在将索引设置为之后使用列表或字典理解timestamp。您应该对数据进行测试,以查看这是否可以解决性能问题。如果您的限制是内存,则不太可能有帮助。df = df.set_index('timestamp')final = {col: df[col].loc[df[col].first_valid_index(): df[col].last_valid_index()] \         for col in df}print(final){'col1': timestamp2018-01-01 08:00:00    1.02018-01-01 10:00:00    2.02018-01-01 12:00:00    3.02018-01-01 14:00:00    4.02018-01-01 16:00:00    5.02018-01-01 18:00:00    6.02018-01-01 20:00:00    7.02018-01-01 22:00:00    8.0Name: col1, dtype: float64,...'col4': timestamp2018-01-01 02:00:00   -2.02018-01-01 04:00:00   -1.02018-01-01 06:00:00    0.02018-01-01 08:00:00    1.02018-01-01 10:00:00    2.02018-01-01 12:00:00    3.02018-01-01 14:00:00    4.0Name: col4, dtype: float64}

精慕HU

我的方法是NaN为每列及其倒数找到的累加总和,并过滤那些大于的条目0。然后,我进行dict理解以为每一列返回一个数据框(如果您愿意,可以将其更改为列表)。例如,我们有cols = [c for c in df.columns if c!='timestamp']result_dict = {c: df[(df[c].notnull().cumsum() > 0) &                     (df.ix[::-1,c].notnull().cumsum()[::-1] > 0)][['timestamp', c]]               for c in cols}
随时随地看视频慕课网APP

相关分类

Python
我要回答