我有一个形状的数据框(40,500)。数据帧中的每一行都有一些数值,直到某个变量列号为k,之后的所有条目都是nan。
我试图获取每行中最后一个非纳米列的值。有没有办法在不循环数据帧的所有行的情况下执行此操作?
示例数据帧:
2016-06-02 7.080 7.079 7.079 7.079 7.079 7.079 nan nan nan
2016-06-08 7.053 7.053 7.053 7.053 7.053 7.054 nan nan nan
2016-06-09 7.061 7.061 7.060 7.060 7.060 7.060 nan nan nan
2016-06-14 nan nan nan nan nan nan nan nan nan
2016-06-15 7.066 7.066 7.066 7.066 nan nan nan nan nan
2016-06-16 7.067 7.067 7.067 7.067 7.067 7.067 7.068 7.068 nan
2016-06-21 7.053 7.053 7.052 nan nan nan nan nan nan
2016-06-22 7.049 7.049 nan nan nan nan nan nan nan
2016-06-28 7.058 7.058 7.059 7.059 7.059 7.059 7.059 7.059 7.059
请求输出
2016-06-02 7.079
2016-06-08 7.054
2016-06-09 7.060
2016-06-14 nan
2016-06-15 7.066
2016-06-16 7.068
2016-06-21 7.052
2016-06-22 7.049
2016-06-28 7.059
答案 0 :(得分:9)
您需要last_valid_index
自定义功能,因为如果所有值均为NaN
,则返回KeyError
:
def f(x):
if x.last_valid_index() is None:
return np.nan
else:
return x[x.last_valid_index()]
df['status'] = df.apply(f, axis=1)
print (df)
1 2 3 4 5 6 7 8 9 \
0
2016-06-02 7.080 7.079 7.079 7.079 7.079 7.079 NaN NaN NaN
2016-06-08 7.053 7.053 7.053 7.053 7.053 7.054 NaN NaN NaN
2016-06-09 7.061 7.061 7.060 7.060 7.060 7.060 NaN NaN NaN
2016-06-14 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2016-06-15 7.066 7.066 7.066 7.066 NaN NaN NaN NaN NaN
2016-06-16 7.067 7.067 7.067 7.067 7.067 7.067 7.068 7.068 NaN
2016-06-21 7.053 7.053 7.052 NaN NaN NaN NaN NaN NaN
2016-06-22 7.049 7.049 NaN NaN NaN NaN NaN NaN NaN
2016-06-28 7.058 7.058 7.059 7.059 7.059 7.059 7.059 7.059 7.059
status
0
2016-06-02 7.079
2016-06-08 7.054
2016-06-09 7.060
2016-06-14 NaN
2016-06-15 7.066
2016-06-16 7.068
2016-06-21 7.052
2016-06-22 7.049
2016-06-28 7.059
替代解决方案 - 使用方法ffill
fillna
并按iloc
选择最后一列:
df['status'] = df.ffill(axis=1).iloc[:, -1]
print (df)
status
0
2016-06-02 7.079
2016-06-08 7.054
2016-06-09 7.060
2016-06-14 NaN
2016-06-15 7.066
2016-06-16 7.068
2016-06-21 7.052
2016-06-22 7.049
2016-06-28 7.059
答案 1 :(得分:5)
使用agg('last')
df.groupby(['status'] * df.shape[1], 1).agg('last')
agg中的'last'产生组中的最后一个有效值。我传递了一个长度等于列数的列表。此列表的每个值都是“status”。这意味着我正在分组。结果是一个数据框,其中一列名为“status”
答案 2 :(得分:3)
这是一个基于NumPy的解决方案 -
In [113]: a
Out[113]:
array([[ 17., 53., nan, 63., 66., nan, nan, nan, nan, nan],
[ 54., 96., 71., 20., 70., 58., 91., nan, nan, nan],
[ 58., 26., 72., 93., 58., 29., 44., 28., 36., 88.],
[ nan, nan, nan, nan, nan, nan, nan, nan, nan, nan],
[ 94., 23., nan, nan, 92., 81., 40., 30., 84., nan]])
In [114]: m = ~np.isnan(a)
In [115]: a[np.arange(m.shape[0]), m.shape[1]-m[:,::-1].argmax(1)-1]
Out[115]: array([ 66., 91., 88., nan, 84.])
要为数据帧移植它,首先我们可以将值提取为数组:a = df.values
并最终生成输出数据帧:
vals = a[np.arange(m.shape[0]), m.shape[1]-m[:,::-1].argmax(1)-1]
df_out = pd.DataFrame(vals,index=df.index)