材料数据预处理实战:数据清洗、去重、格式标准化
说实话,做AI辅助材料筛选这几年,我踩过最大的坑就是——数据没洗干净就往上怼模型。你想想看,垃圾数据进去,再牛的算法也白搭。今天咱们就聊聊材料数据预处理这回事,我用Pandas实战一把。
为什么预处理这么重要?
我记得刚入行那会儿,接过一个材料性能预测的项目。客户给了3万条钢材数据,我兴冲冲地直接跑模型,结果R²只有0.3。后来一查,好家伙,30%的数据是重复的,还有一堆格式乱七八糟的。说白了,数据预处理占整个项目80%的时间,一点都不夸张。
核心原则:干净的数据 = 靠谱的模型。预处理做不好,后面全是白费功夫。
第一步:数据加载与初步探索
我习惯先用Pandas把数据读进来,然后快速扫一眼整体情况。就像去医院体检,先做个全面检查再说。
import pandas as pd
import numpy as np
# 加载材料数据
df = pd.read_csv('materials_data.csv')
# 快速预览
print(df.head())
print(df.info())
print(df.describe())
这里有个小技巧:df.info()能告诉你每列有多少非空值,数据类型是什么。我一般先看这个,心里就有数了。
第二步:数据清洗——处理缺失值与异常值
材料数据里,缺失值太常见了。比如某批次的硬度没测,或者某个成分含量没记录。怎么处理?
缺失值处理策略
| 策略 | 适用场景 | 代码示例 |
|---|---|---|
| 删除缺失行 | 缺失比例 < 5% | df.dropna() |
| 填充均值/中位数 | 数值型特征,分布较均匀 | df.fillna(df.mean()) |
| 前向填充 | 时间序列数据 | df.fillna(method='ffill') |
| 插值法 | 连续变化的数据 | df.interpolate() |
我的经验:对于材料性能数据,我一般先用中位数填充。因为材料数据经常有极端值,均值容易被带偏。比如某批次的抗拉强度异常高,均值填充反而引入偏差。
异常值检测
我曾经处理过一批铝合金数据,发现有个样本的密度是0.5 g/cm³。铝合金密度一般在2.6-2.8之间,这明显是录入错误。怎么快速揪出来?
# 使用Z-score方法检测异常值
from scipy import stats
z_scores = np.abs(stats.zscore(df['density']))
outliers = df[z_scores > 3]
print(f"发现 {len(outliers)} 个异常值")
注意:不要盲目删除异常值。有些异常值可能是新材料或特殊工艺导致的。我建议先标记出来,跟业务方确认后再处理。
第三步:数据去重——别让重复数据骗了你
材料数据里重复的情况很常见。比如同一个批次被录入了两次,或者不同来源的数据有重叠。去重是必须的。
# 检查重复行
duplicates = df.duplicated().sum()
print(f"重复行数: {duplicates}")
# 基于关键列去重
df_clean = df.drop_duplicates(subset=['batch_id', 'material_type'])
# 保留最后一条记录
df_clean = df.drop_duplicates(subset=['sample_id'], keep='last')
嗯,这里要注意:keep='last'的意思是保留最后出现的重复项。我一般用这个,因为后面的记录可能是修正过的版本。
第四步:格式标准化——让数据说同一种语言
材料数据最头疼的就是格式不统一。比如温度,有的用摄氏度,有的用华氏度;成分含量,有的用百分比,有的用ppm。不标准化,模型根本没法用。
常见标准化操作
- 单位统一:把所有温度转成摄氏度,所有长度转成毫米
- 文本清洗:去除空格、统一大小写、处理特殊字符
- 数据类型转换:把字符串转成数值,把日期转成标准格式
- 分类编码:对材料类型、工艺等做One-Hot编码
# 温度标准化:华氏度转摄氏度
df['temp_c'] = (df['temp_f'] - 32) * 5/9
# 文本清洗:去除前后空格,统一小写
df['material_name'] = df['material_name'].str.strip().str.lower()
# 数据类型转换
df['test_date'] = pd.to_datetime(df['test_date'])
# 分类编码
df_encoded = pd.get_dummies(df, columns=['material_type'])
关键点:标准化不是一次性的工作。我建议写一个预处理函数,每次有新数据进来就跑一遍,保证一致性。
知识体系总览
下面这张图是我自己总结的材料数据预处理流程,你可以照着这个思路来。
实战案例:铝合金材料数据预处理
咱们来个完整的例子。假设你拿到了一批铝合金的拉伸测试数据,包含:批次号、测试日期、抗拉强度、屈服强度、延伸率、热处理温度。
# 完整预处理流程
def preprocess_material_data(df):
# 1. 数据清洗
df = df.dropna(subset=['tensile_strength', 'yield_strength'])
df['elongation'] = df['elongation'].fillna(df['elongation'].median())
# 2. 异常值处理(基于3σ原则)
for col in ['tensile_strength', 'yield_strength']:
mean = df[col].mean()
std = df[col].std()
df = df[(df[col] >= mean - 3*std) & (df[col] <= mean + 3*std)]
# 3. 去重
df = df.drop_duplicates(subset=['batch_id', 'test_date'], keep='last')
# 4. 标准化
df['test_date'] = pd.to_datetime(df['test_date'])
df['heat_treat_temp'] = (df['heat_treat_temp'] - 32) * 5/9 # 华氏度转摄氏度
return df
# 执行预处理
df_clean = preprocess_material_data(df)
print(f"原始数据: {len(df)} 条")
print(f"清洗后: {len(df_clean)} 条")
print(f"去除了 {len(df) - len(df_clean)} 条无效数据")
避坑指南:我曾经在去重时没注意时间顺序,把最新的数据删了,保留了旧的。后来发现模型预测偏差很大。所以去重时一定要想清楚保留哪一条。
数据探索:用Pandas快速了解数据
预处理完了,别急着建模。先用Pandas做一波探索性分析,看看数据长什么样。
# 相关性分析
correlation = df_clean[['tensile_strength', 'yield_strength', 'elongation', 'heat_treat_temp']].corr()
print(correlation)
# 分组统计
group_stats = df_clean.groupby('batch_id').agg({
'tensile_strength': ['mean', 'std', 'min', 'max'],
'yield_strength': 'mean'
})
print(group_stats)
# 分布情况
print(df_clean['heat_treat_temp'].describe())
你想想看,这一步能帮你发现很多隐藏问题。比如某个批次的抗拉强度标准差特别大,说明工艺不稳定,需要重点关注。
总结一下:数据预处理不是一次性工作。我每次拿到新数据,都会跑一遍这个流程。养成习惯后,你会发现模型效果稳定很多,调试时间也大大缩短。