mining,一个超 nice 的 Python 库!
mining,一个有点冷门但很顺手的 Python 库
矿山模型这种数据,第一眼看着就是普通表格:x、y、z、吨位、品位、矿种、台阶号。
真丢到 Pandas 里处理一轮就知道,不太一样。
普通业务表最多是订单、用户、时间戳。矿山块模型不一样,它有空间位置,有块尺寸,有旋转角度,还经常要按台阶、区域、品位区间重新聚合。你拿纯 Pandas 写,能写,但写到第三个脚本就开始烦。
这个时候 mining 就有点意思了。
准确点说,包名一般装的是 miningpy,它是给 mining engineering,也就是矿业工程场景用的 Python 工具。官方介绍里提到,它主要干块模型处理、ijk 索引、reblocking、旋转、模型校验、台阶储量、运输建模、可视化这些事,不是那种泛泛的数据挖掘库。PyPI 上当前能看到的版本是 0.6.4,安装方式也很普通:pip install miningpy。([PyPI][1])
pip install miningpy
我比较喜欢它的一点,是它没把自己包装成一个“大平台”。
很多工业软件的 Python SDK,一上来就是一堆对象、工程、会话、连接、许可证。你只是想看一下块模型,最后像是在启动半个桌面软件。
miningpy 这类库的思路更轻一点:数据还是你的 DataFrame,Python 生态还是原来的 Pandas、Numpy。它只是把矿山工程里那几个最容易写脏的动作补上。官方文档里也说,它希望扩展现有的数据科学工具,而不是让用户每次重新造轮子。([PyPI][1])
比如现场经常有这种 CSV:
x,y,z,ore,grade,tonnes,bench
125.0,560.0,320.0,1,0.82,240,320
125.0,570.0,320.0,1,0.76,235,320
135.0,560.0,310.0,0,0.21,260,310
我一般不会上来就画图,先查三件事:坐标有没有空、吨位有没有负数、同一块有没有重复。这个习惯比库本身重要。
import pandas as pd
import miningpy # 会给 DataFrame 扩展一些矿山模型相关能力raw = pd.read_csv("pit_block_model.csv")
need_cols = ["x", "y", "z", "ore", "grade", "tonnes", "bench"]
miss = [c for c in need_cols if c notin raw.columns]
if miss:
raise RuntimeError(f"块模型字段不全,缺字段: {miss}")
bad_rows = raw[
raw[["x", "y", "z", "grade", "tonnes"]].isna().any(axis=1)
| (raw["tonnes"] <= 0)
]
ifnot bad_rows.empty:
bad_rows.to_csv("bad_blocks.csv", index=False)
raise RuntimeError(f"模型里有脏块,先看 bad_blocks.csv,数量={len(bad_rows)}")
dup = raw.duplicated(subset=["x", "y", "z"], keep=False)
if dup.any():
raw.loc[dup].to_csv("dup_xyz_blocks.csv", index=False)
raise RuntimeError("同一坐标出现重复块,这个先别往下算")
这段代码没什么花活,但现场就靠这种东西少背锅。
尤其是块模型,最怕前面数据没查,后面储量报表一跑,吨位对不上。等业务问为什么 320 台阶多了几万吨,你再回头查 CSV,基本就是晚了。
校验完以后,可以先按台阶做一个很粗的储量表。这个不需要什么高级算法,Pandas 就够。
ore_blocks = raw[raw["ore"] == 1].copy()reserve = (
ore_blocks
.assign(metal=lambda d: d["grade"] * d["tonnes"])
.groupby("bench", as_index=False)
.agg(
blocks=("x", "count"),
tonnes=("tonnes", "sum"),
avg_grade=("metal", lambda s: s.sum() / ore_blocks.loc[s.index, "tonnes"].sum())
)
.sort_values("bench", ascending=False)
)
reserve.to_csv("bench_reserve_check.csv", index=False)
print(reserve.head(10))
这里我故意没有把代码写得太“智能”。
储量这类东西,我更愿意让中间文件落下来。bad_blocks.csv、dup_xyz_blocks.csv、bench_reserve_check.csv,这些文件看着土,但排查时真有用。比你在 notebook 里漂亮地画一张图,然后忘了中间过滤条件强。
miningpy 的可视化也适合做第一轮肉眼检查。官方示例里就是把块模型直接在 Python 里预览,支持按字段上色,也能预览 DXF 设计,甚至可以导出 ParaView 兼容格式。([PyPI][1])
sample = raw.query("bench >= 300 and bench <= 330").copy()sample["grade_band"] = pd.cut(
sample["grade"],
bins=[0, 0.3, 0.6, 1.0, 99],
labels=["waste_like", "low", "mid", "high"]
)
sample.plot3D(
xyz_cols=("x", "y", "z"),
dims=(10, 10, 10),
col="grade"
)
这一步主要不是为了“好看”。
我看这种图,第一眼会盯两个地方:有没有明显断层式空洞,边界有没有飘出去的孤块。前者可能是模型缺块,后者经常是坐标系、单位、旋转角度哪里没对上。这个时候别急着调图,先回到源数据查。
再补一个我自己常写的小脚本,专门查块模型边界。很多模型文件从商业软件导出来,字段名看着对,但坐标范围一眼不对。
defprint_model_frame(df: pd.DataFrame) -> None:
frame = {}
for axis in ["x", "y", "z"]:
frame[axis] = {
"min": float(df[axis].min()),
"max": float(df[axis].max()),
"count": int(df[axis].nunique())
}for axis, info in frame.items():
print(
f"{axis}: min={info['min']:.2f}, "
f"max={info['max']:.2f}, "
f"unique={info['count']}"
)
print_model_frame(raw)
如果 z 的范围突然从几十米变成几千米,或者 x/y 出现奇怪的负值,这种我第一反应不会怀疑 miningpy,也不会怀疑 Pandas。先怀疑导出坐标系,或者有人把局部坐标和全局坐标混在一起了。
这个库不适合所有人。
你要是做 Web 后端、推荐系统、普通数据分析,看到 miningpy 大概率用不上。它不是 scikit-learn 那种通用机器学习库,也不是所谓“数据挖掘大全”。
但如果你手上真有块模型、台阶储量、DXF、调度聚合、矿山软件导入导出这些东西,它就挺香。它把很多矿业工程里重复、别扭、容易写错的小动作,塞回了 Python 这条流水线里。
我对这类库的判断很简单:能不能减少 Excel 手工处理,能不能让中间结果可复查,能不能把图、表、校验放在一个脚本里跑完。
miningpy 至少踩中了这几个点。
真正上线用之前还有个提醒:PyPI 页面标的开发状态还是 Alpha,平台分类也偏 Windows,官方文档里还提到它主要测试在 Windows 环境下。别直接把它塞进生产批处理,先拿一份模型跑完整链路,尤其是 Linux 环境和 VTK 依赖,提前试。
库是 nice 的,但矿山数据不 nice。
先校验,再汇总,再画图。顺序别反。