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

基于Python/JavaScript计算300万条经纬度的S2单元格并转十六进制

处理CSV数据并生成S2单元格(含十进制转十六进制)

作为刚接触Python和JavaScript的新手,处理300万条CSV数据确实得找高效靠谱的方法,我来帮你一步步搞定S2单元格的计算和格式转换~


一、JavaScript方案(基于s2-geometry库)

1. 先安装依赖

要处理CSV和S2计算,需要两个npm包:

npm install s2-geometry csv-parser fs

2. 核心代码(包含十进制转十六进制函数)

300万条数据不能一次性加载到内存,所以我们用流式处理来避免内存溢出。代码里已经集成了十进制转十六进制的逻辑,还可以自定义S2单元格的层级(比如下面的S2_LEVEL = 10,你可以根据需求调整):

const fs = require('fs');
const csv = require('csv-parser');
const { S2 } = require('s2-geometry');

// 自定义S2单元格层级,可根据业务需求修改
const S2_LEVEL = 10;

// 十进制S2 Cell ID转十六进制的函数(补全到16位大写格式)
function decimalToHexS2(decimalId) {
    let hex = decimalId.toString(16);
    return hex.padStart(16, '0').toUpperCase();
}

// 创建写入流,输出带S2信息的新CSV
const writeStream = fs.createWriteStream('output_with_s2.csv');
// 先写入表头
writeStream.write('lat,lon,s2_cell_id_decimal,s2_cell_id_hex\n');

// 流式读取原始CSV,逐行处理
fs.createReadStream('input.csv')
    .pipe(csv())
    .on('data', (row) => {
        try {
            // 解析纬度和经度(确保转为数字类型)
            const lat = parseFloat(row.lat);
            const lng = parseFloat(row.lon);

            // 计算S2 Cell的十进制ID
            const cellId = S2.latLngToKey(lat, lng, S2_LEVEL);
            // 转成标准十六进制格式
            const cellIdHex = decimalToHexS2(cellId);

            // 组装新行并写入文件
            const newRow = `${lat},${lng},${cellId},${cellIdHex}\n`;
            writeStream.write(newRow);
        } catch (err) {
            console.error(`处理行失败: ${JSON.stringify(row)}`, err);
        }
    })
    .on('end', () => {
        writeStream.end();
        console.log('所有数据处理完成,已生成output_with_s2.csv');
    })
    .on('error', (err) => {
        console.error('读取CSV出错:', err);
    });

3. 关键说明

  • 流式处理:csv-parser会逐行读取CSV,不会一次性加载300万条数据,避免内存不足
  • 十六进制转换:确保输出的是16位大写字符串,符合S2官方的格式规范
  • 错误处理:如果某行数据格式异常(比如lat/lon不是数字),会打印错误但不中断整个流程

二、Python方案(适合Python新手)

如果你更习惯用Python,可以用s2sphere库实现,同样用分块读取处理大文件:

1. 安装依赖

pip install s2sphere pandas

2. 核心代码

import pandas as pd
import s2sphere

# 自定义S2单元格层级
S2_LEVEL = 10

def decimal_to_hex_s2(decimal_id):
    # 直接生成16位大写十六进制字符串
    return format(decimal_id, '016X')

# 分块读取CSV,每块处理10000行(可根据内存大小调整)
chunk_size = 10000
output_file = 'output_with_s2_python.csv'

# 先写入表头
with open(output_file, 'w', encoding='utf-8') as f:
    f.write('lat,lon,s2_cell_id_decimal,s2_cell_id_hex\n')

# 逐块处理数据并追加写入
for chunk in pd.read_csv('input.csv', chunksize=chunk_size):
    # 计算S2十进制ID
    chunk['s2_cell_id_decimal'] = chunk.apply(
        lambda row: s2sphere.CellId.from_lat_lng(
            s2sphere.LatLng.from_degrees(row['lat'], row['lon'])
        ).parent(S2_LEVEL).id(),
        axis=1
    )
    # 转换为十六进制
    chunk['s2_cell_id_hex'] = chunk['s2_cell_id_decimal'].apply(decimal_to_hex_s2)
    
    # 追加写入到输出文件
    chunk.to_csv(output_file, mode='a', header=False, index=False, encoding='utf-8')

print('所有数据处理完成,已生成output_with_s2_python.csv')

3. 关键说明

  • 分块读取:pandas.read_csv的chunksize参数让我们每次只处理一小部分数据,适配大文件
  • 层级控制:通过parent(S2_LEVEL)指定单元格层级,逻辑直观易懂
  • 格式转换:用Python内置的format函数直接生成标准十六进制字符串

注意事项

  • S2层级选择:层级越高,单元格越小(比如层级20对应极小区域,层级10对应较大区域),请根据业务需求调整S2_LEVEL
  • 数据校验:确保CSV里的lat和lon是有效的十进制数字,否则会触发错误
  • 性能提示:300万条数据处理可能需要几分钟,耐心等待即可,不要中途中断程序

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:47:09