第三章:材料数据库构建——从公开数据库获取数据并进行清洗与标准化
各位同学,今天我们来聊聊材料基因组学里最基础、也最磨人的一环——数据库构建。
说实话,我刚开始接触这个领域时,以为搞材料就是做实验、测数据。后来才发现,真正推动材料发现的,往往是那些躺在公开数据库里的海量数据。但问题来了:数据是公开的,可它不会自己洗干净了送到你面前。
这一章,我就带大家走一遍从Materials Project、OQMD这些公开数据库拉数据,再到清洗、标准化的完整流程。嗯,都是我在项目里踩过坑之后总结出来的经验。
3.1 公开数据库概览:你该从哪里下手?
目前材料基因组学领域,有几个公认的“数据金矿”。我个人最常用的是这三个:
| 数据库名称 | 数据规模 | 主要数据类型 | API支持 |
|---|---|---|---|
| Materials Project | ~15万种材料 | 晶体结构、能带、弹性常数、相图 | RESTful API (pymatgen) |
| OQMD | ~100万种材料 | 热力学稳定性、形成能 | REST API + 批量下载 |
| AFLOW | ~350万种材料 | 电子结构、力学性质 | AFLUX API |
你想想看,光Materials Project就有15万种材料的数据。但问题是,这些数据格式、单位、命名规则都不一样。直接拿来用?那你的模型大概率会翻车。
核心原则:公开数据只是原材料,不是成品。数据清洗和标准化,才是真正体现工程师水平的地方。
3.2 从Materials Project获取数据:API实战
我个人习惯用pymatgen库来对接Materials Project。为什么?因为它封装得好,几行代码就能搞定。
先安装必要的库:
pip install pymatgen
pip install mp-api
然后,你需要去Materials Project官网申请一个API密钥。这个步骤别偷懒,我见过有人直接用别人的密钥,结果被封了IP。
下面是一个完整的获取数据示例:
from pymatgen.ext.matproj import MPRester
# 初始化API连接
api_key = "你的API密钥"
mpr = MPRester(api_key)
# 查询所有含Li和Fe的氧化物
criteria = {
"elements": ["Li", "Fe", "O"],
"nelements": 3
}
properties = ["material_id", "formula_pretty", "structure",
"formation_energy_per_atom", "band_gap"]
# 获取数据
data = mpr.query(criteria, properties)
print(f"共获取到 {len(data)} 条记录")
for entry in data[:3]:
print(entry["formula_pretty"], entry["band_gap"])
这里有个坑:一次查询不要拉太多数据。我曾经一次性拉10万条,结果API直接超时,还得重新跑。建议分批查询,每次5000条左右。
小技巧:可以用 mpr.query(criteria, properties, chunk_size=1000) 来分块获取,避免内存爆炸。
3.3 从OQMD获取数据:另一种风格
OQMD的API风格和Materials Project不太一样。它更偏向于批量下载,而且数据量更大。
来看一个例子:
import requests
import json
# OQMD API端点
base_url = "https://oqmd.org/oqmdapi/"
# 查询形成能低于-0.5 eV/atom的Li-Fe-O体系
params = {
"composition": "Li-Fe-O",
"filter": "delta_e__lt:-0.5",
"limit": 100
}
response = requests.get(f"{base_url}composition", params=params)
data = response.json()
print(f"获取到 {len(data)} 条符合条件的材料")
嗯,这里要注意:OQMD返回的数据结构比较乱。有时候同一个字段名,不同材料返回的类型都不一样。比如“band_gap”字段,有的返回浮点数,有的返回字符串“None”。
避坑指南:我曾经在OQMD数据上吃过亏——直接拿字符串“None”当数值处理,结果模型训练出来一堆NaN。后来我养成了习惯:每次拉完数据,先检查字段类型是否一致。
3.4 数据清洗:把脏数据变成干净数据
数据拉回来了,但问题才刚刚开始。我总结了一套“三步清洗法”:
- 缺失值处理:删除或填充缺失字段
- 异常值检测:识别并处理不合理的数据点
- 格式统一:把字符串、列表等转成统一格式
来看一个实际清洗的例子:
import pandas as pd
import numpy as np
# 假设我们从Materials Project拉到了原始数据
raw_data = [
{"formula": "LiFeO2", "band_gap": 2.1, "formation_energy": -1.5},
{"formula": "Li2FeO3", "band_gap": None, "formation_energy": -2.0},
{"formula": "LiFe5O8", "band_gap": "1.8", "formation_energy": -0.8},
{"formula": "Fe2O3", "band_gap": 2.2, "formation_energy": None},
]
df = pd.DataFrame(raw_data)
# 第一步:处理缺失值
df["band_gap"] = pd.to_numeric(df["band_gap"], errors="coerce")
df["formation_energy"] = pd.to_numeric(df["formation_energy"], errors="coerce")
# 第二步:删除关键字段缺失的行
df_clean = df.dropna(subset=["band_gap", "formation_energy"])
# 第三步:异常值检测(形成能不应该大于0)
df_clean = df_clean[df_clean["formation_energy"] < 0]
print(f"清洗前: {len(df)} 条, 清洗后: {len(df_clean)} 条")
你可能会问:为什么形成能大于0就要删掉?说白了,形成能大于0意味着这个材料在热力学上不稳定,不太可能被合成出来。当然,如果你研究的是亚稳态材料,那另当别论。
3.5 数据标准化:让不同来源的数据“说同一种语言”
数据清洗完了,但还有一个大问题:不同数据库的单位、命名规则不一样。
举个例子:
- Materials Project的形成能单位是
eV/atom - OQMD的形成能单位是
eV/formula_unit - AFLOW的形成能单位是
meV/atom
如果不做标准化,你把这些数据混在一起训练模型,结果就是灾难。
我一般会建立一个“标准单位体系”:
| 属性 | 标准单位 | 转换规则 |
|---|---|---|
| 形成能 | eV/atom | OQMD: 除以原子数;AFLOW: 除以1000 |
| 带隙 | eV | 无需转换 |
| 晶格常数 | Å | 统一使用埃斯特朗 |
| 弹性模量 | GPa | 部分数据库用Pa,需除以1e9 |
标准化代码示例:
def standardize_formation_energy(value, source, num_atoms=None):
"""
将不同来源的形成能统一为 eV/atom
"""
if source == "materials_project":
# 已经是 eV/atom
return value
elif source == "oqmd":
# 需要除以原子数
return value / num_atoms if num_atoms else value
elif source == "aflow":
# meV/atom 转 eV/atom
return value / 1000.0
else:
raise ValueError(f"未知数据来源: {source}")
# 使用示例
mp_energy = -1.5 # eV/atom
oqmd_energy = -4.5 # eV/formula_unit, 假设有3个原子
aflow_energy = -1500 # meV/atom
print(f"MP: {mp_energy} eV/atom")
print(f"OQMD标准化后: {standardize_formation_energy(oqmd_energy, 'oqmd', 3)} eV/atom")
print(f"AFLOW标准化后: {standardize_formation_energy(aflow_energy, 'aflow')} eV/atom")
3.6 本章知识体系总览
说了这么多,我画了一张图来总结整个流程。你看一眼就能明白:
这张图把整个流程串起来了。从三个主流数据库出发,经过API获取、数据清洗、数据标准化,最终得到一份可以直接用于机器学习或数据分析的干净数据集。
3.7 一些实用建议
最后,分享几个我在项目中积累的经验:
- 先小批量测试:别一上来就拉百万级数据。先拿100条试试流程,确认没问题再全量拉取。
- 保留原始数据:清洗后的数据要另存一份,原始数据别删。我吃过这个亏——清洗规则写错了,想回退发现原始数据已经被覆盖了。
- 写日志:每次清洗操作都记录一下,比如删了多少条、改了哪些字段。这样出了问题好排查。
- 版本控制:数据集也要做版本管理。我习惯用
dataset_v1.0.csv、dataset_v1.1.csv这样的命名方式。
一句话总结:数据清洗和标准化,占整个材料基因组学项目60%以上的工作量。别嫌烦,这一步做扎实了,后面的建模和分析才能顺风顺水。
好了,这一章的内容就到这里。记住:公开数据库是宝藏,但只有经过精心打磨的数据,才能真正驱动材料发现。