炸鸡人博客 基本上无害
Posts with the tag python:

Python 相关资源汇总(持续更新中)

简单汇总罗列一下我在网上找到的还不错的 Python 相关资源,包括语言本身以及各种常用库的教程,当然触手可及的官方文档就不收纳了。通通都是免费资源(付费的咱也看不到),分享给有需要的读者。不过互联网资源并非恒久不灭,说不定哪天域名就失效了,或是原作者突然隐藏文章,且看且珍惜吧。

CALIPSO L2 VFM 产品的读取和绘制(with Python)

前言

CALIPSO 卫星的 L2 VFM(Vertical Feature Mask)产品根据激光的后向散射和消光信息,将激光通过的各高度层分类为云或气溶胶。该产品在现实中的表现如下图所示:卫星一边在轨道上移动一边向地面发射激光脉冲,相当于在地面上缓缓拉开一幅“画卷”,VFM 描述了“画卷”上云和气溶胶的分布和分类情况。

R-C

处理 VFM 产品的难点在于:

  • VFM 数组呈 (N, 5515) 的形状,N 表示卫星移动时产生了 N 次观测,但 5515 并非表示有 5515 层高度,而是三种水平和垂直分辨率都不同的数据摊平成了长 5515 的数组。因此处理数据时需要参照文档的说明对 5515 进行变形。
  • 文件中的经纬度和时间与 5515 的对应关系。时间数组需要解析成可用的格式。
  • 每个 range bin 的分类结果编码到了 16 位的无符号短整型的每个比特上,需要按位解码。
  • 网上现成的代码偏少。

网上能找到的代码有:

笔者也曾写过两次教程:

本文是对旧教程的翻新,会对 VFM 数据的结构进行更多解释,对代码也进行了更新。本文使用 pyhdf 读取 HDF4 文件,用 Matplotlib 3.6.2 画图。为了方便画图,用了一些自制的函数(frykit)。虽然基于 Python,但希望能给使用其它语言的读者提供一点思路。

完整代码已放入仓库 calipso-vfm-visualization

Pandas 系列:管道风格

R 语言的管道

这回来介绍一下如何利用管道(pipe)风格将 Pandas 相关的代码写得更易读,不过首先让我们看看隔壁 R 语言中管道是怎么用的。假设输入是 x,经过连续四个函数的处理后得到输出 y,代码可以按顺序写:

x1 <- func1(x, arg1)
x2 <- func2(x1, arg2)
x3 <- func3(x2, arg3)
y <- func4(x3, arg4)

Pandas 系列:图解插值

相信大伙对 NumPy 和 SciPy 里的插值比较熟:已知坐标值 xp 和变量值 fp,调用函数计算变量在目标坐标 x 上的数值。例如 np.interp 的 API 就是

np.interp(x, xp, fp)

Pandas 的 SeriesDataFrame 对象也有插值方法 interpolate,默认做线性插值。但其功能与 NumPy 和 SciPy 不太一样。以一个序列对象 s 为例:

# 缺测部分和有效部分.
invalid = s.isna()
valid = ~invalid

# 对应于xp.
s.index[valid]

# 对应于fp.
s.values[valid]

# 对应于x.
s.index

# 两式大致等价.
s.interpolate(method='index').values
np.interp(s.index, s.index[valid], s.values[valid])

即 Pandas 的插值是要利用序列的有效值当 xpfp,去填补缺测的部分。所以调用 s.interpolate 时我们不需要传入形如 x 的参数,而是应该在调用前就通过 s.reindex 之类的方法将 x 融合到 s 的索引中。这么说可能有点抽象,下面就以图像直观展示 Pandas 里插值的效果。本文不会涉及到具体的插值算法(最邻近、三次样条……),仅以线性插值为例。

Python 系列:衔尾蛇一样的取模

Python 的取模运算 r = m % n 相当于

# 或q = math.floor(m / n)
q = m // n
r = m - q * n

即取模的结果是被除数减去地板除的商和除数的乘积,这一规则对正数、负数乃至浮点数皆适用。

n 为正数时。显然任意实数 x 可以表示为 x = r + k * n,其中 0 <= r < nk 是某个整数。那么有

x // n = floor(r/n + k) = k
x % n = x - x // n = r

x % n 的结果总是一个大小在 [0, n) 之间的实数 r。当 n = 10 时,以 x = 12x = -12 为例:

number

如果以 n 为一个周期,那么 x = 12 就相当于往右一个周期再走 2 格,x % n 会消去这个周期,剩下不满一个周期的 2;x = -12 相当于往左两个周期后再往右走 8 格,x % n 会消去这两个周期,剩下不满一个周期且为正数的 8。

再本质点说,取模运算就是在 [0, 10) 的窗口内进行“衔尾蛇”移动:

  • 12 向右超出窗口两格, 12 % 10 = 2,即右边出两格那就左边进两格。
  • -12 向左超出窗口 12 格,-12 % n = 8,即左边出 12 格那就右边进 12 格,发现还是超出左边两格,再从右边进两格,最后距离零点 8 格。

Python 系列:测量程序的运行时间

前言

说到测量程序的运行时间这件事,我最早的做法是在桌上摆个手机,打开秒表应用,右手在命令行里敲回车的同时左手启动秒表,看屏幕上程序跑完后再马上按停秒表,最后在纸上记下时间。后来我在 Linux 上学会了在命令开头添加一个 time,终于摆脱了手动计时的原始操作。这次就想总结一下迄今为止我用过的那些测量时间的工具/代码。

Python 系列:变量命名时形容词应该放在名词前面还是后面?

今天改程序时脑海里突然蹦出这个问题,更宽泛地说,是修饰词或者偏正结构的先后顺序,例如

  • upper_axbottom_axax_upperax_bottom
  • start_dateend_datedate_startdate_end

一旦开始疑惑,焦虑便随之而来:哪一种比较好呢?我之前的代码里好像两种写法都出现过,有没有什么现成的规范可以参考呢?越想越不痛快,所以赶紧上网找点前人经验来背书。意外的是,网上大部分文章都在讨论如何取有意义的变量名,而关于这个问题的寥寥无几,也许是因为太细节、太“语法”了?现归纳两篇我看过的帖子以供参考。

首先在 stack overflow 上找到了一模一样的提问:是用 left_buttonright_button,还是 button_leftbutton_right 更好呢?提问者自己觉得前者符合英文语序,读起来更加自然,而后者强调了变量的重点在于按钮,而左和右是额外的补充信息。有评论指出后者在 IDE 里更方便,因为你一键入 button,就会自动联想出所有带后缀的版本。这也挺符合人的联想过程,我们肯定是先想到“我要找按钮”,再明确具体要什么样的按钮。当然也有评论给出了经典的废话:与其纠结哪一种约定,任选一种并在项目里维持一致性最重要!好家伙,要是我如此豁达还会来搜这种鸡毛蒜皮的问题吗?

Python 系列:将列表等分为 n 份

本文研究一个小问题:如何将长度为 N 的列表等分为 n 份?该问题的示意图如下

diagram1

N 除以 n 的商为 size,余数为 rest,数值满足 0 <= rest < n or size(除法规则请见 Python 系列:除法运算符)。当 Nn 的倍数时,rest = 0 ,列表正好被等分为 n 份,每份含 size 个元素;而当 N 不是 n 的倍数时,rest > 0,按前面的分法会剩下 rest 个元素。对于后一种情况来说并不存在真正的等分,只能说希望尽量等分,问题的重点也落在了如何处理这 rest 个元素上。

MODIS 二级气溶胶产品指北(with Python)

前言

笔者初次使用 MODIS 二级气溶胶产品时,一下就被密密麻麻一堆变量搞懵了:很多变量名字里带个 Optical_Depth,这我能猜到,就是气溶胶光学厚度,但各种 CorrectedEffectiveBestAverageSmallLarge 的前后缀鬼知道是什么。看过的论文基本不说具体用的哪个变量,各种教程也不会告诉你这些亲戚间的差异,似乎这件事一点也不重要。本着 know your data 的心态,我在翻阅了 MODIS 的几个官网后总算从反演的原理中稍微体会到了这些前后缀的意义。现将学习经验总结归纳如下,希望能帮到和我一样疑惑的小伙伴。同时本文还会提供简单的 Python 示例代码。

如果嫌正文太啰嗦,可以直接跳到文末的总结部分,那里直接给出了各个变量的使用建议。

Python 系列:小心默认的可变参数

之前我在 Cartopy 系列:从入门到放弃 一文中定义了这样一个函数

def set_map_extent_and_ticks(
    ax, extent, xticks, yticks, nx=0, ny=0,
    xformatter=LongitudeFormatter(),
    yformatter=LatitudeFormatter()
):
    ...