我正在使用Python3,并且有一个看起来像熊猫的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
有人可以帮助解决该错误吗?
答案 0 :(得分:0)
调用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
的{{1}}参数,即可坚持只有9MB的“简单”版本。
接下来,这真的会很慢。 SearchEngine()
在幕后使用一个简单的循环,对于每一行,.apply()
方法将使用SQLAlchemy查询SQLite数据库,创建一个具有匹配行中所有列的单个结果对象,然后返回该对象,这样您就可以从它们中获得单个属性。
最好使用Pandas SQL methods直接查询数据库。 .by_zipcode()
软件包在这里仍然有用,因为它可以为您下载数据库并创建SQLAlchemy会话,SearchEngine.ses
attribute可以让您直接访问它,但是从那里我可以做:
uszipcode
创建一个Pandas Dataframe,其中所有唯一的邮政编码都映射到city和state列。然后,您可以join your dataframe with the zipcode dataframe:
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')
这会将df = pd.merge(df, zipcode_df, how='left', left_on='zip', right_index=True)
和city
列添加到原始数据框中。如果需要拉入更多列,请将它们添加到state
部分,使用search.ses.query(...)
在输出数据框中为它们提供合适的列名称(如果没有.label()
,它们将前缀为.label()
或simple_zipcode_
(取决于您使用的类)。从model attributes documented中选择,但是要考虑到,如果您需要访问full Zipcode
model attributes,则需要使用zipcode_
以确保可以使用完整的450MB数据集,然后使用{{ 1}},而不是查询中的SearchEngine(simple_zipcode=False)
。
使用邮政编码作为Zipcode.<column>.label(...)
数据框中的索引,这将比在每一行上单独使用SQLAlchemy快得多( zippier :-)。