技术问询:地理坐标按国家分类存CSV及无GIS库添加绘图山脉
一、地理坐标按国家分类并保存为单独CSV
步骤说明
- 坐标格式转换:将
N/S/E/W格式的坐标转为十进制经纬度数值(北纬、东经为正,南纬、西经为负)。 - 离线国家匹配:使用免费公开的国家边界数据集(如自然地球1:110m分辨率国家边界),通过射线法判断坐标所属国家。
- 分组与保存:按国家分组后,将每组数据写入单独的CSV文件。
代码实现
import csv import json # 坐标转换函数 def convert_coordinate(lat_str, lon_str): lat = float(lat_str[:-1]) if lat_str.endswith('S'): lat = -lat lon = float(lon_str[:-1]) if lon_str.endswith('W'): lon = -lon return lat, lon # 射线法判断点是否在多边形内 def point_in_polygon(point, polygon): x, y = point inside = False n = len(polygon) for i in range(n): j = (i + 1) % n xi, yi = polygon[i] xj, yj = polygon[j] if ((yi > y) != (yj > y)): x_intersect = (y - yi) * (xj - xi) / (yj - yi) + xi if x <= x_intersect: inside = not inside return inside # 加载本地国家边界GeoJSON数据(自然地球1:110m国家数据集) with open('countries.geojson', 'r', encoding='utf-8') as f: countries_data = json.load(f) # 待处理的坐标数据 input_data = [ "Koforidua_ANUC,6.109N,0.302W", "Kuching,1.491N,110.349E", "Kuopio,62.892N,27.634E", "Kuwait_University,29.325N,47.971E" ] # 按国家分组存储数据 country_groups = {} for line in input_data: name, lat_str, lon_str = line.split(',') lat, lon = convert_coordinate(lat_str, lon_str) # 遍历国家边界匹配所属国家 for feature in countries_data['features']: country_name = feature['properties']['NAME'] geometry = feature['geometry'] # 处理多边形和多多边形类型 if geometry['type'] == 'Polygon': polygons = [geometry['coordinates'][0]] elif geometry['type'] == 'MultiPolygon': polygons = [poly[0] for poly in geometry['coordinates']] else: continue # 检查点是否在当前国家的任意多边形内 for poly in polygons: if point_in_polygon((lon, lat), poly): country_groups.setdefault(country_name, []).append([name, lat, lon]) break else: continue break # 保存每个国家的CSV文件 for country, points in country_groups.items(): safe_filename = country.replace(' ', '_').replace('/', '_') with open(f'{safe_filename}_coordinates.csv', 'w', newline='', encoding='utf-8') as csvfile: writer = csv.writer(csvfile) writer.writerow(['Name', 'Latitude', 'Longitude']) writer.writerows(points)
补充说明
- 自然地球1:110m国家边界数据可免费下载后保存为本地
countries.geojson文件使用。 - 若坐标数据量极小,也可手动匹配国家后直接分组,跳过点在多边形判断步骤。
二、不使用GeoPandas添加区域山脉至绘图
步骤说明
- 获取离线山脉数据:使用自然地球免费公开的山脉矢量数据(如1:110m分辨率山脊线)。
- 读取解析数据:用纯Python读取GeoJSON格式的山脉数据,提取坐标信息。
- 叠加山脉绘图:在matplotlib中绘制山脉线条,再叠加自定义坐标点。
代码实现(以matplotlib为例)
import json import matplotlib.pyplot as plt # 加载本地山脊线GeoJSON数据(自然地球1:110m山脊线数据集) with open('ridges.geojson', 'r', encoding='utf-8') as f: ridges_data = json.load(f) # 初始化绘图 fig, ax = plt.subplots(figsize=(10, 8)) # 绘制山脉山脊线 for feature in ridges_data['features']: geometry = feature['geometry'] if geometry['type'] == 'LineString': lons, lats = zip(*geometry['coordinates']) ax.plot(lons, lats, color='#888888', linewidth=0.8) elif geometry['type'] == 'MultiLineString': for line in geometry['coordinates']: lons, lats = zip(*line) ax.plot(lons, lats, color='#888888', linewidth=0.8) # 叠加自定义坐标点 input_points = [ (6.109, -0.302), # Koforidua_ANUC (1.491, 110.349), # Kuching (62.892, 27.634), # Kuopio (29.325, 47.971) # Kuwait_University ] lats, lons = zip(*input_points) ax.scatter(lons, lats, color='red', marker='o', label='Your Points') # 绘图配置 ax.set_xlabel('Longitude') ax.set_ylabel('Latitude') ax.set_title('Map with Mountains') ax.legend() plt.show()
补充说明
- 自然地球还提供山脉多边形等数据,可根据需求选择下载。
- 若使用Shapefile格式数据,可使用纯Python库
pyshp读取,无需依赖GeoPandas。
内容的提问来源于stack exchange,提问作者S.Kociok
相关产品推荐
相关产品推荐

