前言
在数据分析时,经常会遇到数据缺失的情况。而Pandas这个Python数据分析库提供了多种方法来处理缺失值。
缺失值是什么?
pandas中的缺失值
- NaN(NotaNumber)是缺失值的标志
- 方法:isna(),notna()
pandas使用浮点值NaN(NotaNumber)表示缺失数据,使用NA(NotAvailable)
表示缺失值。可以通过isnull()、isna()或notnull()、notna()方法判断某个值是否为缺失
值。
Nan通常表示一个无效的或未定义的数字值,是浮点数的一种特殊取值,用于表示那
些不能表示为正常数字的情况,如0/0、∞-∞等数学运算的结果。nan与任何值(包括
它自身)进行比较的结果都为False。例如在Python中,nan==nan返回False。
NA一般用于表示数据不可用或缺失的情况,它的含义更侧重于数据在某种上下文中是
缺失或不存在的,不一定特指数字类型的缺失。
na和nan都用于表示缺失值,但nan更强调是数值计算中的特殊值,而na更强调数
据的可用性或存在性。
python
import pandas as pd
import numpy as np
s=pd.Series([np.nan,pd.NA,None])
print(s)
s.isna()
0 NaN
1 <NA>
2 None
dtype: object
0 True
1 True
2 True
dtype: bool
准备数据
python
import numpy as np
import pandas as pd
df = pd.DataFrame({
"name":["bob","jack","talk","tell","see","sala"],
"age":[10,15,36,np.nan,40,np.nan],
"height":[1.65,1.70,np.nan,1.7,1.85,1.80]
})
print(df)
name age height
0 bob 10.0 1.65
1 jack 15.0 1.70
2 talk 36.0 NaN
3 tell NaN 1.70
4 see 40.0 1.85
5 sala NaN 1.80
查看缺失值
方法:isna()或者isnull()
python
print(df.isna())
print(df.isna().sum())
name age height
0 False False False
1 False False False
2 False False True
3 False True False
4 False False False
5 False True False
name 0
age 2
height 1
dtype: int64
删除缺失值
常用方法
python
df.dropna() #删除含有缺失值的行,默认情况删除行,df.dropna(axis=1) axis=1删除含有缺失值的列
name age height
0 bob 10.0 1.65
1 jack 15.0 1.70
4 see 40.0 1.85
python
df.dropna(subset=["age"]) #如果某列有缺失值,则删除这一行
name age height
0 bob 10.0 1.65
1 jack 15.0 1.70
2 talk 36.0 NaN
4 see 40.0 1.85
python
df.dropna(axis=0, how="all") #how="all",所有值都是缺失值才会删除 默认any
name age height
0 bob 10.0 1.65
1 jack 15.0 1.70
2 talk 36.0 NaN
3 tell NaN 1.70
4 see 40.0 1.85
5 sala NaN 1.80
python
df.dropna(thresh=2)# 如果至少由n个不是缺失值,就保留
name age height
0 bob 10.0 1.65
1 jack 15.0 1.70
2 talk 36.0 NaN
3 tell NaN 1.70
4 see 40.0 1.85
5 sala NaN 1.80
填充缺失值
python
df.fillna(10) #所有的缺失值,都填充10
name age height
0 bob 10.0 1.65
1 jack 15.0 1.70
2 talk 36.0 10.00
3 tell 10.0 1.70
4 see 40.0 1.85
5 sala 10.0 1.80
python
df.fillna({"age":10,"height":2.26}) #使用字典填充 age 缺失值填充10 height填充 2.26
name age height
0 bob 10.0 1.65
1 jack 15.0 1.7
2 talk 36.0 2.26
3 tell 10.0 1.7
4 see 40.0 1.85
5 sala 10.0 1.8
python
df.fillna({"age":df["age"].mean(),"height":df["height"].mean()}) #使用字典填充 按照平均值填充
name age height
0 bob 10.00 1.65
1 jack 15.00 1.70
2 talk 36.00 1.74
3 tell 25.25 1.70
4 see 40.00 1.85
5 sala 25.25 1.80
python
df.fillna(df[["age","height"]].mean()) #使用平均值填充
name age height
0 bob 10.00 1.65
1 jack 15.00 1.70
2 talk 36.00 1.74
3 tell 25.25 1.70
4 see 40.00 1.85
5 sala 25.25 1.80
注意df.fillna(df[["age","height"]].mean()) 为啥两层中括号 [["age","height"]]
pandas中使用两层中括号df[["age"]].mean()的原因
在pandas中,使用 df.fillna(df[["age"]].mean()) 时采用两层中括号是为了保持数据结构的一致性,这涉及到pandas中索引操作的一个重要区别:
核心区别:
- 一层中括号 df["age"] 返回的是一个 Series对象
- 结果是一维数组结构
- .mean() 会返回一个标量值(单个数字)
- 两层中括号 df[["age"]] 返回的是一个 DataFrame对象
- mean() 会返回一个标量值(单个数字)
- mean() 会返回一个DataFrame对象,索引为列名,值为均值
实际作用:
使用两层中括号的主要好处是:
- 保持数据对齐 :当使用 fillna() 时,DataFrame格式的均值会自动根据列名进行对齐,只填充对应列的缺失值。
- 支持多列操作 :如果需要同时处理多列,可以方便地扩展为 df.fillna(df[["age", "income"]].mean())。
- 避免广播问题 :使用DataFrame格式可以避免标量值被广播到所有列的风险。
因此,当你只想填充特定列的缺失值而不影响其他列时,使用两层中括号是一个良好的实践,可以确保操作的精确性和可预测性。
python
df.ffill() #使用前面的相邻值进行填充
name age height
0 bob 10.0 1.65
1 jack 15.0 1.70
2 talk 36.0 1.70
3 tell 36.0 1.70
4 see 40.0 1.85
5 sala 40.0 1.80
python
df.bfill()#使用后面的相临值进行填充
name age height
0 bob 10.0 1.65
1 jack 15.0 1.70
2 talk 36.0 1.70
3 tell 40.0 1.70
4 see 40.0 1.85
5 sala NaN 1.80
案例练习
df=pd.read_csv("test.csv",keep_default_na=False) #可以通过keep_default_na参数设置是否将空白值设置为缺失值。
print(df.head(6))
日期 最高气温 最低气温
0 2025-07-01 33.0 24.6
1 2025-07-02
2 2025-07-03 33.3 27.7
3 2025-07-04 35.1 27.6
4 31.6 26.4
5 2025-07-06 31.6 22.1
开始
df=pd.read_csv("test.csv")
print(df.head(6))
日期 最高气温 最低气温
0 2025-07-01 33.0 24.6
1 2025-07-02 NaN NaN
2 2025-07-03 33.3 27.7
3 2025-07-04 35.1 27.6
4 NaN 31.6 26.4
5 2025-07-06 31.6 22.1
python
df=pd.read_csv("test.csv")
df["日期"]=pd.to_datetime(df["日期"])
print(df.head(6))
# df=df.interpolate(method="linear")
df=df.fillna(df[["最高气温","最低气温"]].mean().round(2))
print(df.head(6))
日期 最高气温 最低气温
0 2025-07-01 33.0 24.6
1 2025-07-02 NaN NaN
2 2025-07-03 33.3 27.7
3 2025-07-04 35.1 27.6
4 2025-07-04 31.6 26.4
5 2025-07-06 31.6 22.1
日期 最高气温 最低气温
0 2025-07-01 33.00 24.60
1 2025-07-02 31.83 24.49
2 2025-07-03 33.30 27.70
3 2025-07-04 35.10 27.60
4 2025-07-04 31.60 26.40
5 2025-07-06 31.60 22.10
折线图
python
import matplotlib.pyplot as plt
from matplotlib import rcParams
# 设置中文正常显示
rcParams['font.family'] = 'SimHei'
plt.figure(figsize=(12, 6))
# 绘制最高和最低气温曲线
plt.plot(df['日期'], df['最高气温'], 'r', marker='o', label='最高气温')
plt.plot(df['日期'], df['最低气温'], 'b-', marker='o', label='最低气温')
# 填充温差区域
plt.fill_between(df['日期'], df['最低气温'], df['最高气温'], alpha=0.1, color='gray')
# 设置图表属性
plt.title(f'2025年7月份气温变化趋势')
plt.xlabel('日期')
plt.ylabel('气温 (°C)')
plt.grid(True, alpha=0.3)
plt.legend()
# 设置x轴标签旋转角度
plt.xticks(rotation=45)
# 调整布局
plt.tight_layout()
# 显示图表
plt.show()
