You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用lru_cache缓存地址经纬度解析结果时遇列长度不匹配错误

问题:地址解析经纬度时缓存报错ValueError: Columns must be same length as key

问题场景

需要从DataFrame的地址列提取经纬度,同时用lru_cache缓存已解析的地址结果以避免重复调用地理编码接口,但运行代码时触发上述错误。

原始DataFrame

address  customer
0              Surlej, 7513, Silvaplana, Schweiz         1
1  Vodnikova cesta 35, 1000 Ljubljana, Slowenien         2
2              Surlej, 7513, Silvaplana, Schweiz         1

原始代码

from functools import lru_cache
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent='testing_stackoverflow')

import pandas as pd
d = {
    "address": ['Surlej, 7513, Silvaplana, Schweiz', 'Vodnikova cesta 35, 1000 Ljubljana, Slowenien', 'Surlej, 7513, Silvaplana, Schweiz',],
    "customer": [1, 2, 1],
}
df = pd.DataFrame(data=d)
print(df)

@lru_cache(maxsize=None)
def function_that_returns_lat_lon_from_address(address):
    location = geolocator.geocode(address, timeout=10)
    print(location)
    try:
        if (location == None):
            return(None, None)
        else:
            return (location.latitude, location.longitude)
    except GeocoderTimedOut as e:
        print("Timeout ", e)
        return(None, None)

df[['lat', 'lon']] = df['address'].apply(function_that_returns_lat_lon_from_address)

期望输出

address  customer        lat       lon
0              Surlej, 7513, Silvaplana, Schweiz         1  46.459902   9.803370
1  Vodnikova cesta 35, 1000 Ljubljana, Slowenien         2  46.065523  14.490775
2              Surlej, 7513, Silvaplana, Schweiz         1  46.459902   9.803370

报错信息

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-8-4873cdd27090> in <module>()
     24         return(None, None)
     25 
---> 26 df[['lat', 'lon']] = df['address'].apply(function_that_returns_lat_lon_from_address)

2 frames
/usr/local/lib/python3.7/dist-packages/pandas/core/frame.py in _iset_not_inplace(self, key, value)
   3673         if self.columns.is_unique:
   3674             if np.shape(value)[-1] != len(key):
-> 3675                 raise ValueError("Columns must be same length as key")
   3676 
   3677             for i, col in enumerate(key):

ValueError: Columns must be same length as key

错误原因

df['address'].apply()返回的是元素为元组的Series,直接赋值给多列时,pandas无法自动将元组拆分为对应列的数值。此外,原代码未导入GeocoderTimedOut异常类,会导致额外报错。

解决方法

  1. 将apply的结果转换为pd.Series,让pandas自动拆分元组为多列
  2. 导入缺失的GeocoderTimedOut异常类
  3. 保留lru_cache的缓存逻辑,确保重复地址只查询一次

修正后的完整代码

from functools import lru_cache
from geopy.geocoders import Nominatim
from geopy.exc import GeocoderTimedOut  # 导入缺失的异常类
geolocator = Nominatim(user_agent='testing_stackoverflow')

import pandas as pd
d = {
    "address": ['Surlej, 7513, Silvaplana, Schweiz', 'Vodnikova cesta 35, 1000 Ljubljana, Slowenien', 'Surlej, 7513, Silvaplana, Schweiz',],
    "customer": [1, 2, 1],
}
df = pd.DataFrame(data=d)

@lru_cache(maxsize=None)
def get_lat_lon(address):
    location = geolocator.geocode(address, timeout=10)
    try:
        if location is None:
            return (None, None)
        return (location.latitude, location.longitude)
    except GeocoderTimedOut:
        print(f"地址 {address} 解析超时")
        return (None, None)

# 将apply结果转为Series,自动拆分到两列
df[['lat', 'lon']] = df['address'].apply(get_lat_lon).apply(pd.Series)

print(df)

运行结果

address  customer        lat       lon
0              Surlej, 7513, Silvaplana, Schweiz         1  46.459902   9.803370
1  Vodnikova cesta 35, 1000 Ljubljana, Slowenien         2  46.065523  14.490775
2              Surlej, 7513, Silvaplana, Schweiz         1  46.459902   9.803370

内容的提问来源于stack exchange,提问作者Test

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:01:04