如何移除Pandas DataFrame各列中的所有NaN值?
如何独立移除DataFrame各列的NaN值
我来帮你搞定这个问题!先理清楚你的核心需求:你希望每一列都保留所有非NaN的记录,哪怕不同列的有效行数不一样,而不是删除任何包含NaN的整行——这也是你用dropna(how='any')失败的原因,因为这个方法会删掉任何有NaN的行,你的数据里大部分行都存在NaN,所以最后啥都没剩下。
先明确你的数据和目标
首先把你给出的原始DataFrame整理成更清晰的格式:
import pandas as pd import numpy as np # 构造你的原始数据 df = pd.DataFrame({ 'Col_1': [10, 22, 3, 4, np.nan, 4, 6, 10, 12], 'Col_2': [5, 7, 9, np.nan, np.nan, np.nan, 7, np.nan, np.nan], 'Col_3': [2, 7, 5, np.nan, np.nan, np.nan, 7, np.nan, 1] })
对应的表格:
| Col_1 | Col_2 | Col_3 | |
|---|---|---|---|
| 0 | 10 | 5 | 2 |
| 1 | 22 | 7 | 7 |
| 2 | 3 | 9 | 5 |
| 3 | 4 | NaN | NaN |
| 4 | NaN | NaN | NaN |
| 5 | 4 | NaN | NaN |
| 6 | 6 | 7 | 7 |
| 7 | 10 | NaN | NaN |
| 8 | 12 | NaN | 1 |
你想要的结果是每列保留所有非NaN值,最终各列按顺序排列,行数不够的地方补NaN,也就是类似这样:
| Col_1 | Col_2 | Col_3 | |
|---|---|---|---|
| 0 | 10 | 5 | 2 |
| 1 | 22 | 7 | 7 |
| 2 | 3 | 9 | 5 |
| 3 | 4 | 7 | 7 |
| 4 | 4 | NaN | 1 |
| 5 | 6 | NaN | NaN |
| 6 | 10 | NaN | NaN |
| 7 | 12 | NaN | NaN |
两种可行的解决方案
方法1:按列单独处理后拼接
对每一列单独调用dropna(),然后重置索引对齐,最后用pd.concat拼接起来:
# 遍历每一列,提取非NaN值并重置索引 filtered_cols = [df[col].dropna().reset_index(drop=True) for col in df.columns] # 拼接成新的DataFrame filtered_df = pd.concat(filtered_cols, axis=1)
这个方法逻辑很直观,就是逐列清理NaN,再把各列的有效数据拼在一起,自动用NaN填充长度不足的列。
方法2:用stack/unstack快速处理
Pandas的stack()和unstack()方法可以更简洁地实现这个需求:
filtered_df = df.stack().unstack()
stack()会把DataFrame转换成Series,自动过滤掉NaN;unstack()再把Series转换回DataFrame,空缺的位置自动补NaN,结果和方法1完全一致,代码更短。
为什么你的原代码不行?
再解释下df.dropna(how='any')的逻辑:它会检查每一行,只要这一行里有任何一个NaN,就把整行删掉。你的原始数据里,除了前3行,其他行都至少有一个NaN,所以执行后所有行都被删除了,这和你想要的“保留每列有效数据”的需求完全不符。
内容的提问来源于stack exchange,提问作者user_01
相关产品推荐
相关产品推荐

