第4章 Pandas入门:从数据到洞察的第一步
说实话,做材料计算这几年,我最大的感触就是——数据本身不会说话,但Pandas能让它开口。你可能已经用VASP、LAMMPS算了一大堆数据,但面对几十个CSV文件时,是不是有点头大?别急,这一章我们就把Pandas这个利器彻底搞明白。
4.1 Series与DataFrame:Pandas的两大基石
先说说这两个东西到底是什么。我刚开始接触Pandas时,总觉得它们很抽象。后来我给自己打了个比方:Series是一列数据,DataFrame是一张表格。就这么简单。
4.1.1 Series:带标签的一维数组
Series说白了就是「有名字的一列数据」。它比Python列表强在哪?强在你可以给每个数据起个名字(索引)。
import pandas as pd
# 创建一个Series
energies = pd.Series([-4.56, -3.21, -5.89, -2.34],
index=['Si', 'Ge', 'GaAs', 'InP'])
print(energies)
# 输出:
# Si -4.56
# Ge -3.21
# GaAs -5.89
# InP -2.34
# dtype: float64
你看,每个能量值都对应一个材料名。这在处理材料数据时特别方便。我记得有一次做能带计算,需要快速查找某个材料的带隙值,用Series的索引查找比列表快多了。
4.1.2 DataFrame:表格数据的终极形态
DataFrame就是一张电子表格。行是样本,列是属性。做材料计算的人,天天跟这个打交道。
# 创建一个DataFrame
data = {
'材料': ['Si', 'Ge', 'GaAs', 'InP'],
'带隙(eV)': [1.12, 0.67, 1.43, 1.35],
'晶格常数(Å)': [5.43, 5.66, 5.65, 5.87],
'介电常数': [11.9, 16.0, 12.9, 12.5]
}
df = pd.DataFrame(data)
print(df)
输出结果就像一张整齐的表格。我个人习惯把计算出的所有结构参数都塞进一个DataFrame里,这样后续做筛选、绘图都特别顺手。
4.2 数据读取与写入:CSV和Excel
嗯,这里要注意——材料计算的数据文件格式五花八门,但CSV和Excel是最常见的两种。我见过太多人手动复制粘贴数据了,其实一行代码就能搞定。
4.2.1 读取CSV文件
# 读取CSV文件
df = pd.read_csv('band_structure.csv')
# 常用参数
df = pd.read_csv('data.csv',
sep=',', # 分隔符,默认逗号
header=0, # 第0行作为列名
index_col=0, # 第0列作为行索引
na_values=['NA', 'null']) # 指定缺失值标记
我曾经处理过一个VASP计算的大批量数据,几百个CSV文件,每个文件里还有空行和注释。用skiprows参数跳过前几行,用comment参数忽略注释行,几分钟就搞定了。
4.2.2 读取Excel文件
# 读取Excel文件
df = pd.read_excel('experimental_data.xlsx', sheet_name='Sheet1')
# 读取多个sheet
dfs = pd.read_excel('data.xlsx', sheet_name=None) # 返回字典
header=None,自己手动指定列名,问题就解决了。
4.2.3 写入文件
# 写入CSV
df.to_csv('processed_data.csv', index=False)
# 写入Excel
df.to_excel('result.xlsx', sheet_name='计算结果', index=False)
你想想看,每次算完一批数据,直接to_csv保存,既规范又省事。我一般会在文件名里加上日期,比如results_2024_01_15.csv,方便追溯。
4.3 数据清洗与筛选:把脏数据变干净
做材料计算的人都知道,原始数据很少是完美的。有时候计算不收敛,有时候实验测量有误差,数据里总会有各种「脏东西」。清洗数据,说白了就是把这些脏东西挑出来或者修好。
4.3.1 查看数据概览
# 快速查看数据
df.head() # 前5行
df.info() # 列信息、非空值数量、数据类型
df.describe() # 统计摘要(均值、标准差、分位数等)
我个人习惯拿到数据先跑df.info(),看看有没有列的数据类型不对。比如「带隙」这一列如果是object类型而不是float,那肯定有问题。
4.3.2 筛选数据
# 条件筛选
# 筛选带隙大于1.0 eV的材料
wide_gap = df[df['带隙(eV)'] > 1.0]
# 多条件筛选
# 带隙在1.0-2.0之间,且介电常数大于10
selected = df[(df['带隙(eV)'] >= 1.0) & (df['带隙(eV)'] <= 2.0) & (df['介电常数'] > 10)]
# 按列筛选
df[['材料', '带隙(eV)']]
为什么筛选这么重要?因为很多时候我们只关心特定范围的数据。比如研究光伏材料,你肯定只关心带隙在1.0-1.5 eV之间的材料。用Pandas筛选,一行代码就搞定。
4.3.3 排序与去重
# 按带隙升序排序
df_sorted = df.sort_values('带隙(eV)')
# 去重
df_unique = df.drop_duplicates(subset=['材料'])
我记得有一次处理合金成分的数据,同一个成分重复计算了好几次。用drop_duplicates去重后,数据量直接减半,分析起来清爽多了。
4.4 缺失值处理:别让NaN毁了你的分析
缺失值,就是数据里的「黑洞」。计算不收敛、实验没测到、数据录入遗漏……原因太多了。但你不能不管它,否则后续画图、拟合全都会报错。
4.4.1 检测缺失值
# 检测缺失值
df.isnull().sum() # 每列缺失值数量
# 缺失值占比
df.isnull().mean() * 100
4.4.2 处理缺失值的三种策略
处理缺失值,说白了就三条路:删、填、插。我根据自己的经验给你总结一下:
| 策略 | 方法 | 适用场景 | 代码示例 |
|---|---|---|---|
| 删除 | 直接扔掉有缺失的行或列 | 缺失值很少(<5%) | df.dropna() |
| 填充 | 用均值、中位数、众数填充 | 缺失值较多,但数据分布稳定 | df.fillna(df.mean()) |
| 插值 | 用前后值线性插值 | 时间序列或连续变化的数据 | df.interpolate() |
# 具体示例
# 1. 删除所有包含缺失值的行
df_clean = df.dropna()
# 2. 用均值填充
df['带隙(eV)'] = df['带隙(eV)'].fillna(df['带隙(eV)'].mean())
# 3. 线性插值(适用于随温度变化的物理量)
df['电阻率'] = df['电阻率'].interpolate(method='linear')
4.5 本章知识体系
下面这张图帮你理清Pandas处理材料数据的完整流程:
这张图展示的就是我们处理材料数据的完整链路。从读取原始数据开始,经过清洗、缺失值处理,再到分析和可视化。每一步都离不开Pandas。
read_csv、head、info、dropna、fillna这几个最常用的,剩下的遇到问题再查。我当年就是这么过来的。
好了,这一章的内容就到这里。Pandas的核心就是让你用最少的代码,做最多的事。下一章我们会把这些技巧用在真实的材料计算数据上,到时候你就知道这些东西有多好用了。
公众号:蓝海资料掘金营,微信deep3321