pandas-数据清洗dropna,fillna,to_numeric,replace 图形解释

练习数据

物业编号,街道门牌号,街道名称,是否自住,卧室数量,浴室数量,房屋面积
100001000,104,和平路,是,3,1,950
100002000,197,解放路,否,3,1.5,–
100003000,建设路,否,n/a,1,850
100004000,201,人民路,5,1,NaN,700
,203,幸福路,是,3,2,1600
100006000,207,光明街,是,NA,1,800
100007000,NA,朝阳路,2,华杰,950
100008000,213,新华街,是,1,1,
100009000,215,东风路,是,na,2,1800
100010000,219,建国路,否,4,2.5,–

import pandas as pd

# na_values 表示是 错误类型的数据
missing_values = ["n/a", "na", "--",""]
df = pd.read_csv('./dirty-data.csv', na_values = missing_values)

# 查看数值列的统计描述(识别异常值,如最大值/最小值异常)
# count 当前列中 数据有多少个
# mean 平均值是多少
# std 标准差是多少
# min 最小值
# max 最大值
df.describe()
物业编号街道门牌号卧室数量房屋面积
count9.000000e+008.0000007.0000007.000000
mean1.000056e+08194.8750002.4285711092.857143
std3.205897e+0337.4716561.133893427.617987
min1.000010e+08104.0000001.000000700.000000
25%1.000030e+08200.0000001.500000825.000000
50%1.000060e+08205.0000003.000000950.000000
75%1.000080e+08213.5000003.0000001275.000000
max1.000100e+08219.0000004.0000001800.000000
# 显示所有的列的统计情况
df.describe(include="all")
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
count9.000000e+008.0000001097.00000097.000000
uniqueNaNNaN103NaN5NaN
topNaNNaN和平路NaN1NaN
freqNaNNaN15NaN4NaN
mean1.000056e+08194.875000NaNNaN2.428571NaN1092.857143
std3.205897e+0337.471656NaNNaN1.133893NaN427.617987
min1.000010e+08104.000000NaNNaN1.000000NaN700.000000
25%1.000030e+08200.000000NaNNaN1.500000NaN825.000000
50%1.000060e+08205.000000NaNNaN3.000000NaN950.000000
75%1.000080e+08213.500000NaNNaN3.000000NaN1275.000000
max1.000100e+08219.000000NaNNaN4.000000NaN1800.000000
# 25%:每列数据总数*25%,
# 50%:每列数据总数*50%,也就是中位数,
# 75%:每列数据总数*75%
# percentiles:指定要包括的其他百分位数,例如percentiles=[0.3,0.6,0.9]将返 总值的30%,60%,90%
df.describe(percentiles=[0.3,0.6,0.9])
物业编号街道门牌号卧室数量房屋面积
count9.000000e+008.0000007.0000007.000000
mean1.000056e+08194.8750002.4285711092.857143
std3.205897e+0337.4716561.133893427.617987
min1.000010e+08104.0000001.000000700.000000
30%1.000034e+08201.2000001.800000840.000000
50%1.000060e+08205.0000003.000000950.000000
60%1.000068e+08208.2000003.000000950.000000
90%1.000092e+08216.2000003.4000001680.000000
max1.000100e+08219.0000004.0000001800.000000
# 查看每列 (Dtype)数据类型、(Non-Null Count)非空值数量(快速定位缺失值)
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10 entries, 0 to 9
Data columns (total 7 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   物业编号    9 non-null      float64
 1   街道门牌号   8 non-null      float64
 2   街道名称    10 non-null     object 
 3   是否自住    9 non-null      object 
 4   卧室数量    7 non-null      float64
 5   浴室数量    9 non-null      object 
 6   房屋面积    7 non-null      float64
dtypes: float64(4), object(3)
memory usage: 688.0+ bytes
# 1. 查看各列缺失值数量

df.isnull().sum()
物业编号     1
街道门牌号    2
街道名称     0
是否自住     1
卧室数量     3
浴室数量     1
房屋面积     3
dtype: int64

dropna

df.dropna(axis=0, how=‘any’, thresh=None, subset=None, inplace=False)
axis:选择删除行还是列,axis=0(默认)表示操作行,axis=1表示操作列。
how:any表示一行/列有任意元素为空时即丢弃,all表示一行/列所有值都为空时才丢弃
thresh:axis中至少有N个非缺失值,否则删除。
subset:参数类型为列表,表示删除时只考虑的索引或列名。
inplace:是否在原数据上操作。

new_df = df.dropna()

new_df.to_string()
new_df
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
0100001000.0104.0和平路3.01950.0
# 只删除列 ('物业编号')中有nan的行数据
new_df = df.dropna(subset=['物业编号'])
new_df
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
0100001000.0104.0和平路3.01950.0
1100002000.0197.0解放路3.01.5NaN
2100003000.0NaN建设路NaN1850.0
3100004000.0201.0人民路51.0NaN700.0
5100006000.0207.0光明街NaN1800.0
6100007000.0NaN朝阳路NaN2.0华杰950.0
7100008000.0213.0新华街1.01NaN
8100009000.0215.0东风路NaN21800.0
9100010000.0219.0建国路4.02.5NaN

pd.fillna

pd.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)

value:用于填充的空值的值。
method: {‘backfill’, ‘bfill’, ‘pad’, ‘ffill’, None},
default None。定义了填充空值的方法,
pad / ffill表示用前面行/列的值,填充当前行/列的空值,
backfill / bfill表示用后面行/列的值,填充当前行/列的空值。

axis:轴。0或’index’,表示按行删除;1或’columns’,表示按列删除。
inplace:是否原地替换。布尔值,默认为False。如果为True,则在原DataFrame上进行操作,返回值为None。
limit:int, default None。如果method被指定,对于连续的空值,这段连续区域,最多填充前 limit 个空值(如果存在多段连续区域,每段最多填充前 limit 个空值)。如果method未被指定, 在该axis下,最多填充前 limit 个空值(不论空值连续区间是否间断)

downcast:dict, default is None,字典中的项为,为类型向下转换规则。或者为字符串“infer”,此时会在合适的等价类型之间进行向下转换,比如float64 to int64 if possible。

# 2. 填充缺失值
## 物业编号(唯一标识):用“未知编号”填充(无法用数值填充)
df['物业编号'] = df['物业编号'].fillna('未知编号')
df.head()
#df.isnull().sum()
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
0100001000.0104.0和平路3.01950.0
1100002000.0197.0解放路3.01.5NaN
2100003000.0NaN建设路NaN1850.0
3100004000.0201.0人民路51.0NaN700.0
4未知编号203.0幸福路3.021600.0

to_numeric

pandas.to_numeric(arg, errors=‘raise’, downcast=None)
arg: 待转换的数据,可以是Series、DataFrame、列表、数组等。
errors: 控制遇到无法转换的值时的处理方式,可选值包括’raise’(默认,抛出异常)、‘coerce’(将无法转换的值设置为NaN)和’ignore’(保留原始值)。
downcast: 控制数值类型的转换,可选值包括’integer’、‘signed’、‘unsigned’、‘float’,用于降低数据类型的精度。

## 街道门牌号(数值型):用中位数填充(避免受极端值影响)
# 先将“NA”文本转为NaN,再提取数值列的中位数
df['街道门牌号'] = pd.to_numeric(df['街道门牌号'], errors='coerce')  # 非数值转为NaN
df['街道门牌号'] = df['街道门牌号'].fillna(df['街道门牌号'].median())
df.head()
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
0100001000.0104.0和平路3.01950.0
1100002000.0197.0解放路3.01.5NaN
2100003000.0205.0建设路NaN1850.0
3100004000.0201.0人民路51.0NaN700.0
4未知编号203.0幸福路3.021600.0
## 是否自住(分类值):用众数“是”填充(出现频率最高)
df['是否自住'] = df['是否自住'].fillna(df['是否自住'].mode())
df.head()
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
0100001000.0104.0和平路3.01950.0
1100002000.0197.0解放路3.01.5NaN
2100003000.0205.0建设路NaN1850.0
3100004000.0201.0人民路51.0NaN700.0
4未知编号203.0幸福路3.021600.0
## 卧室数量(数值型):先统一异常文本为NaN,再用中位数填充
df['卧室数量'] = df['卧室数量'].replace(['n/a', 'na', 'NA'], pd.NA)  # 替换异常文本
df['卧室数量'] = pd.to_numeric(df['卧室数量'], errors='coerce')  # 转为数值型
df['卧室数量'] = df['卧室数量'].fillna(df['卧室数量'].median()).astype(int)  # 填充后转整数
df.head()
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
0100001000.0104.0和平路31950.0
1100002000.0197.0解放路31.5NaN
2100003000.0205.0建设路31850.0
3100004000.0201.0人民路51NaN700.0
4未知编号203.0幸福路321600.0
## 房屋面积(数值型):替换“--”为NaN,用均值填充
df['房屋面积'] = df['房屋面积'].replace('--',  pd.NA)
df['房屋面积'] = pd.to_numeric(df['房屋面积'], errors='coerce')
df['房屋面积'] = df['房屋面积'].fillna(round(df['房屋面积'].mean())).astype(int)  # 四舍五入为整数
df
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
0100001000.0104.0和平路31950
1100002000.0197.0解放路31.51093
2100003000.0205.0建设路31850
3100004000.0201.0人民路51NaN700
4未知编号203.0幸福路321600
5100006000.0207.0光明街31800
6100007000.0205.0朝阳路NaN2华杰950
7100008000.0213.0新华街111093
8100009000.0215.0东风路321800
9100010000.0219.0建国路42.51093
# 1. 修正“是否自住”(混合文本和数字,统一为“是/否”)
# 规则:原“是”保留,原“否”保留,数字/其他转为“未知”
def fix_own_occupied(x):
    if x in ['是', '否']:
        return x
    else:
        return '未知'  # 数字12/9/7等无法判断,标记为未知

df['是否自住'] = df['是否自住'].apply(fix_own_occupied)

# 2. 修正“浴室数量”(出现文本“HURLEY”,用均值替换)
df['浴室数量'] = df['浴室数量'].replace('HURLEY', pd.NA)  # 异常文本转为NaN
df['浴室数量'] = pd.to_numeric(df['浴室数量'], errors='coerce')
df['浴室数量'] = df['浴室数量'].fillna(round(df['浴室数量'].mean(), 1))  # 保留整数
df
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
0100001000.0104.0和平路31.0950
1100002000.0197.0解放路31.51093
2100003000.0205.0建设路31.0850
3100004000.0201.0人民路未知11.5700
4未知编号203.0幸福路32.01600
5100006000.0207.0光明街31.0800
6100007000.0205.0朝阳路未知21.5950
7100008000.0213.0新华街11.01093
8100009000.0215.0东风路32.01800
9100010000.0219.0建国路42.51093

修改数据类型

# 物业编号:转为字符串(避免科学计数法)
df['物业编号'] = df['物业编号'].astype(str)

# 街道门牌号:转为整数(门牌号应为整数)
df['街道门牌号'] = df['街道门牌号'].astype(int)
df
物业编号街道门牌号街道名称是否自住卧室数量浴室数量房屋面积
0100001000.0104和平路31.0950
1100002000.0197解放路31.51093
2100003000.0205建设路31.0850
3100004000.0201人民路未知11.5700
4未知编号203幸福路32.01600
5100006000.0207光明街31.0800
6100007000.0205朝阳路未知21.5950
7100008000.0213新华街11.01093
8100009000.0215东风路32.01800
9100010000.0219建国路42.51093
import pandas as pd # 读取 Excel 文件(注意添加r前缀) df = pd.read_excel(r"D:\cleaned.xlsx") # 强制转换frame_id为整型 df['frame_id'] = pd.to_numeric(df['frame_id'], errors='coerce').astype('Int64') # 筛选数据(保持原有逻辑) filtered_df = df[(df['yp'] > -3.5) & (df['yp'] <= 0)].copy() # 计算是否有紧急车辆标记 has_emergency filtered_df.loc[:, 'has_emergency'] = filtered_df.groupby('frame_id')['cls_id'].transform( lambda x: x.eq(8).any() ) def calculate_spacing(group): """按车道排序并计算平均车头间距""" sorted_vehicles = group.sort_values("xp") spacings = sorted_vehicles["xp"].diff().dropna() # 计算相邻车辆之间的距离差值 return spacings.mean() if not spacings.empty else None # 返回非空时的均值 # 按照是否为紧急状态 + 时间帧分组计算车头间距 spacing_by_group = ( filtered_df.groupby(['has_emergency', 'frame_id'], observed=True) .apply(calculate_spacing) ) # 将结果转换为 DataFrame 格式 result_df = spacing_by_group.reset_index(name='平均车头间距(m)').fillna({'平均车头间距(m)': 0}) import matplotlib.pyplot as plt # 按frame_id排序保证时间连续性 result_sorted = result_df.sort_values('frame_id') # 创建画布 plt.figure(figsize=(15, 6)) # 绘制完整折线(浅蓝色背景线) plt.plot(result_sorted['frame_id'], result_sorted['平均车头间距(m)'], color='lightblue', linewidth=1, label='基础间距') # 突出显示有应急车辆的帧(红色圆点标记) emergency_frames = result_sorted[result_sorted['has_emergency']] plt.scatter(emergency_frames['frame_id'], emergency_frames['平均车头间距(m)'], color='red', s=30, label='存在应急车辆', zorder=3) # 设置图表格式 plt.title('车头间距随时间变化趋势(应急车辆标记)', fontsize=14, pad=20) plt.xlabel('时间帧ID', fontsize=12) plt.ylabel('平均车头间距(m)', fontsize=12) plt.grid(True, linestyle='--', alpha=0.5) plt.legend(loc='upper right') # 自动调整刻度密度 plt.xticks(rotation=45) plt.tight_layout() plt.show() 有报错,完善代码
04-02
import pandas as pd import numpy as np import matplotlib.pyplot as plt # 1. 设置文件路径 file_path = r"C:\Users\asus\Desktop\E题\附件\附件1\1.xlsx" # 2. 读取 Excel 文件 df = pd.read_excel(file_path, sheet_name='Sheet1') # 3. 清洗帧号列 df['帧号'] = pd.to_numeric(df['帧号'], errors='coerce') df = df.dropna(subset=['帧号']) df = df.reset_index(drop=True) df['帧号'] = df['帧号'].astype(int) # 4. 提取脚部关键点 Y 值 foot_y_cols = ['29_Y', '30_Y', '31_Y', '32_Y'] # 检查列是否存在 for col in foot_y_cols: if col not in df.columns: raise ValueError(f"缺失关键点列:{col}") # 5. 对每个关键点进行插值修复(Y=0 视为缺失) df_interp = df[['帧号']].copy() for col in foot_y_cols: # 将 Y=0 替换为 NaN df_clean = df[col].replace(0, np.nan) # 使用线性插值修复(限制连续插值不超过5帧) df_interp[col] = df_clean.interpolate(method='linear', limit=5) # 剩余 NaN 使用前后均值或前向填充 df_interp[col] = df_interp[col].fillna(method='ffill').fillna(method='bfill') # 6. 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans'] plt.rcParams['axes.unicode_minus'] = False # 正常显示负号 # 7. 绘图 plt.figure(figsize=(16, 6)) for col in foot_y_cols: plt.plot(df_interp['帧号'], df_interp[col], label=col, linewidth=1.5) # 8. 设置横坐标刻度:每 10 帧一个 x_min = int(df_interp['帧号'].min()) x_max = int(df_interp['帧号'].max()) plt.xticks(np.arange(x_min, x_max + 1, 10)) # 9. 设置纵坐标刻度:每 50 像素一个 y_min = df_interp[foot_y_cols].min().min() y_max = df_interp[foot_y_cols].max().max() y_ticks = np.arange((y_min // 50) * 50, (y_max // 50 + 2) * 50, 50) plt.yticks(y_ticks) # 10. 添加标题和标签 plt.title('运动者1脚部关键点29、30、31、32的Y值关于帧值的分析图像', fontsize=16, pad=20) plt.xlabel('帧号', fontsize=12) plt.ylabel('Y 坐标(像素)', fontsize=12) # 11. 图例与网格 plt.legend(loc='upper right') plt.grid(True, alpha=0.3) # 12. 调整布局并显示 plt.tight_layout() plt.show() 参照上述代码把上传的表 代码展示出来
09-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值