Pandas处理百万行数据时经纬度转换遇字符串异常问题求助
解决方案:处理百万行DataFrame的度分转度数格式问题
咱们先拆解下你遇到的核心问题:
- 数据里的
p-这类异常字符串,直接导致转float失败; - 清理后部分行的lat/lon字符串长度不足,触发
IndexError; - 额外提个隐藏坑:用
iterrows()遍历百万行数据效率极低,会拖慢整个处理流程,得换成矢量化操作。
第一步:数据预处理,清理异常值与统一格式
先把所有干扰字符(包括p-、多余符号、标识前缀)清理干净,同时把无效空字符串标记为NaN,避免后续转换报错:
import pandas as pd import numpy as np import glob # 读取文件部分保留你的逻辑,用concat替代append提升效率 path = r'/home/engr/Documents/SchoolHR/Data/SFSU-Boat/SBE45m/2015/' allfiles_list = sorted(glob.glob(path + "/15*.hex")) col = ["temp", "conduct", "salinity", "lat", "lon", "hms", "dmy"] big_frame = pd.DataFrame() for name in allfiles_list: df = pd.read_csv(name, skiprows=12, encoding="latin1", names=col, na_values=0, na_filter=False, engine="c") big_frame = pd.concat([big_frame, df], ignore_index=True) # 清理各列的前缀标识(比如t1=、lat=这类) big_frame["temp"] = big_frame["temp"].str.replace(r'^t1=\s*', '', regex=True) big_frame["conduct"] = big_frame["conduct"].str.replace(r'^c1=\s*', '', regex=True) big_frame["salinity"] = big_frame["salinity"].str.replace(r'^s=\s*', '', regex=True) big_frame["lat"] = big_frame["lat"].str.replace(r'^lat=\s*', '', regex=True) big_frame["lon"] = big_frame["lon"].str.replace(r'^lon=\s*', '', regex=True) # 处理异常值:替换p-、括号,空字符串转NaN big_frame['lat'] = big_frame['lat'].str.replace(r'p-?|\)', '', regex=True).str.strip() big_frame['lon'] = big_frame['lon'].str.replace(r'p-?|\)', '', regex=True).str.strip() big_frame['lat'] = big_frame['lat'].replace('', np.nan) big_frame['lon'] = big_frame['lon'].replace('', np.nan) # 转换数值列 big_frame[["temp", "conduct", "salinity"]] = big_frame[["temp", "conduct", "salinity"]].astype(float)
第二步:矢量化转换函数,替代低效循环
写一个专门的度分转度数函数,处理有效格式的同时捕获异常情况(比如无方向标识、格式错误),再用apply()批量处理:
def dms_to_dd(coord_str): if pd.isna(coord_str): return np.nan # 拆分方向和数值部分 direction = coord_str[-1].upper() coord_part = coord_str[:-1].strip() # 拆分度和分(空格分隔) parts = coord_part.split() if len(parts) != 2: return np.nan # 格式无效,返回NaN try: degrees = float(parts[0]) minutes = float(parts[1]) dd = degrees + minutes / 60 # 根据方向调整正负 if direction in ['S', 'W']: dd = -dd return dd except ValueError: return np.nan # 数值转换失败,返回NaN # 应用转换函数到lat和lon列 big_frame['lat_dd'] = big_frame['lat'].apply(dms_to_dd) big_frame['lon_dd'] = big_frame['lon'].apply(dms_to_dd)
关键说明
- 效率优化:用
pd.concat()替代append(),用apply()替代iterrows(),百万行数据的处理速度会提升一个数量级; - 异常容错:所有无效格式、转换失败的情况都会返回
NaN,不会中断程序,后续你可以用big_frame[big_frame['lat_dd'].isna()]查看无效数据,针对性处理; - 格式兼容:函数支持标准的度分格式(比如
37 46.985 N),同时能处理清理后的异常行。
用你提供的样本数据测试,转换后的lat_dd和lon_dd会得到正确的十进制度数,比如第一行的lat会转为37.783083,lon转为-122.259067。
内容的提问来源于stack exchange,提问作者Earthly
相关产品推荐
相关产品推荐

