蓝光::
我在使用rasterstats包计算带有旋转数组的区域统计数据时遇到问题。我猜问题出在我的仿射矩阵上,但我不完全确定。下面是仿射变换矩阵和输出:
| 951.79, 0.45, 2999993.57|
| 0.00,-996.15,-1985797.84|
| 0.00, 0.00, 1.00|
背景:
我正在为地下水流模型创建文件,并且需要使用来自波多黎各农业水资源管理门户网站的一些 .csv 数据来计算每个模型网格单元的区域统计数据。这些数据可用于许多参数(例如 ET、tmax、tmin、precip 等)的每日时间步长。这些文件没有地理参考,但是可以使用辅助文件来指定每个单元格的经度/纬度,然后可以使用以下方式进行投影pyproj
:
import pandas as pd
import numpy as np
import pyproj
url_base = 'http://academic.uprm.edu/hdc/GOES-PRWEB_RESULTS'
# Load some data
f = '/'.join([url_base, 'actual_ET', 'actual_ET20090101.csv'])
array = pd.read_csv(f, header=None).values
# Read longitude values
f = '/'.join([url_base, 'NON_TRANSIENT_PARAMETERS', 'LONGITUDE.csv'])
lon = pd.read_csv(f, header=None).values
# Read latitude values
f = '/'.join([url_base, 'NON_TRANSIENT_PARAMETERS', 'LATITUDE.csv'])
lat = np.flipud(pd.read_csv(f, header=None).values)
# Project to x/y coordinates (North America Albers Equal Area Conic)
aea = pyproj.Proj('+init=ESRI:102008')
x, y = aea(lon, lat)
在计算区域统计数据之前,我需要创建将行/列坐标与投影 x/y 坐标相关联的仿射变换。我指定 6 个参数来Affine
使用仿射库创建对象:
import math
from affine import Affine
length_of_degree_longitude_at_lat_mean = 105754.71 # 18.25 degrees via http://www.csgnetwork.com/degreelenllavcalc.html
length_of_degree_latitude_at_lat_mean = 110683.25 # 18.25 degrees via http://www.csgnetwork.com/degreelenllavcalc.html
# Find the upper left x, y
xul, yul = aea(lon[0][0], lat[0][0])
xll, yll = aea(lon[-1][0], lat[-1][0])
xur, yur = aea(lon[0][-1], lat[0][-1])
xlr, ylr = aea(lon[-1][-1], lat[-1][-1])
# Compute pixel width
a = abs(lon[0][1] - lon[0][0]) * length_of_degree_longitude_at_lat_mean
# Row rotation
adj = abs(xlr - xll)
opp = abs(ylr - yll)
b = math.atan(opp/adj)
# x-coordinate of the upper left corner
c = xul - a / 2
# Compute pixel height
e = -abs(lat[1][0] - lat[0][0]) * length_of_degree_latitude_at_lat_mean
# Column rotation
d = 0
# y-coordinate of the upper left corner
f = yul - e / 2
affine = Affine(a, b, c, d, e, f)
在哪里:
- a = 像素宽度
- b = 行旋转(通常为零)
- c = 左上像素左上角的 x 坐标
- d = 列旋转(通常为零)
- e = 像素的高度(通常为负)
- f = 左上角像素的左上角的 y 坐标
(来自https://www.perrygeo.com/python-affine-transforms.html)
生成的仿射矩阵看起来很合理,我尝试将行和列旋转作为弧度和度数传递,结果几乎没有变化。链接到网格特征:grid_2km.geojson
import rasterstats
import matplotlib.pyplot as plt
grid_f = 'grid_2km.geojson'
gdf = gpd.read_file(grid_f)
zs = rasterstats.zonal_stats(gdf,
array,
affine=affine,
stats=['mean'])
df = pd.DataFrame(zs).fillna(value=np.nan)
fig = plt.figure(figsize=(14, 6))
ax = fig.add_subplot(131, aspect='equal')
ax.pcolormesh(x, y, np.zeros_like(array))
ax.pcolormesh(x, y, array)
ax.set_title('Projected Data')
ax = fig.add_subplot(132, aspect='equal')
gdf.plot(ax=ax)
ax.set_title('Projected Shapefile')
ax = fig.add_subplot(133, aspect='equal')
ax.imshow(df['mean'].values.reshape((gdf.row.max(), gdf.col.max())))
ax.set_title('Zonal Statistics Output')
plt.tight_layout()
plt.show()
此外,使用仿射对象转换的 x、y 值对与使用 来自本机 lon、lat 值的值对之间存在差异pyproj
:
rr = np.array([np.ones(x.shape[1], dtype=np.int) * i for i in range(x.shape[0])])
cc = np.array([np.arange(x.shape[1]) for i in range(x.shape[0])])
x1, y1 = affine * (cc, rr)
fig = plt.figure(figsize=(14, 6))
ax = fig.add_subplot(111, aspect='equal')
ax.scatter(x, y, s=.2)
ax.scatter(x1, y1, s=.2)
plt.show()