前言

这两天帮一个朋友处理了些 nc 数据,本以为很简单的事情,没想到里面涉及到了很多的细节和坑,无论是“知难行易”还是“知易行难”都不能充分的说明问题,还是“知行合一”来的更靠谱些,既要知道理论又要知道如何实现,于是经过不太充分的研究后总结成此文,以记录如何使用 python 处理 nc 数据。

一、nc 数据介绍

nc 全称 netCDF(The Network Common Data Form),可以用来存储一系列的数组,就是这么简单(参考https://www.unidata.ucar.edu/software/netcdf/docs/netcdf_introduction.html)。

既然 nc 可以用来一系列的数组,所以经常被用来存储科学观测数据,最好还是长时间序列的。

试想一下一个科学家每隔一分钟采集一次实验数据并存储了下来,如果不用这种格式存储,时间长了可能就需要创建一系列的 csv 或者 txt 等,而采用 nc 一个文件就可以搞定,是不是很方便。

更方便的是如果这个科学实验与气象、水文、温度等地理信息稍微沾点边的,完全也可以用 nc 进行存储, GeoTiff 顶多能多存几个波段(此处波段可以认为是气象、水文等不同信号),而 nc 可以存储不同波段的长时间观测结果,是不是非常方便。

可以使用 gdal 查看数据信息,执行:

gdalinfo name.nc

即可得到如下信息:

Driver: netCDF/Network Common Data Format
Files: test.nc
Size is 512, 512
Coordinate System is `'
Subdatasets:
SUBDATASET_1_NAME=NETCDF:"test.nc":T2
SUBDATASET_1_DESC=[696x130x120] T2 (32-bit floating-point)
SUBDATASET_2_NAME=NETCDF:"test.nc":PSFC
SUBDATASET_2_DESC=[696x130x120] PSFC (32-bit floating-point)
SUBDATASET_3_NAME=NETCDF:"test.nc":Q2
SUBDATASET_3_DESC=[696x130x120] Q2 (32-bit floating-point)
SUBDATASET_4_NAME=NETCDF:"test.nc":U10
SUBDATASET_4_DESC=[696x130x120] U10 (32-bit floating-point)
SUBDATASET_5_NAME=NETCDF:"test.nc":V10
SUBDATASET_5_DESC=[696x130x120] V10 (32-bit floating-point)
SUBDATASET_6_NAME=NETCDF:"test.nc":RAINC
SUBDATASET_6_DESC=[696x130x120] RAINC (32-bit floating-point)
SUBDATASET_7_NAME=NETCDF:"test.nc":SWDOWN
SUBDATASET_7_DESC=[696x130x120] SWDOWN (32-bit floating-point)
SUBDATASET_8_NAME=NETCDF:"test.nc":GLW
SUBDATASET_8_DESC=[696x130x120] GLW (32-bit floating-point)
SUBDATASET_9_NAME=NETCDF:"test.nc":LAT
SUBDATASET_9_DESC=[130x120] LAT (32-bit floating-point)
SUBDATASET_10_NAME=NETCDF:"test.nc":LONG
SUBDATASET_10_DESC=[130x120] LONG (32-bit floating-point)
Corner Coordinates:
Upper Left ( 0.0, 0.0)
Lower Left ( 0.0, 512.0)
Upper Right ( 512.0, 0.0)
Lower Right ( 512.0, 512.0)
Center ( 256.0, 256.0)

每一个 SUBDATASET 表示记录的是一种格式的数据(气象、水文等等),如果要想查看此 SUBDATASET 的具体信息,可以执行:

gdalinfo NETCDF:name.nc:SUBDATASET_NAME

此处的 SUBDATASET_NAME 为上面的 T2、PSFC 等等,可以得到如下信息:

Driver: netCDF/Network Common Data Format
Files: test.nc
Size is 120, 130
Coordinate System is `'
Metadata:
LAT#description=LATITUDE, SOUTH IS NEGATIVE
LAT#FieldType=104
LAT#MemoryOrder=XY
LAT#stagger=
LAT#units=degree_north
Corner Coordinates:
Upper Left ( 0.0, 0.0)
Lower Left ( 0.0, 130.0)
Upper Right ( 120.0, 0.0)
Lower Right ( 120.0, 130.0)
Center ( 60.0, 65.0)
Band 1 Block=120x1 Type=Float32, ColorInterp=Undefined
NoData Value=9.96920996838686905e+36
Unit Type: degree_north
Metadata:
description=LATITUDE, SOUTH IS NEGATIVE
FieldType=104
MemoryOrder=XY
NETCDF_VARNAME=LAT
stagger=
units=degree_north

此处只有一个 Band ,每一个 Band 记录了一个时间点(或者其他区分形式)的一条记录,这个记录是一个数组。

所以看到这里,各位应该已经明白了,可以直接使用 GDAL 处理 nc 数据,比如直接使用 gdalwarp 将某个 SUBDATASET 转成 GeoTiff 等等,此处暂且不表,各位只需要查阅一下 gdalwarp 手册即可知道如何处理。

明白了以上信息基本也就清楚了如何处理此数据。

二、数据处理

python 是运用非常广泛,自然其下各种类库非常丰富,专业一点的说法就叫生态丰富。

2.1 netCDF4

此框架可以直接将 nc 读取成数组(详细信息参考https://github.com/Unidata/netcdf4-python)。读取方式如下:

dataset = netCDF4.Dataset('name.nc')  # open the dataset

这样即可读出整个 nc 中的数据信息,如果需要获取某个 SUBDATASET 只需要使用 dataset[SUBDATASET_NAME] 即可,返回的是一个三维数组,表示不同时间段(或其他区分方式下)的数据信息。

我们可以对此数组做各种操作,如求平均值、方差等等,又让我想起了大学里的那一堆枯燥但又让人很有兴趣的实验课程。当然,此处如果使用 numpy 框架进行处理,会起到事半功倍的效果,如求长时间序列下的平均值:

np_arr = np.asarray(dataset[SUBDATASET_NAME])
average_arr = np.average(np_arr, axis=0)

到这里跟地信有关的同志都会看出一个问题,此框架只能对数据进行处理,而不能进行与位置有关的操作,这就导致数据无法变成直白的地图可视化效果。其实任何数据都是相通的,我们可以采用此种方式处理完后转为 GeoTiff 等,当然我们也可以直接采用 GeoTiff 的处理流程来进行处理。

2.2 rasterio

rasterio 是 Mapbox 开源的空间数据处理框架,功能非常强大,此处不细说,只表如何处理我们的 nc 数据。

当然第一种方式就是使用 netCDF4 处理完之后,使用此框架写入 GeoTiff,但是这样不太优雅,而且使用了两个框架,明显过于麻烦,我们直接使用此框架从读数据开始处理。

此处读的时候就有技巧了,要像采用 gdalinfo 读取 SUBDATASET 一样来直接读取此 SUBDATASET 数据,如下:

with rio.open('NETCDF:name.nc:SUBDATASET_NAME') as src:
print(src.meta)
dim = int(src.meta['count'])
src.read(range(1, dim + 1))

即给 open 函数传入 NETCDF:name.nc:SUBDATASET_NAME,采用 src.read(range(1, dim + 1)) 可以直接读出此范围内所有 Band (时间点)的信息,范围可以自己设定,注意从 0 开始,当然也可以仅读取某个 Band 的信息。

src.meta 记录了此 SUBDATASET 的元数据信息,与 gdalinfo 看到的基本相同。

这样我们就可以继续将此数据使用 numpy 等框架进行处理,处理完之后更重要的是要写入 GeoTiff 中(直白的说就是添加空间信息)。

也很简单,如下即可:

with rio.open(newfile, 'w', **out_meta) as dst:
dst.write_band(1, res_arr)

newfile 为存储路径,res_arr 为计算结果数组,注意尺寸不要发生变化(width*height),out_meta 为目标文件的元数据描述信息,可以直接将上面 src.meta 进行简单处理即可。

out_meta =
meta.update({"driver": "GTiff",
"dtype": "float32",
'count': 1,
'crs': 'Proj4: +proj=longlat +datum=WGS84 +no_defs',
'transform': rasterio.transform.from_bounds(west, south, east, north, width, height)
})

crs 表示目标数据空间投影信息,transform 表示目标文件 空间范围信息,可以通过经纬度信息和图像尺寸等计算得到。

dst.write_band 将数据写入对应波段,当然此处也可以写入多个波段,根据计算结果而定,同样从 1 开始。

三、总结

本文简单介绍了 nc 数据的特点及如何使用 python 处理 nc 数据。每个目标都有多条路可以达到,重要的是找到那条自己喜欢的和适合自己的路,然而话又说回来,即使走的不是想要的那条路,不是一样可以达到目标嘛!所以关键是要找到自己的目标。

使用 python 处理 nc 数据的更多相关文章

  1. 使用Python解析JSON数据的基本方法

    这篇文章主要介绍了使用Python解析JSON数据的基本方法,是Python入门学习中的基础知识,需要的朋友可以参考下:     ----------------------------------- ...

  2. python matplotlib plot 数据中的中文无法正常显示的解决办法

    转发自:http://blog.csdn.net/laoyaotask/article/details/22117745?utm_source=tuicool python matplotlib pl ...

  3. Python/Numpy大数据编程经验

    Python/Numpy大数据编程经验 1.边处理边保存数据,不要处理完了一次性保存.不然程序跑了几小时甚至几天后挂了,就啥也没有了.即使部分结果不能实用,也可以分析程序流程的问题或者数据的特点.   ...

  4. Windows下Python读取GRIB数据

    之前写了一篇<基于Python的GRIB数据可视化>的文章,好多博友在评论里问我Windows系统下如何读取GRIB数据,在这里我做一下说明. 一.在Windows下Python为什么无法 ...

  5. 为什么说Python 是大数据全栈式开发语言

    欢迎大家访问我的个人网站<刘江的博客和教程>:www.liujiangblog.com 主要分享Python 及Django教程以及相关的博客 交流QQ群:453131687 原文链接 h ...

  6. 用Python浅析股票数据

    用Python浅析股票数据 本文将使用Python来可视化股票数据,比如绘制K线图,并且探究各项指标的含义和关系,最后使用移动平均线方法初探投资策略. 数据导入 这里将股票数据存储在stockData ...

  7. Python读取JSON数据,并解决字符集不匹配问题

    今天来谈一谈Python解析JSON数据,并写入到本地文件的一个小例子. – 思路如下 从一个返回JSON天气数据的网站获取到目标JSON数据串 使用Python解析出需要的部分 写入到本地文件,供其 ...

  8. 【转】Python——plot可视化数据,作业8

    Python——plot可视化数据,作业8(python programming) subject1k和subject1v的形状相同 # -*- coding: utf-8 -*- import sc ...

  9. [Python] Python 学习 - 可视化数据操作(一)

    Python 学习 - 可视化数据操作(一) GitHub:https://github.com/liqingwen2015/my_data_view 目录 折线图 散点图 随机漫步 骰子点数概率 文 ...

随机推荐

  1. GraphCuts算法解析,Graphcuts算法求最大流,最小割实例

    图割论文大合集下载: http://download.csdn.net/detail/wangyaninglm/8292305 代码: /* graph.h */ /* Vladimir Kolmog ...

  2. Java中的50个关键字

    form:http://blog.csdn.net/luoweifu/article/details/6776240 Java中的50个关键字 关键字也称为保留字,是指java语言中规定了特定含义的标 ...

  3. C 实现基于角色的权限系统

    本文demo下载地址:http://www.wisdomdd.cn/Wisdom/resource/articleDetail.htm?resourceId=1068 实例使用C# 实现基于角色的权限 ...

  4. C++的拷贝构造函数、operator=运算符重载,深拷贝和浅拷贝、explicit关键字

    原文地址:https://blog.csdn.net/shine_journey/article/details/53081523 1.在C++编码过程中,类的创建十分频繁. 简单的功能,当然不用考虑 ...

  5. HashMap在高并发下如果没有处理线程安全会有怎样的安全隐患,具体表现是什么

    Hashmap在并发环境下,可能出现的问题: 1.多线程put时可能会导致get无限循环,具体表现为CPU使用率100%: 原因:在向HashMap put元素时,会检查HashMap的容量是否足够, ...

  6. 八爪鱼在哪里设置xpath

    分享:35个做好的爬虫规则+160篇图文教程汇总 一般在八爪鱼中,获取网页上某个元素的XPATH有以下几种方式:一.在内置浏览器中点选的操作,八爪鱼自动识别XPATH.但是有时候,自动识别的可能不准确 ...

  7. zlib 压缩输出缓冲区 overflow 问题

    [TOC] 问题 后台服务传包太大时,我们框架可以使用 zlib 库对响应进行压缩:在这次服务调试过程中,使用 zlib compress2 以 Z_BEST_COMPRESSION 模式进行压缩时, ...

  8. 《T-SQL查询》读书笔记Part 2.执行计划

    一.关于执行计划 执行计划是优化器生成的用于确定如何处理一个给定查询的“工作计划”.一个计划包含一组运算符,通常按照特定的顺序来应用这些运算符.此外,一些运算符可以在它们之前的运算符还在处理时被应用( ...

  9. Python_字符串简单加密解密

    def crypt(source,key): from itertools import cycle result='' temp=cycle(key) for ch in source: resul ...

  10. Egg Dropping Puzzle问题的分析

    首先,基本问题是这样:You are given two eggs, and access to a 100-storey building. The aim is to find out the h ...