03散点密度图(遥感反演数据精度验证)

news2024/11/20 6:31:35

本文是在模仿中精进数据分析与可视化系列的第三期——散点密度图,本文所用的数据和代码可在公众号GeodataAnalysis回复20230602下载。

一、简介

散点密度图(Scatter Density Plot)是一种用于可视化二维数据分布的图表。它将散点图和核密度估计图(Kernel Density Estimation,KDE)结合起来,通过在散点图上叠加一定透明度的核密度估计图来显示数据点的密度分布情况。

散点密度图可以用来探索数据的分布情况,尤其适用于大量数据点的情况。它可以帮助我们识别出数据的聚集区域、密度高低以及异常值等信息。

二、遥感反演PM2.5数据准备

本文所用的遥感数据来源于Surface PM2.5 | Atmospheric Composition Analysis Group | Washington University in St. Louis,该数据是圣路易斯华盛顿大学大气成分分析组分享的PM2.5数据。网站公布了多个精度的PM2.5数据,我们下载了2015-2020年精度最高的0.01°× 0.01°分辨率的数据,数据格式为.nc。采用如下代码将其转为TIF数据:

import os
import netCDF4 as nc
from glob import glob
from pyproj import CRS
from osgeo import gdal

years = list(range(2015, 2021))
x_res, y_res = 0.01, 0.01

for year in years:
    nc_path = glob(os.path.join('./nc/', f'*{year}*.nc'))[0]
    tif_path = os.path.join('./tif/', f'{year}.tif')
    # 获取分辨率和左上角像素坐标值
    rootgrp = nc.Dataset(nc_path)
    lon = rootgrp['lon'][...].data
    lat = rootgrp['lat'][...].data
    x_min, y_max = lon.min(), lat.max()
    # 仿射变换六参数
    gt = (x_min, x_res, 0, y_max, 0, -y_res)
    # 获取地理坐标系
    crs = CRS.from_epsg(4326)
    wkt = crs.to_wkt()
    # 读取数据
    pm = rootgrp['GWRPM25'][::-1, :]
    pm = pm.filled(np.nan)
    # 创建GeoTIFF文件并写入数据
    driver = gdal.GetDriverByName('GTiff')
    ds = driver.Create(tif_path, pm.shape[1], pm.shape[0], 1, gdal.GDT_Float32)
    ds.SetGeoTransform(gt)
    ds.SetProjection(wkt)
    band = ds.GetRasterBand(1)
    band.WriteArray(pm)
    band.SetNoDataValue(np.nan)

ds = band = None

三、地基PM2.5数据

全国2000+站点2015-2020年的年均PM2.5浓度数据,可在公众号回复20230602下载。以下代码用于筛选掉不符合要求的站点:

df = pd.read_csv('pm25.csv')
df.dropna(subset=["lon", "lat"], inplace=True)

extent = [73.00499725341797, 139.9949951171875, 18.0049991607666, 53.994998931884766]
def in_extent(row):
    lon, lat = row['lon'], row['lat']
    if lon<extent[0] or lon>extent[1]:
        return False
    if lat<extent[2] or lat>extent[3]:
        return False
    return True
mask = df.apply(in_extent, axis=1)
df = df.loc[mask, :]

pm_gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df['lon'], df['lat']), crs='EPSG:4326')
pm_gdf.plot();

四、计算每个站点对应的各年的反演PM2.5浓度

根据站点经纬度计算该站点对应的各年的反演PM2.5浓度,代码如下:

years = [2015, 2016, 2017, 2018, 2019, 2020]
for year in years:
    src = rio.open(f'./tif/{year}.tif')
    band = src.read(1)
    for i in pm_gdf.index:
        lon, lat = pm_gdf.loc[i, 'lon'], pm_gdf.loc[i, 'lat']
        row, col = src.index(lon, lat)
        # 获取指定行列号的像元值
        value = band[row, col]
        pm_gdf.loc[i, f'r{year}'] = value

五、散点密度图绘图

import numpy as np
from statistics import mean
import matplotlib.pyplot as plt
from matplotlib import colors, cm
from sklearn.metrics import mean_squared_error

# 显示中文
plt.rcParams['font.family'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False

def get_xyz(year):
    real = pm_gdf.loc[:, f'y{year}'].to_numpy()
    pred = pm_gdf.loc[:, f'r{year}'].to_numpy()
    mask1 = ~np.isnan(real)
    mask2 = ~np.isnan(pred)
    mask = mask1 & mask2
    real = real[mask]
    pred = pred[mask]
    xy = np.vstack([real, pred])
    # 建立概率密度分布,并计算每个样本点的概率密度
    z = gaussian_kde(xy)(xy)  
    return real, pred, z

def get_regression_line(real, pred, data_range=(0, 110)):
    # 拟合(若换MK,自行操作)最小二乘
    def slope(xs, ys):
        m = (((mean(xs) * mean(ys)) - mean(xs * ys)) / ((mean(xs) * mean(xs)) - mean(xs * xs)))
        b = mean(ys) - m * mean(xs)
        return m, b
    k, b = slope(real, pred)
    regression_line = []
    for a in range(data_range[0], data_range[1]+1):
        regression_line.append((k * a) + b)
    return regression_line

# 绘图,可自行调整颜色等等
fig, axs = plt.subplots(2, 3, constrained_layout=True, figsize=(9, 5))
years = [2015, 2016, 2017, 2018, 2019, 2020]
i = 1
vmin, vmax = 0, 0.5
for year, ax in zip(years, axs.flatten()):
    real, pred, z = get_xyz(year)
    scatter = ax.scatter(real, pred, marker='o', c=z*100, edgecolors=None, s=5, 
                         label='LST', cmap='Spectral_r', vmin=vmin, vmax=vmax)
    ax.plot([0, 120], [0, 120], 'k--', lw=1)  # 画的1:1线
    regression_line = get_regression_line(real, pred, data_range=(0, 120))
    ax.plot(regression_line, 'r-', lw=1.)      # 预测与实测数据之间的回归线
    if i>3:
        ax.set_xlabel('地基$\mathrm{PM_{2.5}(ug/m^3)}$')
    if i==1 or i==4:
        ax.set_ylabel('反演$\mathrm{PM_{2.5}(ug/m^3)}$')
    if i<4:
        ax.axes.xaxis.set_visible(False)
    if i in [2, 3, 5, 6]:
        ax.axes.yaxis.set_visible(False)
    ax.set_xlim(0, 120) # 设置x坐标轴的显示范围
    ax.set_xticks(range(0, 121, 20))
    ax.set_ylim(0, 120) # 设置y坐标轴的显示范围
    x, y = real, pred
    BIAS = mean(x - y)
    MSE = mean_squared_error(x, y)
    RMSE = np.power(MSE, 0.5)
    R = np.corrcoef(x, y)[0, 1]
    ax.text(10, 110, '$N=%.f$' % len(y), family = 'Times New Roman')
    ax.text(45, 110, '$R=%.2f$' % R, family = 'Times New Roman')
    ax.text(10, 100, '$BIAS=%.2f$' % BIAS, family = 'Times New Roman')
    ax.text(10, 90, '$RMSE=%.2f$' % RMSE, family = 'Times New Roman')
    i += 1
cbar = fig.colorbar(cm.ScalarMappable(norm=colors.Normalize(vmin=vmin, vmax=vmax), cmap="RdYlBu_r"), 
                    pad=0.012, orientation='vertical', aspect=30, ax=axs, label='Scatter Density')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/603424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux【网络编程】之HTTPS协议,一文了解HTTPS是保证通信安全的

linux【网络编程】之HTTPS协议 一、什么是HTTPS协议二、加密和解密2.1 什么是加密解密2.2 为什么需要加密2.3 常见的加密方式2.3.1 对称加密2.3.2 非对称加密2.3.3 数据摘要&#xff08;数据指纹&#xff09;2.3.4 数字签名 2.4 理智选择加密解密方式2.4.1 只使用对称加密✖️2…

OpenMMLab-AI实战营第二期——2.人体关键点检测与MMPose

文章目录 1. 人体姿态估计的介绍和应用2-1. 2D姿态估计概述2.1 任务描述2.2 基于回归2.3 基于热力图2.3.1 从数据标注生成热力图&#xff08;高斯函数&#xff09;2.3.2 使用热力图训练模型2.3.3 从热力图还原关键点 2.4 自顶向下2.5 自底向上2.6 单阶段方法 2-2. 2D姿态估计详…

搞什么飞机?快速排序算法都没搞懂,还敢说自己值20k?

引言 之前面试过一位求职者&#xff0c;其期望薪资是20k&#xff0c;面试时问到了排序算法&#xff0c;结果就是模棱两可&#xff0c;说这说那的… 所以&#xff0c;还是有必要学一些基础算法的 首先&#xff0c;搞明白学算法的重要性和为什么学算法 算法我认为是一种解决问题…

Midjourney摄影真人风,超高清图片一篇足够

欢迎小伙伴光临&#xff0c;本博主打的就是一个真实&#xff0c;关注点赞不迷路&#xff0c;毫无保留奉献&#xff0c;欢迎大家来探讨&#xff0c;以上图片均是万能咒语篇出品。 有些小伙伴感觉我的咒语水分很大&#xff0c;出不来效果&#xff0c;如果出不来效果的&#xff0c…

windows sql server 如何卸载干净?

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 windows sql server 怎么卸载干净&#xff1f; 前言一、windows sql server是什么&#xff1f;二、如何卸载干净 1、关闭sql server服务2、到控制面板&#xff0c;卸载sql …

深入Mybatis框架:解读数据源的实现,整合MyBatis框架,事务管理,集成JUnit测试

深入Mybatis框架 文章目录 深入Mybatis框架了解数据源解读Mybatis数据源实现非池化的数据源实现池化的数据源实现 整合Mybatis框架使用HikariCP连接池Mybatis事务管理使用Spring事务管理 集成JUnit测试 前面已经了解了JavaBean的创建和注入到IoC容器中&#xff0c;接下来深入My…

Nginx服务优化

配置nginx隐藏版本号 隐藏nginx版本号&#xff0c;避免安全漏洞泄漏 方法一&#xff1a;修改配置文件法 [rootwww conf]# vim /usr/local/nginx/confnginx.conf17 http { 18 include mime.types; 19 default_type application/octet-stream; 20 21 serve…

Generative AI 新世界 | 大型语言模型(LLMs)概述

在上一篇《Generative AI 新世界&#xff1a;文本生成领域论文解读》中&#xff0c;我带领大家一起梳理了文本生成领域&#xff08;Text Generation&#xff09;的主要几篇论文&#xff1a;InstructGPT&#xff0c;RLHF&#xff0c;PPO&#xff0c;GPT-3&#xff0c;以及 GPT-4…

jQuery的引入/jQuery筛选/菜单下拉案例/对类操作/封装的动画/自定义动画/获取元素属性

jQuery的使用与引入 点击链接后进入页面 复制整个页面,随后后新建文件,把复制的粘进去 jQuery入口函数 样式处理/隐式迭代 小案例 排他思想 淘宝服饰 链式编程 操作css方法 封装的动画 淡入淡出 自定义动画 获取元素固有属性值

添加程序到右键菜单打开项目文件夹

以Pycharm为例 第一部分&#xff1a; 添加程序到右键菜单。这里实验程序为pycharm&#xff0c;路径是形如D://pycharm/pycharm.exe。实际路径不是&#xff0c;这里是为了简便。 1、打开注册表&#xff0c;找到如下&#xff1a;HKEY_CLASSES_ROOT\Directory\Background\shell …

JVM学习(十四):垃圾收集器(万字介绍CMS、G1)

目录 一、垃圾收集器们 二、CMS(Concurrent-Mark-Sweep)&#xff1a;低延迟 2.1 什么是CMS 2.2 CMS工作流程 2.3 详细描述 2.4 CMS的优缺点 2.4.1 优点 2.4.2 弊端 2.5 CMS常用参数 三、G1&#xff08;Garbage First&#xff09;收集器&#xff1a;区域化分代…

【2023最新】C站最全的Python实战项目合集(附源码),练完即可就业,从入门到进阶,基础到框架,你想要的全都有

不管是从编程语言排行榜来说&#xff0c;还是流行程度来说&#xff0c;Python目前都算得上是最好的编程语言之一。由于入门简单对初学者友好&#xff0c;而被广泛使用。 部分中小学已将Python编入教材&#xff0c;浙江高考加入Python&#xff0c;计算机二级也加入Python&#…

Redis数据结构简介

对redis来说&#xff0c;所有的key&#xff08;键&#xff09;都是字符串。 1.String 字符串类型 是redis中最基本的数据类型&#xff0c;一个key对应一个value。 String类型是二进制安全的&#xff0c;意思是 redis 的 string 可以包含任何数据。如数字&#xff0c;字符串&am…

【数据库从0到1】-入门基础篇

【数据库从0到1】-入门基础篇 &#x1f53b;一、数据库产生背景&#x1f53b;二、数据库有关概述&#x1f53b;三、数据库访问接口&#x1f53b;四、数据库种类&#x1f53b;五、数据库有关术语&#x1f53b;六、常见DBMS排名&#x1f53b;七、常见数据库介绍7.1 RDS(关系型数据…

前端gulp的安装和使用,你或许用得到

gulp安装 1.npm install --global gulp-cli全局安装&#xff08;只需要执行成功一次&#xff0c;之后就不需要再全局安装了&#xff09; 2.npx mkdirp my-project创建项目并进入 3.cd my-project进入目录 4.npm init在项目目录下创建 package.json 文件 5.npm install --sav…

分享24个强大的HTML属性,建议每位前端工程师都应该掌握!

HTML属性非常多&#xff0c;除了一些基础属性外&#xff0c;还有许多有用的特别强大的属性 本文将介绍24个强大的HTML属性&#xff0c;可以使您的网站更具有动态性和交互性&#xff0c;让用户感到更加舒适和愉悦。 让我们一起来探索这24个强大的HTML属性吧&#xff01; 1、Ac…

tqdm.notebook显示进度条

需要安装hbox插件 如图是无法正常显示进度条插件的 要在Jupyter Notebook中使用HBox&#xff08;即水平盒子&#xff09;布局插件&#xff0c;您需要执行以下步骤&#xff1a; 确认您已经安装了Jupyter Notebook和ipywidgets。如果没有安装&#xff0c;您可以使用如下命令进行…

【蓝桥杯单片机第八届国赛真题】

【蓝桥杯单片机第八届国赛真题】 文章目录 【蓝桥杯单片机第八届国赛真题】前言一、真题二、源码 前言 有幸进入国赛&#xff0c;为自己大学最后一个比赛画上完满的句号^^ 下面为蓝桥杯单片机第八届国赛程序部分&#xff0c;功能差不多都实现了&#xff0c;可能存在小bug&#…

Qt(C++)使用QChart动态显示3个设备的温度变化曲线

一、介绍 Qt的QChart是一个用于绘制图表和可视化数据的类。提供了一个灵活的、可扩展的、跨平台的图表绘制解决方案,可以用于各种应用程序,如数据分析、科学计算、金融交易等。 QChart支持多种类型的图表,包括折线图、散点图、柱状图、饼图等。它还支持多个数据系列(data…

Emacs之magit提交代码(一百零八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…