ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

气象日值数据V3.0处理:VS2019编译到站点shp关联全流程

气象日值数据V3.0处理:VS2019编译到站点shp关联全流程 简介面向需要从中国地面气候资料日值数据集(V3.0)中批量提取气温、降水要素的科研人员与气象爱好者这份工具包提供了一体化处理方案C#编写的处理软件可快速将日值数据转换为月/年平均或总量并支持选择输出类型。软件基于VS2019开发压缩包内含可直接运行的exe、完整源码及工程配置.sln/.csproj/config/json开发者可自由修改算法或扩展其他气象要素同时附带的全国气象站点矢量数据覆盖全部站点提供shp、shx、dbf、prj等标准GIS格式便于在ArcGIS/QGIS中直接加载、配准和空间分析。包内使用说明书docx和文本说明详细讲解了输入路径的配置方式默认对应C:\Users\Lenovo\Downloads\v3.0下的两个年份文件夹可大幅降低上手门槛。整个资源共41个文件仅239KB轻巧紧凑已有1055人学习下载。无论是做气候统计、地图制图还是教学演示这套工具都能省去繁琐的数据清洗环节直接产出可用的研究成果兼具实用性与可维护性。1. 从拿到压缩包到跑出第一份 CSV为什么 VS2019 和站点矢量数据会卡住绝大多数人搞气象评估、农业区划或者写论文的人下载到“中国地面气候资料日值数据集(V3.0)处理软件”之后通常会被两步卡死第一步是软件只给工程源码要求至少 VS2019 才能编译很多人装的是 VS2022 或者干脆没装 C 桌面组件第二步是终于跑通后发现输出的结果表和“全国气象站点矢量数据”对不上号——站号前导零丢了、经纬度差出几公里、站名字段乱码。这篇笔记按一次完整落地的顺序来先讲清 V3.0 日值数据和站点 shp 的结构关系再给 VS2019 下编译并运行处理软件的最小操作然后把 CSV 和全国气象站点矢量数据做空间关联最后整理五条踩坑记录和一份按月批处理的进阶方案。适合预报员、GIS 工程师和需要自行处理气象数据的研究生参考。2. V3.0 日值数据集的结构先弄清楚 TXT 里的“压缩整数”与站点矢量数据怎么互认2.1 每个日值 TXT 里到底装着什么要素列、编码单位与质控标志位的关系中国地面气候资料日值数据集(V3.0)对外分发时并不是给你一份干净的 Excel 表而是按站点和要素打包好的文本文件。最常见的组织方式是一个站点一个文件或者一个省区多个站点合并到一个文件文件名前缀形如 SURF_CLI_CHN_MUL_DAY后面跟着区域号、年月信息偶尔也有按要素单独拆分的文件。这些文件的正文每一行代表一个站某一天的观测记录列上依次是区站号、年、月、日然后是“要素值 质控标志位”的交替序列。有的文件只放单要素有的把气温、降水、风速、日照等多个要素交错排列处理软件就是要按固定的列顺序把它们切开并重组。区站号是这批数据最关键的主键。气象台站在全国站网里的编号是五位数例如南京的 58238、上海的 58362在“全国气象站点矢量数据”的 shp 属性表里也维护着同一个五位区站号。只要这两个主键能稳定对上后续空间分析才有意义。很多新人没有意识到原始 TXT 里的区站号是以文本形式存储的部分不规范的导出会把 00582 这种带前导零的站号写成 582Excel 打开时进一步把前导零抹掉导致与 shp 匹配时整表横断。这个问题我后面专门有一节来展开解决。处理软件做的事可以拆成两件。第一把 V3.0 文本里以整数编码保存的气象值还原成真实观测值。本数据集大部分要素采用 0.1 倍率编码例如原始值 37 表示 3.7 摄氏度108 表示 10.8 毫米降水量2147 表示 214.7 hPa 平均气压。不同要素的倍率稍有差别不能一概而论见下表。要素变量名编码倍率解码后单位平均气温TEM×0.1℃最高气温MAX×0.1℃最低气温MIN×0.1℃降水量PRE×0.1mm平均风速WIN×0.1m/s日照时数SSD×0.1h平均气压PRS×0.1hPa第二件事是切分数值与其紧随其后的质控码。质控标志位是本数据集区别于 V2.0 的核心之一0 表示数据通过质检、1 表示可疑、2 表示错误或已经过修正。如果处理软件在导出 CSV 时把质控码一并写出后续统计时还能补救如果直接丢弃你面对的就是一份无法辨别真假的时间序列。个人建议无论做气候平均还是极端事件分析一律保留质控码列导出后再按业务需要筛选。2.2 台站参数文件、月值文件与站点 shp三套文件里的经纬度和海拔为什么对不上和日值数据一起下载的通常还有一份台站参数文件文件里一行一个站字段按“区站号、站名、省份、纬度、经度、观测场海拔、气压传感器海拔”排列其中经纬度大多以十进制度存储。全国气象站点矢量数据的属性表里同样有站号、站名、经纬度、海拔字段而且因为来源不同两套坐标会出现小数点后第四位不一致的情况这在几公里尺度上是能察觉的。我的经验是空间位置一律以 shp 属性表为准日值数据里的经纬度只用于抽样核对不参与地图制图。坐标还有一个容易被忽略的单位差异。部分台站参数文件是从老数据库转换来的经纬度列的历史版本曾使用“度分”混合格式或者“整数度 × 100”的压缩格式。比如 116.28°N 可能被存成 11628如果不经过处理软件换算直接当十进制度用站点就会离真实位置几百公里。处理软件在输出阶段会把统一格式的十进制度写进结果我建议拿到结果后先抽查上海、北京、广州三个知名站点确认纬度落在预期范围内再继续。海拔字段同样有坑。观测场海拔表示气象站地坪高度气压传感器海拔表示测量气压表所在的高度二者差几米到几十米不等。做地面温度分析时用哪个影响不大但做气压订正或者高空观测对比时取错列会导致系统性偏差。全国气象站点矢量数据里通常只保留一个海拔值需要和台站参数文件做逐站比对后才能混用。编码问题也是三套文件互认时的重灾区。shp 属性表的 DBF 部分默认采用 GBK 或 GB2312 存储中文站名而处理软件输出的 CSV 往往按 UTF-8 编码在 QGIS 里两者分开打开都正常一旦用 Python 的 pandas 合并一边按默认编码读、一边按 gbk 读就会出现乱码。我统一的做法是处理软件输出 UTF-8 带 BOM 的 CSVpython 读 CSV 时用 encodingutf-8-sig读 shp 时显式传入 encodinggbk两边站名才能都对上。3. 用 VS2019 编译并运行处理软件从源码到跑通第一个日值 TXT 文件3.1 安装 VS2019 与打开工程v142 工具集缺失是最常见的编译失败原因标题里特意写“需要至少配备 VS2019”潜台词是这批源码里用到了较新的 C 标准语法VS2017 的 v141 工具集很可能编译不过。安装 VS2019 时有个容易踩空的环节默认安装不含“使用 C 的桌面开发”工作负载你要在 Visual Studio Installer 里手动勾选它同时选上 Windows 10 SDK 和 MSVC v142 构建工具。如果之前只装过 VS2022也别急着卸先尝试用 VS2019 打开 .sln在解决方案资源管理器里右键工程进入“属性 → 常规 → 平台工具集”把它改回 Visual Studio 2019 (v142)。命令行编译是我一贯推荐的方式因为输出信息比 IDE 完整报错定位也直接。先调用 VS2019 自带的开发环境初始化脚本再执行 msbuildcall C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\VsDevCmd.bat -archx64 msbuild 日值V3.0处理软件.sln /p:ConfigurationRelease /p:Platformx64 /m第一行命令把编译所需的 cl.exe、link.exe 和 include 路径全部注入当前终端-archx64 指定生成 64 位程序如果你装的 VS2019 是 Professional 或 Enterprise路径里的 Community 要替换成对应目录名。第二行的 /m 参数表示多进程并行编译能显著缩短时间/p:ConfigurationRelease 和 /p:Platformx64 必须与后续运行版本保持一致避免出现 Debug 版编译、Release 版运行的混乱情况。如果 msbuild 报错“MSB8020 找不到 v142 生成工具”多数原因是这台机器只装了 VS2022需要在 IDE 中手动切换工具集后再试。编译生成的 exe 通常在 x64\Release 目录下。这里有个提醒exe 的动态链接依赖 VC 运行库换一台机器运行时需要安装 vc_redist.x64.exe否则会报“缺少 VCRUNTIME140.dll”。把工程属性里“C/C → 代码生成 → 运行库”改成“多线程(/MT)”可以做到静态链接把运行库打进展 dir 里部署起来省心很多但要求所有代码模块没有 MFC 依赖否则依然要带 MFC 动态库。3.2 最小可运行配置用配置文件把原始目录、站点参数、输出规则一次性说清楚很多处理软件版本要求输入一个配置文件来指定工作参数。这是我常用的一个最小配置模板[输入] ; 原始日值 TXT 文件所在目录注意不要有中文路径 原始目录D:\ClimateData\SURF_CLI_CHN_MUL_DAY ; 台站参数文件路径用于输出经纬度和海拔 站参数文件D:\ClimateData\台站参数.txt [输出] ; 转换结果的 CSV 输出目录 输出目录E:\Processed ; 1 表示剔除质控码为 2 的错误数据0 表示全部保留 剔除错误1 ; 输出站号补零位数5 表示统一保留 5 位站号 站号补零5 ; 输出编码0 为 UTF-81 为 GBK 输出编码0这段配置的逻辑并不复杂程序启动后先读 [输入] 段定位原始数据和台站参数然后遍历原始目录里的 TXT把每个站逐日记录按 0.1 倍率还原再按 [输出] 段的规则裁剪质控码和补零。关键参数是“剔除错误”和“站号补零”。“剔除错误”这个开关要看你做什么做长期气候平均时我一般开启因为质控码 2 的数据已经是确证错误但分析台风、寒潮等极端过程时有时可疑数据反而记录了真实极端天气我会关闭剔除开关把质控码列导出后人工核查。“输出编码”选 UTF-8 是给 Python 用的选 GBK 是给 ArcGIS 的属性连接直接读取用的两者不要混。程序跑完后输出目录里会多出若干 CSV 文件命名格式类似 58238_2020_TEM.csv代表 58238 站 2020 年平均气温逐日序列。如果你下载的是多要素混合文件输出可能是 58238_2020.csv每个文件的列里同时包含 PRES、TEM、RHU、PRE 等字段筛选列时注意区分。第一次跑完不要急着做统计先打开 CSV 抽查第一年和最后一年的数据行对照原始 TXT 里同一日期、同一要素的编码值验证倍率换算有没有出问题。4. 让处理结果和“全国气象站点矢量数据”对得上属性关联、投影检查与 WKT 导出4.1 基于区站号的左关联pandas 和 geopandas 的组合操作处理软件产出的 CSV 通常是纯属性表没有几何信息全国气象站点矢量数据则是带经纬度的面或点图层。把两者合成一份可用于绘图或空间统计的数据时标准动作是以区站号为主键做左关联。用站名关联要尽量避免全国站名有重名现象缩写规则也不统一五位数站号才是唯一主键。写一段可以直接跑的 Python内置了对前导零和编码的防御import pandas as pd import geopandas as gpd df pd.read_csv(58238_2020_TEM.csv, dtype{站号: str}) df[站号] df[站号].str.zfill(5) gdf gpd.read_file(全国气象站点矢量数据.shp, encodinggbk) gdf[站号] gdf[站号].astype(str).str.zfill(5) merged gdf.merge(df, on站号, howleft) print(merged.crs) print(merged.head())这段代码的要点是read_csv 用 dtype 显式把站号读成字符串而不是数字防止 58238 这类站号被 read_csv 自动转成 int64 丢掉str.zfill(5) 会把“58238”左侧补零到 5 位即使原始站号在某个环节被写成“8238”也能恢复gdf 读取时指定 encodinggbk避免中文站名乱码。merge 完成后的 merged 是 GeoDataFrame可以继续做空间分析。注意 geopandas 依赖 GDAL 环境建议通过 conda 安装 geopandas而不是手动 pip 装底层库。如果你的分析不需要空间操作只想把 CSV 关联到站点的经纬度坐标也可以用普通 pandas 读取两个 CSV 后 merge稍微快一些。如果日值数据量很大比如你要关联近 30 年全国两千多个站的逐日数据merge 结果会有几百万行在 GIS 里做属性连接必然卡死。我会先把日值按月聚合为月平均或月累计再和 shp 关联要是仍然太大就改用数据库把 CSV 灌进 SQLite 或 PostgreSQL用结构化查询完成关联而不是在内存里死磕。4.2 空间自检三步走用抽查、距离计算和投影统一来排查错位关联只是第一步位置对不对需要验证。我总结了三步自检法。第一步抽查知名站点。依次打印北京54511、上海58362、拉萨55591三个站点的经纬度和手头已知值比对误差超过 0.02 度就要警惕。第二步计算距离。在 geopandas 里先用样条函数把两套坐标系投影到同一基准然后计算 CSV 里的经纬度到 shp 点位的距离import pandas as pd import geopandas as gpd from shapely.geometry import Point gdf_xy gpd.GeoDataFrame( merged, geometry[Point(x, y) for x, y in zip(merged[原始经度], merged[原始纬度])], crsEPSG:4326, ) gdf_xy gdf_xy.to_crs(EPSG:32650) gdf_base gdf.copy() gdf_base gdf_base.to_crs(EPSG:32650) merged[偏移距离_m] gdf_xy.geometry.distance(gdf_base.geometry) print(merged[[站号, 偏移距离_m]].describe())这里把两套经纬度都先统一到 WGS84 的 EPSG:4326 再投影到 UTM 50NEPSG:32650计算平面距离。如果全国绝大多数站点偏移在 100 米以内说明 CSV 经纬度与 shp 一致如果出现几千到上百公里的偏移通常是投影单位没换算或者 CSV 里留存了“度分”格式的经纬度需要回到第 2 章的倍率检查。第三步处理投影不一致。当 shp 的 crs 是 CGCS2000而 CSV 的经纬度基于 WGS84 时在 QGIS 里开启 OTF 实时投影看不出问题但导出到某些离线服务就会错位。做法是给 gdf 指定正确的初始 crs再用 to_crs 转成目标坐标。有把数据送给第三方做 Web 可视化需求的朋友顺带可以把几何转成 WKT 字符串避免对方手边没有 shp 文件merged 里的 geometry 列直接调 to_wkt() 导出即可一行代码就能拿到经纬度、站名、要素值全部躺在同一张 CSV 里的结果。5. 避坑处理软件与站点矢量数据最容易翻车的 5 个细节5.1 软件运行层面的坑运行库、中文路径与前导零丢失现象VS2019 编译成功后把 exe 复制到另一台电脑双击弹出“找不到 VCRUNTIME140.dll”或“MSVCP140.dll”。原因exe 动态链接了 VC 运行库目标机器没有装对应版本的运行库还有一种情况是编译时选了 Debug 配置Debug 运行库默认不随系统分发。解决统一编译成 Release x64并在目标机器安装 vc_redist.x64.exe。如果要长期在多台机器部署在工程属性里把运行库设为“多线程(/MT)”让运行库静态链接进 exe部署时不再依赖系统运行库。现象软件能编译但运行时读不到数据文件程序退出码是 0输出目录里没有任何 CSV。原因数据路径里带了中文比如“D:\气象数据\”而处理软件内部采用 ANSI 代码页的文件操作函数读取路径在某些 Windows 区域设置下无法识别中文路径。这种现象非常隐秘往往和你系统区域切换有关属于最调皮的一类玄学问题。解决把原始数据、输出目录一律放到纯英文字符路径下例如 D:\ClimateData。宁可让自己的目录名丑一点也绝不给编码问题留后门。现象处理软件输出的 CSV 用 Excel 打开区站号 00582 变成了 582所有前导零被静默删除。原因Excel 在打开无 BOM 的 CSV 时自动把纯数字列转为数值型前导零被当作无意义字符丢弃。这不是处理软件的 bug而是 Excel 自身的格式猜测行为。解决在输出阶段把区站号写成等长补零文本或在 CSV 里用带引号的方式包裹站号字段读取时在 pandas 里用 dtypestr 强制读为字符串再做 zfill(5)如果你只在 Excel 里用选中该列后设置“文本”格式再导入即可。5.2 数据关联层面的坑站名字段重名、质控码位偏移和经纬度误差现象用 pandas merge 按站号关联 CSV 和 shp 后整列全是 NaN一条有效记录都没剩下。原因两边站号字段的类型或字段名不一致。shp 属性表里的字段可能叫 Sta_IDCSV 里叫 Station_Id或者一边是文本一边是 int64merge 时主键匹配不上。解决在 merge 前先打印 df.columns 和 gdf.columns手动统一成同一个字段名再用 df[站号] df[站号].astype(str).str.zfill(5) 把两边都规范成五位数文本最后才执行 merge。现象处理软件按配置剔除质控码为 2 的记录后输出结果里仍然出现 -99.9 这类明显的缺失值占位符。原因部分老版本 TXT 中缺测值不是“无数据”而是用 -99.9、-9999 之类的特殊编码填充质控码本身可能是 0因此“剔除错误”规则管不到它。解决处理软件输出后再用一段清洗脚本把 -99.9、-9999、32766 这类极端占位符统一替换为空值并生成一列记录替换位置的标记列。不要直接删行因为这类记录还保留了日期信息删行会破坏时间序列的连续性。现象把 CSV 和 shp 叠到地图上发现站点整体向东南方向偏移约几百米到几十公里但各站相对位置形状没变。原因shp 的坐标系是 GCS_CGCS2000而 CSV 经纬度按 WGS84 存储两者虽然很接近却不完全重合如果偏移达到上千公里级别则是 CSV 经纬度未做“度/分”换算直接把“11628”当成了 116.28°。解决统一用 geopandas 先将 gdf 设置为其原始 crs再 to_crs 到目标坐标系对于不合理的经纬度数值用第 2 节的知名站点抽查法快速定位。现象用站名做关联统计时发现有的省站名完全不匹配明明看到的是同一个站。原因站名表里存在旧名、新名和别名。例如一些站点在 2005 年后更名shp 属性表更新滞后导致按站名 join 失败。解决一律不用站名做主键改用区站号。已经用站名 joining 过又出错的可以回到原始台站参数文件用旧站号反查新站名后再修正。6. 把逐站日值快速聚合成站点月值表一个可以反复用的落地框架当数据源有几百个站、三十年以上逐日记录时逐个点击处理软件图形界面是不现实的。我通常第一层交给处理软件做全目录批量转换第二层用 Python 把输出 CSV 批量读入并按站号、年、月聚合。下面这段代码把多年逐日温度、降水量转换成站点月值表直接可以和全国气象站点矢量数据 merge 出“月尺度站点空间表”import pandas as pd import glob csv_list glob.glob(rE:\Processed\*.csv) frames [] for f in csv_list: tmp pd.read_csv(f, dtype{站号: str}, encodingutf-8-sig) frames.append(tmp) df pd.concat(frames, ignore_indexTrue) df[站号] df[站号].str.zfill(5) df[年] df[日期].str[:4].astype(int) df[月] df[日期].str[5:7].astype(int) df[均温] pd.to_numeric(df[平均气温], errorscoerce) df[降水] pd.to_numeric(df[降水量], errorscoerce) month_table df.groupby([站号, 年, 月]).agg( 月平均气温(均温, mean), 月降水量(降水, sum), 有效天数(均温, count), ).reset_index() month_table.to_csv(站点_月值.csv, indexFalse, encodingutf-8-sig)这里的操作逻辑是glob 把输出目录中所有站的 CSV 都读进来concat 成一张全量长表然后按站号与年月分组。均值与求和分别是温度类、降水类要素的典型聚合方式有效天数这个统计项很值得保留它让你知道某个月份该站是否缺测超过阈值避免用一个月只观测几天的不完整资料去做气候统计。验证方法我有两个固定动作。第一个是取一个气候极稳的站比如用北京站把处理后的 1 月平均气温序列画成折线和公开的气候标准值1981—2010 年平均做对照偏差通常应小于 0.3℃如果出现整年整月的大幅偏差方向对但整体系统性高或低多半是倍率或质控规则设错了。第二个是随机抽三个站的手工抽查打开原始 TXT 核对某一日的温度编码值和 CSV 输出值是否一致。能通过这两项验证这批数据才能进入业务分析。我自己的血泪经验是处理这类数据永远不要相信“第一次就对了”每次都从一小批测试文件开始跑确认清晰后再放全量数据。挂上自动批处理之后也不能干等把质控码列和有效天数列一直留在表里做到什么时候都能追溯数据质量。希望这个从 VS2019 编译、日值转换、站点 shp 关联到月值聚合的完整流程能帮你在下一个研究季少走几趟弯路。本文还有配套的精品资源点击获取
返回列表