按分组查找DataFrame各列首个有效值的高效实现方案
按分组获取DataFrame多列的首个有效值
我来帮你高效搞定这个需求!要实现按列a分组后,每组各列保留第一个非NaN的数值型有效值,Pandas有个简洁又高效的方法,完美匹配你的场景。
先看你的原始数据
先把示例DataFrame的代码贴出来,方便复现测试:
import pandas as pd import numpy as np df = pd.DataFrame({ 'a':[1,1,1,1,1,2,2,2], 'b':[2,np.nan,4,np.nan,5,np.nan,1,np.nan], 'c':[np.nan,1,4,0,4,np.nan,6,np.nan], 'd':[np.nan, np.nan, np.nan, 1,6,2,5,np.nan] })
原始数据的结构如下:
| 索引 | a | b | c | d |
|---|---|---|---|---|
| 0 | 1 | 2.0 | NaN | NaN |
| 1 | 1 | NaN | 1.0 | NaN |
| 2 | 1 | 4.0 | 4.0 | NaN |
| 3 | 1 | NaN | 0.0 | 1.0 |
| 4 | 1 | 5.0 | 4.0 | 6.0 |
| 5 | 2 | NaN | NaN | 2.0 |
| 6 | 2 | 1.0 | 6.0 | 5.0 |
| 7 | 2 | NaN | NaN | NaN |
最优解决方案:groupby().first()
Pandas的groupby.first()方法就是专门干这个的——返回每组中第一个非缺失值,而且是向量化操作,比循环处理快得多,数据量大的时候优势特别明显。
代码就这么一行:
result = df.groupby('a', as_index=False).first()
运行后得到的结果完全符合你的期望:
| 索引 | a | b | c | d |
|---|---|---|---|---|
| 0 | 1 | 2.0 | 1.0 | 1.0 |
| 1 | 2 | 1.0 | 6.0 | 2.0 |
为什么这个方法好用?
groupby('a'):按列a的取值对DataFrame分组as_index=False:让分组列a保留为普通列,而不是变成索引(如果不需要可以去掉,结果会把a设为索引)first():对每组的每一列,从前往后遍历找到第一个非NaN的值,直接作为该组该列的结果
备选自定义方案(灵活场景用)
如果之后你需要更灵活的规则(比如取最后一个有效值,或者自定义筛选逻辑),可以用apply配合dropna()实现,不过效率会低一些:
result = df.groupby('a').apply( lambda x: x.apply(lambda col: col.dropna().iloc[0] if not col.dropna().empty else np.nan) ).reset_index()
但对于你当前的需求,groupby().first()绝对是最简洁高效的选择。
内容的提问来源于stack exchange,提问作者yatu
相关产品推荐
相关产品推荐

