利用矢量邊界提取.nc數據
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import seaborn as sns
import geopandas as gpd
import earthpy as et
import xarray as xr
# .nc文件的空間切片包
import regionmask
# 繪圖選項
sns.set(font_scale=1.3)
sns.set_style("white")
讀取數據
data_path_monthly='http://thredds.northwestknowledge.net:8080/thredds/dodsC/agg_macav2metdata_tasmax_BNU-ESM_r1i1p1_rcp45_2006_2099_CONUS_monthly.nc'
with xr.open_dataset(data_path_monthly) as file_nc:
monthly_forecast_temp_xr=file_nc
monthly_forecast_temp_xr
讀取感興趣區的Shapefile文件
# 下載數據
# et.data.get_data(
# url="https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/50m/cultural/ne_50m_admin_1_states_provinces_lakes.zip")
# 讀取.shp文件
states_path = "ne_50m_admin_1_states_provinces_lakes"
states_path = os.path.join(
states_path,"ne_50m_admin_1_states_provinces_lakes.shp"
)
states_gdf=gpd.read_file(states_path)
states_gdf.head()
篩選出California州範圍
cali_aoi=states_gdf[states_gdf.name=="California"]
# 獲取其外包絡矩形座標
cali_aoi.total_bounds
array([-124.37165376, 32.53336527, -114.12501824, 42.00076797])
根據外包絡矩形經緯度對nc數據進行切片
- 利用
sel()
函數
# 獲取外包絡矩形的左下角和右上角經緯度座標
aoi_lat = [float(cali_aoi.total_bounds[1]), float(cali_aoi.total_bounds[3])]
aoi_lon = [float(cali_aoi.total_bounds[0]), float(cali_aoi.total_bounds[2])]
print(aoi_lat, aoi_lon)
# 將座標轉換爲標準經度,即去掉正負號
aoi_lon[0] = aoi_lon[0] + 360
aoi_lon[1] = aoi_lon[1] + 360
print(aoi_lon)
[32.533365269889316, 42.00076797479207] [-124.3716537616361, -114.12501823892204]
[235.62834623836392, 245.87498176107795]
# 根據指定的時間和空間範圍進行切片
start_date = "2010-01-15"
end_date = "2010-02-15"
two_months_cali = monthly_forecast_temp_xr["air_temperature"].sel(
time=slice(start_date, end_date),
lon=slice(aoi_lon[0], aoi_lon[1]),
lat=slice(aoi_lat[0], aoi_lat[1]))
two_months_cali
# 繪製切片數據分佈的直方圖
two_months_cali.plot()
plt.show()
# 繪製切片數據的空間分佈
two_months_cali.plot(col='time',
col_wrap=1)
plt.show()
# 若不指定時間範圍
cali_ts = monthly_forecast_temp_xr["air_temperature"].sel(
lon=slice(aoi_lon[0], aoi_lon[1]),
lat=slice(aoi_lat[0], aoi_lat[1]))
cali_ts
提取每個點的每年的最高氣溫
cali_annual_max=cali_ts.groupby('time.year').max(skipna=True)
cali_annual_max
提取每年的最高氣溫
cali_annual_max_val=cali_annual_max.groupby('year').max(["lat","lon"])
cali_annual_max_val
繪製每年的最高溫變化圖
f,ax=plt.subplots(figsize=(12,6))
cali_annual_max_val.plot.line(hue="lat",
marker="o",
ax=ax,
color="grey",
markerfacecolor="purple",
markeredgecolor="purple")
ax.set(title="Annual Max Temperature (K) in California")
plt.show()
使用Shapefile對nc文件進行切片
在上述的操作中,使用外包絡矩形的座標對nc數據進行了切片,但有時我們希望能得到不規則邊界的數據,此時需要使用到regionmask
包創建掩膜
f,ax=plt.subplots()
cali_aoi.plot(ax=ax)
ax.set(title="california AOI Subset")
plt.show()
cali_aoi
根據GeoPandasDataFrame生成掩膜
cali_mask=regionmask.mask_3D_geopandas(cali_aoi,
monthly_forecast_temp_xr.lon,
monthly_forecast_temp_xr.lat)
cali_mask
根據時間和掩膜對數據進行切片
two_months=monthly_forecast_temp_xr.sel(
time=slice("2099-10-25","2099-12-15"))
two_months=two_months.where(cali_mask)
two_months
繪製掩膜結果
two_months["air_temperature"].plot(col='time',
col_wrap=1,
figsize=(10, 10))
plt.show()
可以看到此時圖中顯示範圍較大,可以通過設置經緯度進一步切片
two_months_masked = monthly_forecast_temp_xr["air_temperature"].sel(time=slice('2099-10-25',
'2099-12-15'),
lon=slice(aoi_lon[0],
aoi_lon[1]),
lat=slice(aoi_lat[0],
aoi_lat[1])).where(cali_mask)
two_months_masked.dims
('time', 'lat', 'lon', 'region')
two_months_masked.plot(col='time', col_wrap=1)
plt.show()
同時對多個區域進行切片
# 選取多個州
cali_or_wash_nev = states_gdf[states_gdf.name.isin(
["California", "Oregon", "Washington", "Nevada"])]
cali_or_wash_nev.plot()
plt.show()
# 根據多個州的範圍進行掩膜的生成
west_mask = regionmask.mask_3D_geopandas(cali_or_wash_nev,
monthly_forecast_temp_xr.lon,
monthly_forecast_temp_xr.lat)
west_mask
幫助生成多個mask的函數
def get_aoi(shp, world=True):
"""Takes a geopandas object and converts it to a lat/ lon
extent
Parameters
-----------
shp : geopandas object
world : boolean
Returns
-------
Dictionary of lat and lon spatial bounds
"""
lon_lat = {}
# Get lat min, max
aoi_lat = [float(shp.total_bounds[1]), float(shp.total_bounds[3])]
aoi_lon = [float(shp.total_bounds[0]), float(shp.total_bounds[2])]
if world:
aoi_lon[0] = aoi_lon[0] + 360
aoi_lon[1] = aoi_lon[1] + 360
lon_lat["lon"] = aoi_lon
lon_lat["lat"] = aoi_lat
return lon_lat
west_bounds = get_aoi(cali_or_wash_nev)
# 設定提取的起止時間
start_date = "2010-01-15"
end_date = "2010-02-15"
# Subset
two_months_west_coast = monthly_forecast_temp_xr["air_temperature"].sel(
time=slice(start_date, end_date),
lon=slice(west_bounds["lon"][0], west_bounds["lon"][1]),
lat=slice(west_bounds["lat"][0], west_bounds["lat"][1]))
two_months_west_coast
two_months_west_coast.plot(col="region",
row="time",
sharey=False, sharex=False)
plt.show()
計算每個區域的溫度均值
summary = two_months_west_coast.groupby("time").mean(["lat", "lon"])
summary.to_dataframe()
本節完整代碼
# 提取geopandas對象的外包絡矩形經緯度
def get_aoi(shp, world=True):
"""Takes a geopandas object and converts it to a lat/ lon
extent """
lon_lat = {}
# Get lat min, max
aoi_lat = [float(shp.total_bounds[1]), float(shp.total_bounds[3])]
aoi_lon = [float(shp.total_bounds[0]), float(shp.total_bounds[2])]
# Handle the 0-360 lon values
if world:
aoi_lon[0] = aoi_lon[0] + 360
aoi_lon[1] = aoi_lon[1] + 360
lon_lat["lon"] = aoi_lon
lon_lat["lat"] = aoi_lat
return lon_lat
# 本節完整代碼
# 讀取矢量數據
states_path = "ne_50m_admin_1_states_provinces_lakes"
states_path = os.path.join(
states_path, "ne_50m_admin_1_states_provinces_lakes.shp")
states_gdf = gpd.read_file(states_path)
# 讀取nc數據
data_path_monthly = 'http://thredds.northwestknowledge.net:8080/thredds/dodsC/agg_macav2metdata_tasmax_BNU-ESM_r1i1p1_rcp45_2006_2099_CONUS_monthly.nc'
with xr.open_dataset(data_path_monthly) as file_nc:
monthly_forecast_temp_xr = file_nc
# 數據對象
monthly_forecast_temp_xr
# 將geopandas對象轉換成掩膜
states_gdf["name"]
cali_or_wash_nev = states_gdf[states_gdf.name.isin(
["California", "Oregon", "Washington", "Nevada"])]
west_mask = regionmask.mask_3D_geopandas(cali_or_wash_nev,
monthly_forecast_temp_xr.lon,
monthly_forecast_temp_xr.lat)
west_mask
west_bounds = get_aoi(cali_or_wash_nev)
# 根據時間、掩膜範圍對數據進行切片 .sel().where()
start_date = "2010-01-15"
end_date = "2020-02-15"
two_months_west_coast = monthly_forecast_temp_xr["air_temperature"].sel(
time=slice(start_date, end_date),
lon=slice(west_bounds["lon"][0], west_bounds["lon"][1]),
lat=slice(west_bounds["lat"][0], west_bounds["lat"][1])).where(west_mask)
# 輸出切片數據
two_months_west_coast
# 直方圖繪製
two_months_west_coast.plot()
plt.show()
# 繪製每個區域的變化
regional_summary = two_months_west_coast.groupby("region").mean(["lat", "lon"])
regional_summary.plot(col="region",
marker="o",
color="grey",
markerfacecolor="purple",
markeredgecolor="purple",
col_wrap=2)
plt.show()
# 轉換爲dataframe
two_months_west_coast.groupby("region").mean(["lat", "lon"]).to_dataframe()
參考鏈接:
https://gitee.com/jiangroubao/learning/tree/master/NetCDF4