Вызов search.by_zipcode(x)
возвращает ZipCode()
экземпляр , а не словарь, поэтому применение ['City']
к этому объекту завершается неудачей.
Вместо этого используйте атрибут .major_city
с более коротким псевдонимом, атрибут .city
; Вы хотите вернуть это значение, а не распечатать его:
def zco(x):
return search.by_zipcode(x).city
Если все, что вы собираетесь использовать для проекта uszipcode
, - это сопоставление почтовых индексов с названиями штатов и городов, вам не нужно использовать полную базу данных (загрузка 450 МБ). Просто придерживайтесь «простой» версии, которая составляет всего 9 МБ, оставив аргумент simple_zipcode=False
в SearchEngine()
.
Далее, это будет действительно очень медленно . .apply()
использует простой цикл под капотом, и для каждой строки метод .by_zipcode()
будет запрашивать базу данных SQLite с помощью SQLAlchemy, создавать один объект результата со всеми столбцами из соответствующей строки, а затем возвращать этот объект, просто чтобы вы может получить от них один атрибут.
Вы бы лучше обращались к базе данных напрямую, используя методы Pandas SQL . Пакет uszipcode
все еще полезен здесь, так как он обрабатывает загрузку базы данных для вас и создание сеанса SQLAlchemy, атрибут SearchEngine.ses
дает вам прямой доступ к нему, но оттуда я бы просто сделал:
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')
чтобы создать Dataframe Pandas со всеми вашими уникальными почтовыми индексами, сопоставленными со столбцами города и штата. Затем вы можете присоединить ваш фрейм данных к фрейму данных почтового индекса :
df = pd.merge(df, zipcode_df, how='left', left_on='zip', right_index=True)
Это добавляет столбцы city
и state
к исходному кадру данных. Если вам нужно добавить больше столбцов, добавьте их в часть search.ses.query(...)
, используя .label()
, чтобы дать им подходящее имя столбца в выходном фрейме данных (без .label()
, они получат префикс simple_zipcode_
или zipcode_
, в зависимости от класса, который вы используете). Выберите из атрибутов модели, задокументированных , но учтите, что если вам нужен доступ к full Zipcode
атрибутам модели , вам нужно использовать SearchEngine(simple_zipcode=False)
, чтобы получить полные 450 МБ набор данных в вашем распоряжении, затем используйте Zipcode.<column>.label(...)
вместо SimpleZipcode.<column>.label(...)
в запросе.
С почтовыми индексами в качестве индекса в кадре данных zipcode_df
это будет намного быстрее ( zippier :-)), чем использование SQLAlchemy для каждой строки в отдельности.