为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

喵喵时光机 2021-03-31 04:11:04
我有一个这样的数据框: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  col40  2018-01-01 02:00:00   NaN   NaN   NaN  -2.01  2018-01-01 04:00:00   NaN   NaN  -1.0  -1.02  2018-01-01 06:00:00   NaN   0.0   NaN   0.03  2018-01-01 08:00:00   1.0   1.0   1.0   1.04  2018-01-01 10:00:00   2.0   NaN   2.0   2.05  2018-01-01 12:00:00   3.0   3.0   NaN   3.06  2018-01-01 14:00:00   NaN   4.0   4.0   4.07  2018-01-01 16:00:00   5.0   NaN   5.0   NaN8  2018-01-01 18:00:00   6.0   NaN   6.0   NaN9  2018-01-01 20:00:00   7.0   NaN   7.0   NaN10 2018-01-01 22:00:00   8.0   NaN   8.0   NaN11 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, :])
查看完整描述

3 回答

?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

您可以使用函数式编程的功能,并将函数应用于每一列。这可能会加快速度。同样,当您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])

    return


df.apply(func)

另外,您可以将所有东西压紧在一个衬里中:


final = []

df.apply(lambda col: final.append(col.loc[col.first_valid_index() : col.last_valid_index()]))



查看完整回答
反对 回复 2021-04-13
?
慕村225694

TA贡献1880条经验 获得超4个赞

一种想法是在将索引设置为之后使用列表或字典理解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': timestamp

2018-01-01 08:00:00    1.0

2018-01-01 10:00:00    2.0

2018-01-01 12:00:00    3.0

2018-01-01 14:00:00    4.0

2018-01-01 16:00:00    5.0

2018-01-01 18:00:00    6.0

2018-01-01 20:00:00    7.0

2018-01-01 22:00:00    8.0

Name: col1, dtype: float64,

...

'col4': timestamp

2018-01-01 02:00:00   -2.0

2018-01-01 04:00:00   -1.0

2018-01-01 06:00:00    0.0

2018-01-01 08:00:00    1.0

2018-01-01 10:00:00    2.0

2018-01-01 12:00:00    3.0

2018-01-01 14:00:00    4.0

Name: col4, dtype: float64}


查看完整回答
反对 回复 2021-04-13
?
精慕HU

TA贡献1845条经验 获得超8个赞

我的方法是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}


查看完整回答
反对 回复 2021-04-13
  • 3 回答
  • 0 关注
  • 166 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号