pyvin:解析 VIN 号

问题描述

背景

用于解码带有车辆识别号的列的相同代码,对于其中一个库,我遇到了错误

代码

import pandas as pd
from vininfo import Vin # COUNTRY AND BRAND
from pyvin import VIN # MODEL AND YEAR


db = pd.DataFrame("VIN": ["3N6PD23W5ZK911765","MNTACUD40Z0000632","3N6DD23T9ZK874454"])  # VIN EXAMPLE


db["COUNTRY"] = db["VIN"].map(lambda x: Vin(x).country)  # PARSES OK AND RETURNS COUNTRY
db["BRAND"] = db["VIN"].map(lambda x: Vin(x).manufacturer)  # PARSES OK AND RETURNS BRAND

db["MODEL"] = db["VIN"].map(lambda x: VIN(x).Model)  # ERROR
db["YEAR"] = db["VIN"].map(lambda x: VIN(x).ModelYear)  # ERROR

错误

AttributeError: 'list' object has no attribute 'Model'
or
AttributeError: 'list' object has no attribute 'ModelYear'

问题

我不要求提供完整的解决方案,因为问题非常具体,但此时我感到不安全,欢迎提供任何提示

x 中的 db["YEAR"] = db["VIN"].map(lambda x: VIN(x).ModelYear) 是否等于单个字符串,还是将列表传递给函数

解决方法

让我们把问题分成几部分。首先,db 是一个 pandas.DataFrame 对象。您可能知道,db["VIN"] 是一个 pandas.Series 对象。您也可以使用

来验证它
In [19]: type(db["VIN"])
Out[19]: pandas.core.series.Series

然后,您使用的 pandas.Series.map 函数将 arg 作为参数,该参数可以是 dict 类型或函数(或系列)。你给它一个函数。然后,为系列 db["VIN"] 的每个值调用此函数。让我们看看那是什么。

# first value OK. Maybe?
In [23]: VIN("3N6PD23W5ZK911765")
Out[23]: <pyvin.pyvin.DecodedVIN at 0x2ef77ea5550>

# second value not OK
In [24]: VIN("MNTACUD40Z0000632")
Out[24]: []

因此,出于某种原因,VIN 返回一个 list。这是为什么?这是因为 pyvin.VIN 无法识别输入。如果添加错误处理,您将看到:

In [26]: import pyvin

In [27]: VIN("MNTACUD40Z0000632",error_handling=pyvin.RAISE)

...
c:\python\python 3.8.6-64\lib\site-packages\pyvin\utils.py in _compare_check_digit(vin,remainder)
     92     if check_digit != rem_val:
     93         msg = 'Invalid check digit! %s does not match computed val %s' % (check_digit,rem_val)
---> 94         raise VINError(msg)
     95     logger.debug("%s check [OK]")
     96

VINError: Invalid check digit! 0 does not match computed val 5

我怀疑 VIN 代码不正确,pyvin 有错误,或者底层服务 (NHTSA API) 无法识别 VIN 代码。