我正在使用Python3并且有一个看起来像的pandas df
zip
0 07105
1 00000
2 07030
3 07032
4 07032
我想使用我正在使用的包uszipcode添加州和城市
import uszipcode
search = SearchEngine(simple_zipcode=False)
def zco(x):
print(search.by_zipcode(x)['City'])
df['City'] = df[['zip']].fillna(0).astype(int).apply(zco)
但是,我收到以下错误
TypeError: 'Zipcode' object is not subscriptable
有人可以帮助解决错误吗?
调用search.by_zipcode(x)
返回ZipCode()
instance,而不是字典,因此将['City']
应用于该对象失败。
相反,使用较短别名的.major_city
属性,.city
attribute;你想要返回该值,而不是打印它:
def zco(x):
return search.by_zipcode(x).city
如果您要使用uszipcode
项目将邮政编码映射到州和城市名称,则无需使用完整数据库(450MB下载)。通过省略simple_zipcode=False
的SearchEngine()
论证,坚持使用'简单'版本,只有9MB。
接下来,这真的很慢。 .apply()
在引擎盖下使用一个简单的循环,对于每一行,.by_zipcode()
方法将使用SQLAlchemy查询SQLite数据库,使用匹配行中的所有列创建单个结果对象,然后返回该对象,这样就可以获得单个来自他们的属性。
使用Pandas SQL methods直接查询数据库会好得多。 uszipcode
包在这里仍然有用,因为它处理为你下载数据库并创建一个SQLAlchemy会话,SearchEngine.ses
attribute让你直接访问它,但从那里我只是做:
from uszipcode import SearchEngine, SimpleZipcode
search = SearchEngine()
query = (
search.ses.query(
SimpleZipcode.zipcode.label('zip'),
SimpleZipcode.major_city.label('city'),
SimpleZipcode.state.label('state'),
).filter(
SimpleZipcode.zipcode.in_(df['zip'].dropna().unique())
)
).selectable
zipcode_df = pd.read_sql_query(query, search.ses.connection(), index_col='zip')
创建一个Pandas Dataframe,其中所有唯一的zipcode都映射到city和state列。你可以然后join your dataframe with the zipcode dataframe:
df = pd.merge(df, zipcode_df, how='left', left_on='zip', right_index=True)
这会将city
和state
列添加到原始数据框中。如果你需要引入更多的列,将它们添加到search.ses.query(...)
部分,使用.label()
在输出数据框中为它们提供合适的列名称(没有.label()
,它们将以simple_zipcode_
或zipcode_
为前缀,具体取决于您的类别使用)。从model attributes documented中选择,但考虑到如果你需要访问full Zipcode
model attributes,你需要使用SearchEngine(simple_zipcode=False)
来确保你获得完整的450MB数据集,然后在查询中使用Zipcode.<column>.label(...)
而不是SimpleZipcode.<column>.label(...)
。
使用zipcodes作为zipcode_df
数据帧中的索引,这比单独在每一行上使用SQLAlchemy要快得多(zippier :-))。