我正在处理钻孔的地下测量,其中每种测量类型都覆盖不同的深度范围。在这种情况下,深度被用作索引。
我需要找到每种测量类型第一次和/或最后一次出现的数据(非NaN值)的深度(索引)。
获取数据帧的第一行或最后一行的深度(索引)很容易:df.index[0]
或df.index[-1]
。诀窍在于找到任何给定列的第一个或最后一个非NaN出现的索引。
df = pd.DataFrame([[500, np.NaN, np.NaN, 25],
[501, np.NaN, np.NaN, 27],
[502, np.NaN, 33, 24],
[503, 4, 32, 18],
[504, 12, 45, 5],
[505, 8, 38, np.NaN]])
df.columns = ['Depth','x1','x2','x3']
df.set_index('Depth')
理想的解决方案对于x1的第一次出现将产生503的索引(深度),对于x2的第一次出现将产生502(索引),对于x3的最后出现将产生504(索引)。
答案 0 :(得分:4)
df.notna().agg({'x1':'idxmax','x2':'idxmax','x3':lambda x: x[::-1].idxmax()})
#df.notna().agg({'x1':'idxmax','x2':'idxmax','x3':lambda x: x[x].last_valid_index()})
x1 503
x2 502
x3 504
另一种方法是检查第一行是否为nan,并根据该条件应用条件:
np.where(df.iloc[0].isna(),df.notna().idxmax(),df.notna()[::-1].idxmax())
[503, 502, 504]
答案 1 :(得分:4)
first_valid_index()和last_valid_index()可以使用。
>>> df
x1 x2 x3
Depth
500 NaN NaN 25.0
501 NaN NaN 27.0
502 NaN 33.0 24.0
503 4.0 32.0 18.0
504 12.0 45.0 5.0
505 8.0 38.0 NaN
>>> df["x1"].first_valid_index()
503
>>> df["x2"].first_valid_index()
502
>>> df["x3"].first_valid_index()
500
>>> df["x3"].last_valid_index()
504
答案 2 :(得分:2)
IIUC
df.stack().groupby(level=1).head(1)
Out[619]:
Depth
500 x3 25.0
502 x2 33.0
503 x1 4.0
dtype: float64
答案 3 :(得分:2)
如果我对您的理解正确,请尝试一下:
pd.concat([df.apply(pd.Series.first_valid_index),
df.apply(pd.Series.last_valid_index)],
axis=1,
keys=['Min_Depth', 'Max_Depth'])
输出:
Min_Depth Max_Depth
x1 503 505
x2 502 505
x3 500 504
或移调输出:
pd.concat([df.apply(pd.Series.first_valid_index),
df.apply(pd.Series.last_valid_index)],
axis=1,
keys=['Min_Depth', 'Max_Depth']).T
输出:
x1 x2 x3
Min_Depth 503 502 500
Max_Depth 505 505 504
使用带功能列表的应用:
df.apply([pd.Series.first_valid_index, pd.Series.last_valid_index])
输出:
x1 x2 x3
first_valid_index 503 502 500
last_valid_index 505 505 504
稍微重命名:
df.apply([pd.Series.first_valid_index, pd.Series.last_valid_index])\
.set_axis(['Min_Depth', 'Max_Depth'], axis=0, inplace=False)
输出:
x1 x2 x3
Min_Depth 503 502 500
Max_Depth 505 505 504