跳转至

Python

使用 papermill 运行 Jupyter Notebook

当执行两个具有前后依赖关系的 Jupyter Notebook 时,我们需要等待第一个 Notebook 运行完成,再开始运行第二个 Notebook。

一个笨拙的方法是,先预估好第一个 Notebook 运行需要的时间(例如 1 小时),然后在第二个 Notebook 的第一个 Cell 添加:

Python
import time

time.sleep(1 * 60 * 60)

这将使第二个 Notebook 运行 1 小时后,再运行后续的 Cell。

上述方法需要事先预估第一个 Notebook 运行需要的时间,预估时间过短会导致第二个 Notebook 提前运行,预估时间过长又会导致第二个 Notebook 浪费很多时间在 time.sleep() 上。

本文介绍了如何使用 papermill 运行 Jupyter Notebook,实现控制先后运行两个 Notebook 的功能。

screen-capture

pypika 中自定义 SQL 函数

pypika 是一个在 Python 中构建 SQL 语句的工具。这篇文章提供了一个很棒的入门教程,介绍了许多 pypika 的基本用法。

本文以 ClickHouse 中的 quantileExact 函数为例,介绍如何在 pypika 中自定义函数,尤其是自定义字符串拼接方式的实现方法。

image-20240711001853859

Python 类型检查工具 beartype

Python 代码中的类型提示并不是需要强制满足的。如果我们希望代码使用者严格遵循类型提示,在类型不符时抛出错误,可以使用 beartype 进行类型检查。

多线程下调试 Python 代码

当启用 n_jobs 超过 1 时,直接调试 Python 代码可能会报错 "Couldn't find a debug adapter descriptor for debug type 'Python Kernel Debug Adapter' (extension might have failed to activate)"

image-20240325190005418

本文记录了一个解决方案,可以在 n_jobs 超过 1 的多线程环境下调试 Python 代码。

使用 blacken-docs 对文档中的 Python 代码进行格式化

ruff 等代码格式化工具可以美化 Python 代码,但是不方便美化文档文本中的 Python 代码。如果想要格式化 markdown、字符串文档等中间的 Python 代码,经常需要手动地去统一格式。

本文介绍了 blacken-docs 这款工具,它可以轻松实现对文档中的 Python 代码进行格式化。

机器生成文本检测器

简介

本应用使用 BERT 模型和 SHAP 解释性分析技术,旨在帮助用户判断一个文本是否可能由机器生成。应用允许用户输入文本,然后使用预先训练好的 BERT 模型进行分析,最后通过 SHAP 提供文本的可解释性分析,帮助理解模型的预测结果。

在线体验地址:https://machine-generated-text-detection.streamlit.app

screenshot

使用 pathvalidate 处理不合法的文件或路径名字符串

在编程时经常需要处理文件和目录的命名,然而直接将字符串用作文件名或路径名时,可能会遇到一个常见问题:字符串中含有特殊字符或保留字,这可能导致在尝试保存文件时出现异常,如无法创建文件、路径解析错误等问题。例如,Windows 系统不允许文件名包含字符如 \/:*?"<>|

本文介绍了 pathvalidate 库,它提供了一系列实用的函数,用于验证和清理文件名和路径名中的非法字符。这样我们就不必重复造轮子来处理这些特殊字符了。

对含有空值的数据使用 np.corrcoef 计算 Pearson 和 Spearman 相关系数

本文实验探究了 np.corrcoef 在对含有空值的数据计算 Pearson 相关系数和 Spearman 相关系数时的结果。

  • np.corrcoef 在计算相关系数时,如果数据中存在一个空值,那么空值所在列与其他列的相关系数也会为空值。
  • 如果需要忽略空值后计算相关系数,可以使用 np.ma.corrcoef,它的参数 allow_masked 默认为 True。当传入一个 MaskedArray 对象时,np.ma.corrcoef 会忽略掉其中的空值。
  • 在对含有空值的数据使用 argsort().argsort() 对数据进行排序后,空值会被当做最小值,它也会获得一个排序值,空值内部的排序值大小取决于该空值所在的位置。因此,计算 Spearman 相关系数时,需要先手动删除空值。

迁移 Conda 虚拟环境

在一个设备上搭建了 Conda 虚拟环境后,如果需要在另一个设备上使用相同的环境,可以制作 environment.yml 文件,方便快速地迁移,而不需要再次手动安装包。

本文记录了将 macOS 的 Conda 虚拟环境迁移到 Linux 的过程。

image-20240121224354485

在 Python 中使用大语言模型进行文本分类

大语言模型可以做很多事情:给它一个提示词,它就能给出聪明的回复。但是,我们有时需要得到结构化的、具有严格类型要求的回答。例如我们需要判断一句话的情感得分,那么我们只需要得到一个数值,而不需要任何其他的元素。即使我们每次都在提示词中写上“请返回一个数值,例如 1.0。不要包含任何其他元素,只要一个数值,求你了”,模型仍然可能会返回各种奇怪的文本,这些文本在后续代码中极有可能出错。

marvin 是一个非常实用的 Python 包,它使用简单的代码和类型提示就能获取特定数据类型的返回。它的官网介绍说:

This lets you focus on what you've always focused on: writing clean, versioned, reusable code and data models, and not scrutinizing whether you begged your LLM hard enough to output JSON or needed to offer it a bigger tip for the right answer.

本文借助 marvingpt-3.5-turbo 对文本进行二分类,判断一段文本是否由大语言模型生成,而不是人类生成。

image-20240120232958730

JupyterLite:在浏览器中运行 Python

JupyterLite 是一个轻量级的 Jupyter 笔记本环境,旨在为用户提供快速、便捷的交互式计算体验。与传统的 Jupyter 环境不同,JupyterLite 可以在不需要安装任何软件的情况下直接在浏览器中运行。

有时我们希望快速测试一些简单的代码(例如得到 ChatGPT 给出的代码后),就可以用 JupyterLite 在浏览器中快速运行代码。

本文记录了如何部署 JupyterLite 站点,以及参与开源项目贡献的心得。

image-20240109210830896

Python 中的 set 和 list 转换时的随机性

在 Python 中,set 和 list 是两种不同的数据结构,它们在使用和功能上有很大的不同。set 是一个无序的、不重复的元素集合,而 list 是一个有序的、可重复的元素集合。

然而,从 set 到 list 的过程并不是一个简单的转换,因为 set 本身就是无序的,所以从 set 到 list 的过程并没有固定的顺序。这意味着每次转换得到的 list 的元素顺序可能都会不同。

在一些项目中,我们希望结果可重现,因此需要确保每一步的结果都没有随机性。许多随机性可以通过随机种子来控制,但从 set 到 list 的过程并不会被随机种子控制住,因此仍然存在随机性。

本文探讨了从 set 到 list 的过程中的随机性,亦作为排查随机性来源的一次记录。

批量修改 Jupyter Notebook 的内容

有时需要批量替换许多 Jupyter Notebook 的内容,由于 Jupyter Notebook 并不是简单的文本文件,在读取和替换时并不像批量修改 Python 脚本那样方便。

本文介绍了使用 nbformat 批量修改 Jupyter Notebook 的内容的方法。

20231207155702

Python argparse 解析命令行参数为布尔值

在 Python 开发中,命令行参数解析是一个常见的需求,它允许我们以命令行的方式向程序传递参数,从而实现更灵活和可配置的程序设计。Python 提供了一个内置库 argparse,它简化了命令行参数解析的过程。

这篇帖子介绍过如何使用 argparse 解析命令行参数,本文将介绍如何指定命令行参数为布尔值类型。直接使用 type=bool 是无法实现的,而需要传入一个 callable 的对象,在其中编写将字符串转换为布尔值的逻辑。

image-20231122230439023

chat-data: 基于大语言模型的数据分析应用

在数据分析领域,Pandas 是最受欢迎的 Python 库之一。然而,许多数据分析任务可以利用人工智能模型进行自动化。PandasAI 库为流行的数据分析和处理工具 Pandas 添加了生成式人工智能功能,你可以与 DataFrame 进行对话,并得到想要的数据分析结果。

本文使用 Streamlit 构建了一个在线应用,用户可以上传 Excel/CSV 数据,在输入想要执行的数据分析任务后,便可得到图表等结果,以及生成该结果的相应代码。

chat-data

在 Python 中调用在线大模型 API

许多大模型都提供了在线 API 接口服务,我们可以在 Python 中调用它们。本文使用 openaichatllmdashscope 等包实现了对 OpenAI、讯飞星火、智谱 AI、百度、阿里通义千问的调用。用户只需在本地用 .env 文件存储 API Key 即可快速调用这些大模型。

image-20231031211003404

计算部分相关系数矩阵

本文使用相关系数的矩阵表达形式,实现了计算部分相关系数矩阵的加速算法,并实证检验了三种计算相关系数矩阵方法的运行速度。

  • 在计算部分相关系数矩阵时,自定义的加速算法 相比 Pandas .corr() 方法提速约 2180 倍,比 Numpy .corrcoef() 方法提速约 115 倍。
  • 在计算全部相关系数矩阵时,Numpy .corrcoef() 方法比自定义的加速算法略快 \(10\%\),比 Pandas .corr() 方法快约 20 倍。

Python 3.12 新特性:@override 装饰器

Python 3.12 引入了 @override 装饰器,可以用来指定该方法是用来覆盖基类方法的。

新特性简介

在继承基类后,如果我们想覆盖基类中的某个方法 original(),我们可以改写该方法。然而,如果我们不小心将方法名拼写错误为 ooooriginal(),即一个基类中不存在的方法,那么当调用子类的 original() 方法时,实际上会调用基类中的方法,而且程序不会产生错误。这种情况下,我们可能无法察觉到问题的存在。

为了解决这个问题,我们可以使用 @override 注解来明确表示方法的覆盖关系。这样程序会检查 ooooriginal() 方法是否在基类中存在。由于 ooooriginal() 方法并未在基类中定义,程序会报错,从而帮助我们发现错误。

简而言之,使用 @override 注解可以帮助我们检测覆盖方法是否正确,避免潜在的错误。

Pandas 根据日期进行分组

问题背景:有一个分钟级别索引的数据框,需要根据日期进行分组聚合计算。

  1. 简单的 .groupby('datetime') 无法实现按日期分组。
  2. .groupby(pd.Grouper(level='datetime', freq='D')) 会为原始数据中不存在的日期填充空值(例如,在股票数据中,周末、节假日等非交易日会被填充为空值)。
    • 如果分组后调用的是 .mean(),则会出现这个问题。
    • 如果分组后调用的是 .transform('mean'),则不存在这个问题。

本文记录了可以正确根据日期进行分组的方法。

image-20231008235016433

Python 使用 * 以强制调用者使用关键字参数

在 Python 中,函数可以接受不同类型的参数,包括位置参数和关键字参数。位置参数必须按照特定的顺序传递给函数,而关键字参数可以根据参数名指定。

在某些情况下,我们可能希望定义一个函数,其中一部分参数只能以关键字形式指定。为此,我们可以使用独立的 * 号来分隔这些参数。

使用 pyflyby 自动管理导入包

在编写 Python 代码时,尤其是在构建复杂的项目时,你是否遇到过这些问题:

  • 忘记 import 某个包了;

  • import 了很多包,但不知道哪些是可以删掉的?

Python 开发过程中,我们经常需要导入一些第三方包或自定义的模块。但是,手动导入这些包和模块有时候会变得非常繁琐和冗长。由 D. E. Shaw group 贡献的开源工具 pyflyby 可以自动为我们管理这些导入,帮助我们轻松解决这些问题!

Kapture 2023-09-16 at 13.23.00

Python @lru_cache 内置 LRU 缓存

Python 内置模块 functools 的一个高阶函数 @lru_cache 是一个为函数提供缓存功能的装饰器,缓存 maxsize 组传入参数,在下次以相同参数调用时直接返回上一次的结果。用以节约高开销或 I/O 函数的调用时间。

在递归计算斐波那契数列的第 30 项时,使用 @lru_cache 可使速度提升约 400 万倍。

image-20230916231919961

Pandas 向前与居中滚动计算

Pandas 中的 rolling 默认是向后(也就是向上)获取滚动窗口,如果需要向前(也就是向下)或者居中(也就是同时向上和向下)获取滚动窗口,则可以分别使用 pd.api.indexers.FixedForwardWindowIndexercenter=True 来实现。

本文还使用了 .shift(-1) 实现向前或者居中获取滚动窗口,并对比了这种方法与上述方法所得结果的差异。

data forward_using_FixedForwardWindowIndexer forward_using_shift center_using_center center_using_shift
0 1.0 3.0 3.0 3.0 3.0
1 2.0 2.0 2.0 3.0 3.0
2 NaN 4.0 4.0 6.0 6.0
3 4.0 9.0 9.0 9.0 9.0
4 5.0 5.0 NaN 9.0 NaN

使用下一个非空值的平摊值填充

本文记录了一个数据处理的小项目。需求如下:

  • 一列数据中 存在零值

  • 我们需要 用下一个非零值进行填充

  • 用于填充的值 是“下一个非零值”除以“这一段零值的长度 +1”,也就是将下一个非零值平摊后进行填充。

image-20230823233238606

image-20230823234017340

本文还记录了如何向同一个工作簿中导出多个工作表。

Python 继承 Mixin 以拓展类的功能

在 Python 中,我们经常会使用继承来构建类之间的关系。继承可以让子类获得父类的属性和方法,在代码复用和扩展功能方面非常有用。然而,当我们需要在一个类中引入多个不相关的功能时,继承的方式可能会变得复杂和混乱。这时,就可以使用 Mixin 以一种更灵活的方式来扩展类的功能。

使用 Mixin 的好处

  1. 灵活性:使用 Mixin 可以将特定功能的复用与类的继承分离开来,使代码更加灵活和可维护。
  2. 可组合性:通过多继承,可以将多个 Mixin 类组合在一起,来实现多个功能的复用。
  3. 避免继承层次过深:当需要引入多个不相关的功能时,使用 Mixin 可以避免继承层次过深造成的代码复杂性和混乱。
  4. 增强可读性:Mixin 类中只包含特定功能的方法或属性,使代码更易读、更易理解。

什么是 Mixin

Python 中的类方法和静态方法

Python 中常见的方法分三种:实例方法、类方法和静态方法。实例方法最为常见,也最容易理解,而另外两种方法则稍难理解。本文介绍了类方法和静态方法的用途,并提供了代码示例。

Python 进阶教程系列 10:组合模式

本文是 Python 进阶教程系列 10,主要介绍了 Python 组合模式。

组合模式是一种结构型设计模式,它允许我们将对象组合成树形结构来表示“部分 - 整体”的层次结构。组合模式使得客户端能够以相同的方式处理单个对象和组合对象,从而使得客户端代码更加简单和通用。

img

Python 进阶教程系列 9:单例模式

本文是 Python 进阶教程系列 9,主要介绍了 Python 单例模式。

在软件开发中,单例模式是一种常见的设计模式,它确保一个类只有一个实例,并提供全局访问点。Python 作为一种灵活而强大的编程语言,也提供了多种实现单例模式的方法。

本文将介绍 Python 中常用的两种单例模式实现方式:基于模块和基于类装饰器。

Python 进阶教程系列 8:代理模式

本文是 Python 进阶教程系列 8,主要介绍了 Python 代理模式。

什么是代理模式?

代理模式是一种结构型设计模式,它允许通过创建一个代理对象来控制对另一个对象的访问。在软件开发中,代理是对象的一种封装,它可以隐藏实际对象的复杂性,并提供简洁的接口供其他对象使用。

代理模式有以下几个优点:

  • 通过使用代理对象,可以对真实对象进行封装和控制,从而隐藏了真实对象的复杂性。
  • 可以通过代理对象实现一些额外的功能,如记录日志、缓存数据、实现懒加载等。
  • 代理模式符合单一职责原则,将对象的职责分离,使得每个对象都可以专注于自己的功能。

Python 进阶教程系列 6:使用 mypy 进行类型提示

本文是 Python 进阶教程系列 6,主要介绍了使用 mypy 进行类型提示。

Python 是一门动态类型的编程语言,这意味着我们在编写代码时并不需要显式地声明变量的类型。然而,对于大型项目或需要和他人合作的项目来说,类型提示可以提供更好的代码健壮性和可读性。

为了实现类型提示,Python 社区开发了许多工具,其中之一就是 mypymypy 是一个静态类型检查器,它可以在不运行代码的情况下分析代码并发现潜在的类型错误。通过使用类型注释,mypy 可以提供更好的代码可读性和可维护性,同时还能帮助捕获潜在的错误。

Python 进阶教程系列 5:获取和修改被保护的属性

本文是 Python 进阶教程系列 5,主要介绍了 Python 私有化及 _ 下划线命名用途,以及使用 gettersetterproperty 来修改被保护的属性。

本文部分转载了 Python 私有化及 _ 下划线命名用途,已获得原作者授权。

Python 中没有真正的私有属性或方法,但有一些和命名有关的约定,让编程人员处理一些需要私有化的情况。我们常常需要区分私有方法、属性和公有方法、属性以方便管理和调用,在 Python 中如何做呢?

在变量、方法命名中有下列几种情况:

  • xx 公有变量/方法
  • _xx 前置单下划线
  • __xx 前置双下划线
  • __xx__ 前后双下划线
  • xx_ 后置单下划线

接下来分别介绍这几种带下划线命名的特性与区别。

Python 进阶教程系列 4:命令行参数

本文是 Python 进阶教程系列 4,主要介绍了 sysargparse 解析命令行参数。

命令行参数是指在运行程序时传递给程序的参数。例如,我们可以通过命令行参数来指定要处理的文件名、设置程序的配置选项等。

image-20230727235705211

Python 进阶教程系列 3:生成器

本文是 Python 进阶教程系列 3,主要介绍了生成器 generatoryield 的机制和 nextsend 的用法,并展示了如何用 generator 生成无限序列。

在循环中使用生成器作为迭代对象,就不用将所有需要遍历的值都全部计算出来再迭代,而是可以每迭代一次就计算一个需要遍历的值。

这种写法有以下几个好处:

  1. 节省内存资源:生成器以延迟计算的方式逐个生成数据,不会一次性生成所有数据,因此可以避免在内存中存储大量数据,从而减少内存资源的占用。
  2. 更快的计算速度:由于生成器以延迟计算的方式逐步生成数据,避免了一次性计算所有数据所带来的资源浪费,因此生成器往往比一次性生成所有数据的方式更加高效。
  3. 更灵活的逻辑处理:生成器可以动态地生成数据,并且可以支持迭代过程中的数据清洗、处理等操作,从而让代码更加灵活、简单。

Python 进阶教程系列 2:装饰器

本文是 Python 进阶教程系列 2,主要介绍了装饰器的机制和用法。

Python 是一种功能强大的编程语言,其灵活性和可扩展性使得开发者能够创造出各种强大且高效的应用程序。其中一个让 Python 如此受欢迎的特性就是装饰器(Decorators)。

装饰器是一种可以动态地修改某个类或函数的行为的函数,它们在不修改源代码的情况下为已经存在的函数或类添加额外的功能。

我对装饰器的理解是:装饰器即为“传入一个函数,传出一个被加工后的函数”的函数。

Python 进阶教程系列 1:双下划线的魔法方法

在构建大型项目时,一些进阶的 Python 开发技术能够让我们编写可复用、可拓展、更优雅、更高效的代码,使得代码清晰、整洁且便于维护。本系列笔记参考了 YouTube NeuralNine 频道Python Advanced Tutorials 系列视频,内容涵盖魔法函数、装饰器、生成器、参数解析等内容。

本文是 Python 进阶教程系列 1,主要介绍了双下划线的魔法方法的作用及示例代码,包括__init____str____len____getitem____add____call____format__ 等。

image-20230724232129477

使用 Ruff 自动检查代码错误

在编写大型项目时,一些细节代码容易影响代码的正常运行。若花费太多时间检查变量命名、导入包等细节问题,则会大幅影响工作效率和心情。

Ruff 是一个代码分析工具,即 Linter,它可以用于检查代码中的语法错误、编码规范问题、潜在的逻辑问题和代码质量问题等,可以提供实时反馈和自动修复建议。

Ruff 的优点是速度非常快,且安装和使用都非常简单。使用 Ruff 可以帮助我们自动检查代码存在的错误(如变量未定义、缺失外部依赖包等),这一切都不需要真正花时间运行代码。

Shows a bar chart with benchmark results.

Dijkstra 算法求解最短路径问题

本文使用 Python 实现了 Dijkstra 算法求解最短路径问题。在算法实现中,使用数组存储网络中各结点之间的距离,使用二叉堆存储 T 集合,并尽量使用向量化计算加快运行速度。

最终在三种网络结构下的运行时间为:

输入文件 grid_150_150 random_20000_40000 dense_1000
运行时间 302.93ms 292.14ms 135.29ms

但在最开始实现 Dijkstra 算法时,我的程序需要花 5 秒才能完成计算。经过逐步优化,运行时间可以降为 3 秒甚至 0.13 秒。把算法效率优化到极致的过程是非常有收获的,既加深了对算法本身的理解,又学习了许多优化算法的经验。

优化算法的经验

  1. 多考虑用向量化计算,尽量避免使用 for 循环。
  2. 想清楚算法的终止条件是什么。例如,在 One-to-all 问题中,可以把“遍历完T集合中的所有元素,直到 T 集合为空集”作为终止条件,也可以把“ P 集合中的元素个数等于网络中的结点个数”作为终止条件。虽然两者都能得到正确的结果,但当 P 集合中的元素个数等于网络中的结点个数时,T 集合中的元素是不需要再更新的,所以后者比前者所需要的运算次数少得多。
  3. 熟悉 NumPy 等科学计算库的实现细节。例如,在 NumPy 中,np.onesnp.empty 都可以用来创建指定形状的数组,其中 np.ones 会创建一个填充 1 的数组,而 np.empty 会在一块内存上创建一个未初始化的数组。由于 np.empty 不会进行初始化,因此生成速度要比 np.ones 更快。
  4. 使用合适的数据类型。例如,若问题中的变量可以肯定为整数,则可以考虑用 dtype=np.int32 或者 dtype=np.int16,节约内存空间。不同整数数据类型所能表示的整数范围如下:
Type Capacity
Int16 (-32,768 to +32,767)
Int32 (-2,147,483,648 to +2,147,483,647)
Int64 (-9,223,372,036,854,775,808 to +9,223,372,036,854,775,807)

Python 滚动回归

本文实现了多个资产分别在时间序列上进行滚动回归,并返回由最新系数计算得到的残差,最后将多个资产的残差结果重新聚合为多重索引的数据框。

image-20230424173801905

从零开始搭建卷积神经网络组件

本文是深度学习课程的一次练习,使用 Numpy 实现了 CNN 中卷积层、池化层的前向传播与反向传播。

以下是一个典型卷积层的计算过程:

  • 输入张量:\(X \in \mathbb{R}^{M \times N \times D}\)。例:\(D=1\) 时,输入的是 \(M \times N\) 维的灰度图像; \(D=3\) 时,输入的是 \(M \times N\) 维的彩色图像。
  • 卷积核:\(W \in \mathbb{R}^{U \times V \times D \times P}\),其中每个切片矩阵 \(W^{d, p} \in \mathbb{R}^{U \times V}\), \(1 \leq d \leq D, 1 \leq p \leq P\)
  • 输出张量: \(Y \times \mathbb{R}^{M^{\prime} \times N^{\prime} \times P}\)

conv_single_step

基于 ChatGPT 的在线问答机器人

本文介绍了如何基于 OpenAI ChatGPT 接口和 feffery components 构建在线问答机器人,并基于 render 实现自动化持续部署。

它支持:

  1. 开启多轮对话模式,它将记住你之前的问题。
  2. 导出当前对话记录为 Markdown 文件,你可以将其保存到本地。
  3. 一键清空当前对话记录。

使用它!

image-20230305114453764

VS Code 代码片段

许多常用的代码片段是重复、通用的,将它们记录并整理起来,在需要时可以方便地调用,可以大幅提高编码效率。

VS Code 代码片段功能是一个非常好用的功能,在保存代码片段后,只需输入几个前缀,即可自动生成代码片段。

利用 snippet-generator 这个工具自动生成代码片段,可以让整理代码片段的过程更高效!

vscode-snippets

LightGBM 的用法

LightGBM 是一种基于决策树的梯度提升机(GBM)算法,它是一种快速、准确的机器学习算法,可以用于分类和回归问题。

本文介绍了 LightGBM 的使用方法和代码示例,并记录了自定义损失函数、打印训练过程、迭代次数参数等问题的解决方法。

LightGBM_logo_black_text

使用 pdb 调试代码

pdb 是 Python 内置的一个调试库,为 Python 程序提供了一种交互的源代码调试功能,主要特性包括设置断点、单步调试、进入函数调试、查看当前代码、查看栈片段、动态改变变量的值等。

常用的 pdb 命令

image-20230208010600684

Python 自动合并 PDF 文件

问题与需求

合并 PDF 文件是常用的操作,如果手动合并的话可以使用 Adobe Acrobat 这类专业软件,只要点点鼠标即可完成合并。

如果经常需要合并同样的文件(例如经常更新的中英文简历),可以使用 PyPDF2 包,几行代码即可实现自动合并 PDF 的功能。

代码实现

Python 中的赋值与深浅拷贝

Python 中的赋值只是引用了对象,当原变量发生改变时,新变量也会随之发生改变。

.copy()方法可以进行浅拷贝,它可以深拷贝父对象(一级目录),但子对象(二级目录)仍然只是引用。

.deepcopy()方法可以进行深拷贝,它可以深拷贝父对象(一级目录)和子对象(二级目录),当原变量改变时,深拷贝得到的变量不会发生任何改变。

Black 格式化 Python 代码

用 Black 自动格式化 Python 代码,编写规范、美观的 Python 代码,让阅读代码变成一种享受。

本文记录了在 VS Code 中安装 Black 时遇到的问题和解决方案。

python-formatter-black

Python 实现多列滚动计算——以“更优波动率”为例

对单列数据进行滚动计算,可以使用常规的.rolling()

如果需要对多列数据进行滚动计算,可以考虑下面两种方法:

  1. 引入外部包numpy_ext,使用其中的rollling_apply()方法。
  2. .rolling()中加入参数method='table'

本文以方正金工发表的一篇研报中提出的计算“更优波动率”为例,实现了对多列数据进行滚动计算,并对上述两种方法总结如下:

  1. numpy_ext.rollling_apply()需要引入外部包numpy_ext,该方法接受需要进行滚动计算的多个 Series,并返回计算出的一个数组。
  2. .rolling(method='table')是 Pandas 内置的函数(需要升级到较新的版本),指定method='table'后,就可以对数据框中的多列进行滚动计算,并返回一个数据框。若返回的多列结果相同,我们只需要取出其中一列即可。
  3. .rolling(method='table')使用了engine='numba',计算速度更快。

修改 Jupyter Notebook 的默认 Python 解释器

Conda 可以十分方便地创建虚拟环境,便于在不同的项目中使用不同的 Python 版本、外部包等。今天在创建新的虚拟 Conda 环境后,在 VS Code 中没有找到刚刚创建的 Python 解释器。

解决方案是:

  1. 先按Ctrl+Shift+P,调出Select Interpreter选项,这里应该可以看到最新创建的 Conda 环境;
  2. 再按Ctrl+Shift+P,调出Clear Cache and Reload Window选项,重新加载窗口;
  3. 最后点击右上角的“选择内核”,可以看到刚才创建的环境。

pandas 中的 axis

pandas 中的axis参数代表对数据进行处理时遵循的方向。在单行、单列操作(如drop)时,axis=0axis=1分别代表删除行和删除列。在聚合操作(如求mean)时,axis=0axis=1分别代表求列均值和行均值。

总结

  • axis=0

如果是单行操作,就指的是某一行;

如果是聚合操作,指的是跨行 cross rows。

  • axis=1

如果是单列操作,就指的是某一列;

如果是聚合操作,指的是跨列 cross columns。

在 pandas 中计算方差

pandas 默认的.var()方法计算的是样本方差,即自由度为\(N-1\)。若想计算总体方差,需指定参数ddof=0(1)。

  1. Delta Degrees of Freedom。当指定ddof时,计算方差的分母为N-ddof

总结

  • pandas 中的var()默认的自由度是 n-1,即var(ddof=1)
  • NumPy 中的var()默认的自由度是 n,即var(ddof=0)
  • pandas 中的var(ddof=0)相当于 NumPy 中的 var()