从Excel中Twitter字符串子串提取坐标及CSV特征拆分技术求助
嘿,针对你手里百万级Twitter CSV文件提取坐标的需求,我给你整理了一套高效又靠谱的解决方案,咱们一步步来:
核心思路:正则精准匹配 + 大文件高效处理
百万行数据最忌讳一次性读进内存,所以优先用分块/逐行处理的方式,再结合正则表达式精准抓取推文里的坐标信息。
第一步:先搞定坐标的正则匹配规则
推文里的坐标一般有几种常见格式,咱们把它们都覆盖到:
- 普通十进制坐标对:
40.7128,-74.0060或者(40.7128, -74.0060) - Twitter原生GeoJSON格式:
{"type":"Point","coordinates":[-74.0060, 40.7128]}(注意这里是经度在前,纬度在后,别搞反!)
对应的正则表达式可以这么写:
import re # 匹配普通坐标对(纬度,经度 或带括号的格式) basic_coord_pattern = re.compile(r'(\-?\d+\.\d+)\s*,\s*(\-?\d+\.\d+)') # 匹配Twitter的GeoJSON坐标格式 geojson_coord_pattern = re.compile(r'"coordinates":\s*\[(\-?\d+\.\d+),\s*(\-?\d+\.\d+)\]')
解释下:\-?负责匹配正负号,\d+\.\d+匹配十进制数字,\s*用来忽略逗号前后的空格,兼容各种排版情况。
第二步:高效处理百万行CSV文件
方法1:用Pandas分块读取(推荐,代码简洁易维护)
Pandas的chunksize参数可以让我们分批次读文件,避免内存溢出:
import pandas as pd # 定义坐标提取函数 def extract_coordinates(text): text_str = str(text) # 先尝试匹配GeoJSON格式 geojson_match = geojson_coord_pattern.search(text_str) if geojson_match: # GeoJSON是[经度,纬度],所以要调换顺序 lon = float(geojson_match.group(1)) lat = float(geojson_match.group(2)) return pd.Series([lat, lon], index=['latitude', 'longitude']) # 再匹配普通坐标对 basic_match = basic_coord_pattern.search(text_str) if basic_match: lat = float(basic_match.group(1)) lon = float(basic_match.group(2)) # 可选:验证坐标范围(纬度-90~90,经度-180~180) if -90 <= lat <=90 and -180 <= lon <=180: return pd.Series([lat, lon], index=['latitude', 'longitude']) # 没匹配到就返回空值 return pd.Series([None, None], index=['latitude', 'longitude']) # 分块处理,每块10000行(可根据你的内存情况调整) chunk_size = 10000 output_file = "processed_tweets.csv" for chunk in pd.read_csv("your_raw_tweets.csv", chunksize=chunk_size, encoding="utf-8"): # 假设合并特征的列名叫"merged_features",替换成你实际的列名 chunk[["latitude", "longitude"]] = chunk["merged_features"].apply(extract_coordinates) # 把处理后的块追加到输出文件,第一次写的时候加表头 chunk.to_csv( output_file, mode="a", header=not pd.io.common.file_exists(output_file), index=False, encoding="utf-8" )
方法2:用Python内置CSV模块(更轻量,适合极端大文件)
如果Pandas还是占内存,就用原生CSV模块逐行读写,完全不占大内存:
import csv with open("your_raw_tweets.csv", "r", newline="", encoding="utf-8") as infile, \ open("processed_tweets.csv", "w", newline="", encoding="utf-8") as outfile: reader = csv.DictReader(infile) # 给输出文件新增纬度、经度列 fieldnames = reader.fieldnames + ["latitude", "longitude"] writer = csv.DictWriter(outfile, fieldnames=fieldnames) writer.writeheader() for row in reader: text = row["merged_features"] lat, lon = None, None # 先匹配GeoJSON geojson_match = geojson_coord_pattern.search(str(text)) if geojson_match: lon = geojson_match.group(1) lat = geojson_match.group(2) else: # 匹配普通坐标 basic_match = basic_coord_pattern.search(str(text)) if basic_match: lat = basic_match.group(1) lon = basic_match.group(2) # 可选:验证坐标范围 try: lat_float = float(lat) lon_float = float(lon) if not (-90 <= lat_float <=90 and -180 <= lon_float <=180): lat, lon = None, None except: lat, lon = None, None row["latitude"] = lat row["longitude"] = lon writer.writerow(row)
第三步:优化与验证
- 测试正则:先拿几十行样本数据跑一遍,确保能匹配到所有出现的坐标格式,比如有没有带特殊符号、空格多的情况,随时调整正则。
- 异常处理:上面的代码里已经加了基础的异常处理,避免因为格式错误的坐标导致程序崩溃。
- 加速处理:如果机器有多核,可以用
swifter库加速Pandas的apply操作,只需要把chunk["merged_features"].apply(extract_coordinates)改成chunk["merged_features"].swifter.apply(extract_coordinates)就行。
内容的提问来源于stack exchange,提问作者Christopher Loynes
相关产品推荐
相关产品推荐

