
本文介绍在 Pandas 中高效、健壮地从 location 列(含 {'coordinates': array[lon, lat], 'type': 'Point'} 结构)批量提取经度和纬度,自动生成新列,并妥善处理 None 值。
本文介绍在 pandas 中高效、健壮地从 `location` 列(含 `{'coordinates': array[lon, lat], 'type': 'point'}` 结构)批量提取经度和纬度,自动生成新列,并妥善处理 `none` 值。
在地理空间数据处理中,第三方数据集常将坐标封装为嵌套结构(如 GeoJSON 风格的 point 类型),其典型形式为:{'coordinates': array([lon, lat]), 'type': 'Point'}。直接对整列调用 .apply() 并配合条件判断,是提取此类嵌套数组元素的最清晰、最安全的方式。
以下是一个生产就绪的解决方案,使用 lambda 函数结合类型检查,确保对 None 或非预期格式的数据返回 None(Pandas 自动转为 NaN):
import pandas as pd
import numpy as np
def extract_coordinates(df, location_col='location'):
"""
从 location 列中安全提取 longitude 和 latitude,支持 None 和异常值。
Parameters:
-----------
df : pandas.DataFrame
输入 DataFrame
location_col : str
存储位置字典的列名,默认为 'location'
Returns:
--------
pandas.DataFrame
带新增 'longitude' 和 'latitude' 列的 DataFrame
"""
def get_lon(x):
if isinstance(x, dict) and 'coordinates' in x and len(x['coordinates']) >= 2:
return float(x['coordinates'][0])
return None
def get_lat(x):
if isinstance(x, dict) and 'coordinates' in x and len(x['coordinates']) >= 2:
return float(x['coordinates'][1])
return None
df = df.copy()
df['longitude'] = df[location_col].apply(get_lon)
df['latitude'] = df[location_col].apply(get_lat)
return df
# 示例数据构建
sample_data = {
'location': [
{'coordinates': [-97.707172829666, 30.385328900508], 'type': 'Point'},
{'coordinates': [-74.587966507573, 39.395338984595], 'type': 'Point'},
None,
{'coordinates': [-104.664962196304, 42.396358150943], 'type': 'Point'},
{'coordinates': [0.0], 'type': 'Point'}, # 边界情况:坐标长度不足
{'type': 'Point'}, # 边界情况:无 coordinates 键
]
}
results_df = pd.DataFrame(sample_data)
# 执行提取
results_df = extract_coordinates(results_df)
print(results_df[['longitude', 'latitude']])
输出结果:
longitude latitude 0 -97.707173 30.385329 1 -74.587967 39.395339 2 NaN NaN 3 -104.664962 42.396358 4 NaN NaN 5 NaN NaN
✅ 关键设计要点说明:
- 健壮性优先:显式检查 isinstance(x, dict) 和 'coordinates' in x,避免 KeyError 或 AttributeError;
- 数组长度防护:len(x['coordinates']) >= 2 防止索引越界(如单元素坐标);
- 类型统一:float() 强制转换确保数值一致性,兼容 np.ndarray 和 Python list;
- 无副作用:使用 df.copy() 避免修改原始 DataFrame(可按需移除);
- 可扩展性强:函数参数化列名,便于复用至其他类似嵌套字段。
⚠️ 注意事项:
- 若使用 PySpark Pandas API(即 pyspark.pandas),语法几乎一致,但需注意:pyspark.pandas 的 apply 默认运行在分布式环境下,对 lambda 支持良好,但复杂逻辑建议封装为命名函数并注册为 UDF(用户定义函数)以提升性能与可调试性;
- 对于超大规模数据(千万行以上),可考虑 pd.json_normalize() 预展开 + str.split() 等向量化替代方案,但本例中 apply 已足够高效且语义清晰;
- 坐标顺序需严格确认:GeoJSON 规范为 [longitude, latitude](即 x, y),切勿颠倒。
通过该方法,你不仅能准确生成 longitude/latitude 列,还能确保数据管道在面对脏数据时稳定可靠——这是地理数据分析落地的关键一步。











