使用pyzipcode库查询邮编信息,不存在的邮编如何返回NaN
解决方法
问题原因
你直接用zipDB[邮编]的语法查询不存在的邮编时,pyzipcode库会直接抛出KeyError异常,而非返回空值,因此你提前用pd.isnull判断的逻辑还没执行就会中断报错。从报错的源码也可以看到,库内部的__getitem__方法会先调用get查询,查询不到就直接抛异常。
具体实现
推荐用一次apply完成三个字段的生成,避免对DataFrame做三次遍历,提升运行效率,两种实现方式可选:
方式1:异常捕获(兼容性最强)
import pyzipcode from pyzipcode import ZipCodeDatabase import numpy as np import pandas as pd zipDB = ZipCodeDatabase() def get_zip_info(zip_code): try: zip_info = zipDB[int(zip_code)] return pd.Series([zip_info.state, zip_info.latitude, zip_info.longitude]) except KeyError: # 未查询到的邮编对应字段返回NaN return pd.Series([np.nan, np.nan, np.nan]) dfZ[['State', 'LAT', 'LNG']] = dfZ['Zip'].apply(get_zip_info)
方式2:调用库内置get方法(代码更直观)
从报错的源码可以看到库内置了get方法,查询不到会返回None,不会抛异常,也可以直接用这个方法实现逻辑:
import pyzipcode from pyzipcode import ZipCodeDatabase import numpy as np import pandas as pd zipDB = ZipCodeDatabase() def get_zip_info(zip_code): # 邮编统一转成补零到5位的字符串,符合库的查询规则 zip_str = str(zip_code).zfill(5) zip_info = zipDB.get(zip_str) if zip_info: return pd.Series([zip_info.state, zip_info.latitude, zip_info.longitude]) return pd.Series([np.nan, np.nan, np.nan]) dfZ[['State', 'LAT', 'LNG']] = dfZ['Zip'].apply(get_zip_info)
如果要保留你原来三次单独赋值的写法,可以把lambda表达式改写成如下形式:
dfZ['State'] = dfZ['Zip'].apply(lambda x: zipDB[int(x)].state if zipDB.get(str(x).zfill(5)) else np.nan) dfZ['LAT'] = dfZ['Zip'].apply(lambda x: zipDB[int(x)].latitude if zipDB.get(str(x).zfill(5)) else np.nan) dfZ['LNG'] = dfZ['Zip'].apply(lambda x: zipDB[int(x)].longitude if zipDB.get(str(x).zfill(5)) else np.nan)
注意这种写法会对每个邮编重复查询三次,数据量大的时候效率更低,不推荐。
内容的提问来源于stack exchange,提问作者ponnob
相关产品推荐
相关产品推荐

