当前位置:首页>python>教程 | Python 批量整理野外坐标,一键出规范成果

教程 | Python 批量整理野外坐标,一键出规范成果

  • 2026-10-11 07:01:12
教程 | Python 批量整理野外坐标,一键出规范成果

做完你能得到什么:把一份乱糟糟的野外坐标 Excel(点号、X/Y、高程、备注混在一起,还可能有重复点、空行、千分位逗号)一键整理成两种规范成果——坐标交换文件 CSV(直接进 CASS / 南方 / ArcGIS 展点)和点之记 Excel(归档、出图、交差都好用)。几百个点,几秒钟搞定,省掉半天复制粘贴。

适用人群:外业队长、测量员、国土变更调查作业人员,以及任何"手里有一堆坐标表要交差"的人。会装 Python、能在命令行敲几行命令即可,不需要会写代码——脚本已经写好,改个文件名就能跑。


一、准备清单

项目
说明
软件
Python 3.10+(本文在 3.13 实测通过)
第三方库
pandas ≥ 1.5
、openpyxl ≥ 3.0(仅这两个)
数据
野外手簿 / 记录表导出的 .xlsx,至少含 点号、X(纵/北)、Y(横/东)三列;高程 H、备注可选
环境
任意文件夹;脚本、输入表、输出文件放同一目录最省事

易错提醒(就地):输入表不要用"合并单元格"当点号(比如一个村名合并占 10 行)。脚本按"每行一个点"读取,合并单元格只有第一行有值,其余会变成空行被丢掉。先把点号拆成"每行一个"再导入。


二、操作步骤(逐条、可复现)

步骤 1 · 整理原始表,确认列名

  • 操作:Excel 打开野外表,确认至少有三列。列名随便叫,脚本认得这些别名:
    • 点号:点号 / 点名 / 序号 / 编号
    • X(纵坐标/北):X坐标(北) / 纵坐标 / 北坐标
    • Y(横坐标/东):Y坐标(东) / 横坐标 / 东坐标
    • 高程:高程H / 海拔 / Z;备注:备注 / 说明 / 地类
  • 预期结果:表头清晰,每行一个独立点,点号不重不空。
  • 📸 截图标注区块(待你上传):截 Excel 表头那几列,标注 ①点号列 ②X 列 ③Y 列 ④高程列 的位置,方便核对脚本能否自动识别。

步骤 2 · 建目录、放脚本

  • 操作:新建文件夹 坐标整理,把 野外坐标表.xlsx 和脚本 2026-08-13_坐标整理脚本.py 放进去。
  • 预期结果:目录里至少两个文件并列。
  • 易错提醒:路径、文件名不要含中文空格或全角括号,Windows 下偶尔抽风。用 坐标整理 这种纯英文/简单中文最稳。

步骤 3 · 修改脚本顶部配置(几乎不用动)

  • 操作:用记事本 / VS Code 打开脚本,看最上面几行:
    INPUT_FILE = ”野外坐标表.xlsx”

待整理的原始表

SHEET      = 0

工作表序号,0 = 第一个工作表

OUT_CSV    = "坐标交换文件.csv"

输出:坐标交换文件

OUT_DOC    = "点之记.xlsx"

输出:点之记

如果你的表不叫这个名、或数据在第二个 sheet,改这里即可。- **预期结果**:配置指向你的真实文件。- **易错提醒**:`SHEET` 从 **0** 开始数,第二个表是 `1`,不是 `2`。填错会读到空表。### 步骤 4 · 安装依赖- **操作**:在文件夹地址栏输入 `cmd` 回车,打开命令行,执行:```batpip install pandas openpyxl

(若已安装则跳过;提示权限问题可加 --user)

  • 预期结果:命令行滚过 Successfully installed pandas-... openpyxl-...。
  • 易错提醒:电脑上若同时有 Python2/3,用 python3 或 py -3 明确版本。装完用 python -c "import pandas, openpyxl" 不报错即成功。

步骤 5 · 运行脚本

  • 操作:同一命令行执行:
    python 2026-08-13_坐标整理脚本.py
  • 预期结果(控制台示例输出):
    [1] 读入原始行数:7,列名:['点号', 'X坐标(北)', 'Y坐标(东)', '高程H', '备注'][2] 识别到的列映射:{'id': '点号', 'x': 'X坐标(北)', 'y': 'Y坐标(东)', 'h': '高程H', 'memo': '备注'}[3] 去除空行后剩余:6 行[!] 警告:1 行的 X/Y 不是数字,已保留原文本并标'坐标异常':    点号 D004:X=见记录  Y=38545000.00[4] 坐标系粗判:疑似高斯投影(3°/6°带·CGCS2000/54/80)(如有疑问请人工核对)[!] 发现重复点号 1 个,保留首次出现:['D001'][5] 已写出坐标交换文件:坐标交换文件.csv(5 个点)[6] 已写出点之记:点之记.xlsx(5 个点)===== 整理报告 =====原始行数:7 -> 有效点:5重复点号已合并:1坐标异常行:1坐标系粗判:疑似高斯投影(3°/6°带·CGCS2000/54/80)输出文件:坐标交换文件.csv / 点之记.xlsx完成。
  • 易错提醒:看到 [!] 不用慌,那是脚本在替你兜底——空行、重复点、坐标非数字都会被自动处理并报告,不会中断运行。

步骤 6 · 检查两份成果

  • 坐标交换文件.csv:用 Excel 或记事本打开,应是 点号,点名,X,Y,H,备注 六列,已按点号排序、无重复、逗号千分位已去掉。
  • 点之记.xlsx:表头深蓝、奇偶行浅蓝间隔,含坐标系粗判结果;缺高程处显示"—"、缺备注显示"(待补)"。

步骤 7(进阶)· 改成你们单位的成果模板

  • 多数单位点之记有固定版式(含 通视、土质、埋石类型、点位略图)。脚本第 9 步 headers 和 vals 两处直接改文字与取值即可,比如把"点位描述/备注"换成你们字段。
  • 预期结果:产出直接贴合归档要求,不用二次手抄。

三、完整可运行脚本(已实测)

直接拿去用。逐行注释版如下:

# -*- coding: utf-8 -*-”””野外坐标表 -> 规范成果一键整理功能:把野外手簿 / 记录表导出的 Excel,整理成      ① 坐标交换文件 CSV      ② 点之记 Excel      ③ 控制台整理报告依赖:pandas, openpyxl用法:python 坐标整理.py   (同目录放一份 野外坐标表.xlsx)”””import pandas as pdimport reINPUT_FILE = ”野外坐标表.xlsx”# 待整理的原始表SHEET      = 0# 工作表序号,0 = 第一个工作表OUT_CSV    = ”坐标交换文件.csv”# 输出:坐标交换文件OUT_DOC    = ”点之记.xlsx”# 输出:点之记# ---- 1. 读取(先全按文本,避免 001 变 1、长数字变科学计数)----raw = pd.read_excel(INPUT_FILE, sheet_name=SHEET, dtype=str)print(f”[1] 读入原始行数:{len(raw)},列名:{list(raw.columns)}”)# ---- 2. 列名标准化(兼容各种叫法)----def find_col(columns, candidates):    ”””在列名里模糊匹配候选名,返回第一个命中的列名;都找不到返回 None”””    cols = [str(c) for c in columns]    for cand in candidates:        for c in cols:            if cand.lower() in c.lower():                return c    return NoneCOL = {    ”id”:   find_col(raw.columns, [”点号”, ”点名”, ”序号”, ”编号”, ”id”, ”name”]),    ”x”:    find_col(raw.columns, [”纵坐标”, ”北坐标”, ”north”, ”x坐标”, ”x”]),    ”y”:    find_col(raw.columns, [”横坐标”, ”东坐标”, ”east”, ”y坐标”, ”y”]),    ”h”:    find_col(raw.columns, [”高程”, ”海拔”, ”elev”, ”z”, ”h”]),    ”memo”: find_col(raw.columns, [”备注”, ”说明”, ”注释”, ”remark”, ”描述”, ”地类”]),}print(f”[2] 识别到的列映射:{COL}”)if not COL[”id”] or not COL[”x”] or not COL[”y”]:    raise SystemExit(”缺少关键列(点号 / 纵坐标X / 横坐标Y),请检查表头。”)# ---- 3. 提取并清洗 ----df = pd.DataFrame()df[”点号”] = raw[COL[”id”]].astype(str).str.strip()df[”点名”] = df[”点号”]df[”X”] = raw[COL[”x”]].astype(str).str.strip().str.replace(”,”, ””, regex=False)df[”Y”] = raw[COL[”y”]].astype(str).str.strip().str.replace(”,”, ””, regex=False)df[”H”] = raw[COL[”h”]].astype(str).str.strip().str.replace(”,”, ””, regex=False) if COL[”h”] else ””df[”备注”] = raw[COL[”memo”]].astype(str).str.strip() if COL[”memo”] else ””# 去掉点号为空/NaN 的行(Excel 空单元格读成 NaN,astype(str) 会变 'nan')df[”点号”] = df[”点号”].mask(df[”点号”].str.lower().isin([”nan”, ”none”, ”nat”]), ””)df = df[df[”点号”].str.len() > 0].reset_index(drop=True)print(f”[3] 去除空行后剩余:{len(df)} 行”)# ---- 4. 数值化与告警 ----df[”Xn”] = pd.to_numeric(df[”X”], errors=”coerce”)df[”Yn”] = pd.to_numeric(df[”Y”], errors=”coerce”)df[”Hn”] = pd.to_numeric(df[”H”], errors=”coerce”)bad = df[df[”Xn”].isna() | df[”Yn”].isna()]if len(bad) > 0:    print(f”[!] 警告:{len(bad)} 行的 X/Y 不是数字,已保留原文本并标'坐标异常':”)    for _, r in bad.iterrows():        print(f”    点号 {r['点号']}:X={r['X']}  Y={r['Y']}”)# ---- 5. 坐标系粗判(高斯公里网 vs 经纬度)----def guess_crs(x, y):    if pd.isna(x) or pd.isna(y):        return ”未知”# 经纬度:纬度(X)一般<90,经度(Y)一般<180    if abs(x) < 90 and abs(y) < 180:        return ”疑似经纬度(WGS84/GCJ02)”# 高斯坐标:X(北)=2.9e6~5.6e6,Y(东,带号+500km)=3.0e7~5.0e7    if 2.9e6 < abs(x) < 6e6 and 3.0e7 < abs(y) < 5.0e7:        return ”疑似高斯投影(3°/6°带·CGCS2000/54/80)”    return ”数值异常或自定义”crs = guess_crs(df[”Xn”].median(), df[”Yn”].median())print(f”[4] 坐标系粗判:{crs}(如有疑问请人工核对)”)# ---- 6. 去重(按点号,保留首次出现)----dups = df[df[”点号”].duplicated(keep=”first”)]if len(dups) > 0:    print(f”[!] 发现重复点号 {len(dups)} 个,保留首次出现:{list(dups['点号'])}”)df = df.drop_duplicates(subset=[”点号”], keep=”first”).reset_index(drop=True)# ---- 7. 点号自然排序(提取末尾数字)----def sort_key(s):    m = re.findall(r”\d+”, str(s))    return (0, 0) if not m else (len(str(s)), int(m[-1]))df[”_k”] = df[”点号”].apply(sort_key)df = df.sort_values(”_k”).drop(columns=[”_k”]).reset_index(drop=True)# ---- 8. 输出坐标交换文件 CSV ----csv_df = df[[”点号”, ”点名”, ”X”, ”Y”, ”H”, ”备注”]].copy()csv_df.to_csv(OUT_CSV, index=False, encoding=”utf-8-sig”)print(f”[5] 已写出坐标交换文件:{OUT_CSV}({len(csv_df)} 个点)”)# ---- 9. 输出点之记 Excel ----from openpyxl import Workbookfrom openpyxl.styles import Font, Alignment, PatternFill, Border, Sidewb = Workbook()ws = wb.activews.title = ”点之记”hdr_font = Font(name=”Microsoft YaHei”, bold=True, size=11)fill_head = PatternFill(”solid”, fgColor=”1F4E79”)fill_alt = PatternFill(”solid”, fgColor=”DDEBF7”)thin = Side(style=”thin”, color=”B0B0B0”)border = Border(left=thin, right=thin, top=thin, bottom=thin)headers = [”点号”, ”坐标(X 北)”, ”坐标(Y 东)”, ”高程 H”, ”点位描述/备注”, ”坐标系”]ws.append(headers)for c in range(1, len(headers) + 1):    cell = ws.cell(row=1, column=c)    cell.font = hdr_font    cell.fill = fill_head    cell.alignment = Alignment(horizontal=”center”, vertical=”center”)    cell.border = borderfor i, (_, r) in enumerate(df.iterrows(), start=2):    vals = [        r[”点号”],        r[”X”],        r[”Y”],        r[”H”] if r[”H”] != ”” else ”—”,        r[”备注”] if r[”备注”] != ”” else ”(待补)”,        crs,    ]    ws.append(vals)    for c in range(1, len(headers) + 1):        cell = ws.cell(row=i, column=c)        cell.border = border        cell.alignment = Alignment(horizontal=”left”, vertical=”center”)        if i % 2 == 0:            cell.fill = fill_altws.column_dimensions[”A”].width = 14ws.column_dimensions[”B”].width = 18ws.column_dimensions[”C”].width = 18ws.column_dimensions[”D”].width = 12ws.column_dimensions[”E”].width = 30ws.column_dimensions[”F”].width = 28wb.save(OUT_DOC)print(f”[6] 已写出点之记:{OUT_DOC}({len(df)} 个点)”)# ---- 10. 汇总报告 ----print(”\n===== 整理报告 =====”)print(f”原始行数:{len(raw)} -> 有效点:{len(df)}”)print(f”重复点号已合并:{len(dups)}”)print(f”坐标异常行:{len(bad)}”)print(f”坐标系粗判:{crs}”)print(f”输出文件:{OUT_CSV} / {OUT_DOC}”)print(”完成。”)

示例输入 → 输出(同一份脏数据,7 行原始 → 5 个有效点):

原始坑
处理结果
点号空行 1 行
自动丢弃
点号 D001 重复 1 次
去重保留首次
D002 的 3,854,200.10
千分位逗号清除 → 3854200.10
D004 的 X=见记录
标"坐标异常"保留原文本,不中断
全部点无坐标系标注
自动粗判"高斯投影(3°/6°带)"并写入点之记

四、关键步骤截图标注(汇总,待你上传截图)

  1. 步骤 1:Excel 表头,标 点号 / X / Y / 高程 列位置。
  2. 步骤 5:控制台输出,标 [!] 警告行与底部"整理报告"数字。
  3. 步骤 6:CSV 前几行 + 点之记 Excel 首屏,标 排序 / 缺值显示 / 坐标系列。

把对应软件截图发我,我按标注点帮你复核或改版式。


五、常见坑(按严重程度排序)

  1. 【严重】合并单元格当点号 → 只有首行有值,其余点被当空行丢弃。先"取消合并 + 向下填充"再导入。
  2. 【严重】Y 坐标带带号被误判 → 高斯 Y 是 3.0e7 量级(如 38541234),脚本已自动粗判;若你用的是"不带带号的 8 位 Y",粗判可能误报,请人工核对后改 guess_crs 的阈值。
  3. 【中等】千分位逗号 → 3,854,200.10 不处理会成文本。脚本已 str.replace(",","") 清除;但若是全角逗号 , 需自行替换。
  4. 【中等】点号重复 → 同一控制点测两次,CSV 会乱。脚本按点号去重保留首次,意味着第二次的修正高程被丢弃——重要点请先人工确认哪次为准。
  5. 【轻微】高程缺失 → 脚本留空显示"—",但成果表里高程为空可能影响后续平差,记得补。
  6. 【轻微】sheet 序号数错 → SHEET 从 0 开始,第二个表是 1。

最新文章

随机文章