问题描述
我对使用 Visions 库来自动化识别某些类型的证券(股票)标识符的过程很感兴趣。 documentation mentions 它可以以这种方式用于 ISBN 代码,但我正在寻找一个更具体的例子来说明如何做到这一点。我认为对于我正在考虑的字段,该过程几乎相同,因为它们都有校验位(ISIN、SEDOL、CUSIP)。
我的总体想法是,我将为不同的标识符类型创建自定义类型,并且可以使用这些类型来
- 获取类型未知的数据框并识别与类型匹配的列(即使不是 100% 匹配)
- 在已知类型的数据帧上验证类型
解决方法
很好的问题和用例!不幸的是,关于创建新类型的 documentation 现在可能需要一点爱,因为 0.7.0 版本有 API 重大更改。上一个链接和 2020 年 8 月发布的 this 帖子都应该更详细地介绍类型创建的概念。如果这些示例中的任何一个失败,那么我很抱歉,我们会切换到基于调度的实现来支持每种类型的不同后端(pandas、numpy、dask、spark 等...)。您现在不必担心,但如果您有兴趣,可以找到默认类型定义 here 及其后端 here。
构建 ISBN 类型
在定义类型时,我们需要做出两个基本决定:
- 什么定义了类型
- 我们的新类型还与哪些其他类型相关?
对于 ISBN 用例,O'Reilly 提供验证正则表达式以匹配 ISBN-10 和 ISBN-13 代码。所以,
- 什么定义了类型?
我们希望序列中的每个元素都是与相应的 ISBN-10 或 ISBN-13 正则表达式匹配的字符串
- 我们的新类型还与哪些其他类型相关?
由于 ISBN 本身就是字符串,我们可以使用 Visions 提供的默认字符串类型。
类型定义
from typing import Sequence
import pandas as pd
from visions.relations import IdentityRelation,TypeRelation
from visions.types.string import String
from visions.types.type import VisionsBaseType
isbn_regex = "^(?:ISBN(?:-1[03])?:?●)?(?=[0-9X]{10}$|(?=(?:[0-9]+[-●]){3})[-●0-9X]{13}$|97[89][0-9]{10}$|(?=(?:[0-9]+[-●]){4})[-●0-9]{17}$)(?:97[89][-●]?)?[0-9]{1,5}[-●]?[0-9]+[-●]?[0-9]+[-●]?[0-9X]$"
class ISBN(VisionsBaseType):
@staticmethod
def get_relations() -> Sequence[TypeRelation]:
relations = [
IdentityRelation(String),]
return relations
@staticmethod
def contains_op(series: pd.Series,state: dict) -> bool:
return series.str.contains(isbn_regex).all()
仔细观察,有三件事需要注意。
- 新类型继承自
VisionsBaseType
- 我们必须定义一个
get_relations
方法,用于将新类型与我们可能想在排版中使用的其他类型相关联。在本例中,我使用了IdentityRelation
到 String,这意味着 ISBN 是 String 的子集。当我们想要支持改变基础数据的关系(比如将字符串“4.2”转换为浮点数 4.2)时,我们也可以使用InferenceRelation
。 - A
contains_op
这是我们对类型的定义。在本例中,我们将一个正则表达式字符串应用于输入中的每个元素,并验证它是否与 O'Reilly 提供的正则表达式匹配。
扩展
理论上,ISBN 也可以编码为 10 位或 13 位整数 - 与您可能想要在 InferenceRelation
和 Integer
之间创建 ISBN
的人一起使用。一个简单的实现将涉及将整数强制转换为字符串并应用上述正则表达式。