第三章:材料数据库构建——从公开数据库获取数据并进行清洗与标准化

各位同学,今天我们来聊聊材料基因组学里最基础、也最磨人的一环——数据库构建。

说实话,我刚开始接触这个领域时,以为搞材料就是做实验、测数据。后来才发现,真正推动材料发现的,往往是那些躺在公开数据库里的海量数据。但问题来了:数据是公开的,可它不会自己洗干净了送到你面前。

这一章,我就带大家走一遍从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 数据清洗:把脏数据变成干净数据

数据拉回来了,但问题才刚刚开始。我总结了一套“三步清洗法”:

  1. 缺失值处理:删除或填充缺失字段
  2. 异常值检测:识别并处理不合理的数据点
  3. 格式统一:把字符串、列表等转成统一格式

来看一个实际清洗的例子:

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 本章知识体系总览

说了这么多,我画了一张图来总结整个流程。你看一眼就能明白:

材料数据库构建流程 Materials Project OQMD AFLOW API数据获取(RESTful / 批量下载) pymatgen / requests / AFLUX 数据清洗 缺失值处理 → 异常值检测 → 格式统一 pandas / numpy / 自定义规则 数据标准化(单位统一 / 命名规范 / 格式对齐) eV/atom → 标准单位 | 元素符号统一 | 结构格式标准化

这张图把整个流程串起来了。从三个主流数据库出发,经过API获取、数据清洗、数据标准化,最终得到一份可以直接用于机器学习或数据分析的干净数据集。

3.7 一些实用建议

最后,分享几个我在项目中积累的经验:

  • 先小批量测试:别一上来就拉百万级数据。先拿100条试试流程,确认没问题再全量拉取。
  • 保留原始数据:清洗后的数据要另存一份,原始数据别删。我吃过这个亏——清洗规则写错了,想回退发现原始数据已经被覆盖了。
  • 写日志:每次清洗操作都记录一下,比如删了多少条、改了哪些字段。这样出了问题好排查。
  • 版本控制:数据集也要做版本管理。我习惯用 dataset_v1.0.csvdataset_v1.1.csv 这样的命名方式。

一句话总结:数据清洗和标准化,占整个材料基因组学项目60%以上的工作量。别嫌烦,这一步做扎实了,后面的建模和分析才能顺风顺水。

好了,这一章的内容就到这里。记住:公开数据库是宝藏,但只有经过精心打磨的数据,才能真正驱动材料发现。

专注资料整理