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

Golang中Gota DataFrame读取CSV/JSON差异及Excel转DataFrame问询

问题说明
  • 用Golang的Gota库时,dataframe.ReadJSON()和dataframe.ReadCSV()读取同一份数据生成的DataFrame存在差异,目前能看到的是列顺序颠倒,不排除还有其他未知差异
  • 项目要求JSON转出来的DataFrame必须和CSV版本完全一致
  • 当前工作流程:
    1. 判断文件是xlsx还是csv
    2. 用对应方式转成DataFrame
    3. 把DataFrame传给processDF()函数处理
  • 用到的库:xlsxreader、gota/dataframe、excel2json
解决方法

一、对齐JSON与CSV生成的DataFrame

核心问题:列顺序不统一

JSON的键是无序的,dataframe.ReadJSON()会按字典序排列列;而CSV是按文件里的顺序读取列。要让两者对齐,只需要:

  1. 先读CSV拿到标准列顺序
  2. 读JSON生成DataFrame后,按这个标准顺序重新排列列

其他潜在差异处理

  • 数据类型:JSON的数值可能被解析成float,CSV可能推断为int,可以通过dataframe.ReadOption强制统一类型
  • 空值处理:用dataframe.WithNaN()之类的选项,确保JSON和CSV的空值解析逻辑一致

二、直接把Excel转成Gota DataFrame(绕开JSON中转)

如果不想折腾JSON和CSV的差异,直接用xlsxreader读取Excel内容,手动构建DataFrame就行,步骤如下:

  1. 用xlsxreader打开Excel,读取目标工作表
  2. 读取表头作为列名
  3. 逐行读取单元格数据,转成Gota支持的series.Series
  4. 用列名和对应的Series构建DataFrame
代码示例

1. 让JSON生成的DataFrame对齐CSV的列顺序

package main

import (
	"os"
	"github.com/go-gota/gota/dataframe"
)

// 获取CSV的列顺序,作为标准参考
func getCSVColumnOrder(csvPath string) []string {
	f, err := os.Open(csvPath)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	csvDF := dataframe.ReadCSV(f)
	return csvDF.Names()
}

// 读取JSON并按指定列顺序重新排列
func jsonToAlignedDF(jsonPath string, columnOrder []string) dataframe.DataFrame {
	f, err := os.Open(jsonPath)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	jsonDF := dataframe.ReadJSON(f)
	// 按CSV的列顺序重新选择列
	return jsonDF.Select(columnOrder)
}

func main() {
	csvPath := "data.csv"
	jsonPath := "data.json"
	
	colOrder := getCSVColumnOrder(csvPath)
	alignedDF := jsonToAlignedDF(jsonPath, colOrder)
	processDF(alignedDF)
}

func processDF(df dataframe.DataFrame) {
	// 这里写你的DataFrame处理逻辑
}

2. 直接读取Excel生成Gota DataFrame

package main

import (
	"fmt"
	"github.com/go-gota/gota/dataframe"
	"github.com/go-gota/gota/series"
	"github.com/tealeg/xlsx"
)

// 把Excel文件转成Gota DataFrame,sheetIndex是工作表下标(从0开始)
func excelToDF(excelPath string, sheetIndex int) (dataframe.DataFrame, error) {
	xlFile, err := xlsx.OpenFile(excelPath)
	if err != nil {
		return dataframe.DataFrame{}, err
	}
	if sheetIndex >= len(xlFile.Sheets) {
		return dataframe.DataFrame{}, fmt.Errorf("指定的工作表下标超出范围")
	}
	sheet := xlFile.Sheets[sheetIndex]

	// 读取表头作为列名
	var colNames []string
	headerRow := sheet.Rows[0]
	for _, cell := range headerRow.Cells {
		colNames = append(colNames, cell.String())
	}

	// 按列收集数据,准备构建Series
	colData := make([][]interface{}, len(colNames))
	for rowIdx := 1; rowIdx < len(sheet.Rows); rowIdx++ {
		row := sheet.Rows[rowIdx]
		for cellIdx, cell := range row.Cells {
			if cellIdx >= len(colNames) {
				continue // 跳过超出表头列数的单元格
			}
			// 这里默认转成字符串,你可以根据实际需求处理成int/float等类型
			colData[cellIdx] = append(colData[cellIdx], cell.String())
		}
	}

	// 构建Series数组
	var seriesList []series.Series
	for idx, name := range colNames {
		s := series.String(colData[idx], series.Name(name))
		seriesList = append(seriesList, s)
	}

	// 生成最终的DataFrame
	return dataframe.New(seriesList...), nil
}

func main() {
	excelPath := "data.xlsx"
	df, err := excelToDF(excelPath, 0) // 读取第一个工作表
	if err != nil {
		panic(err)
	}
	processDF(df)
}

func processDF(df dataframe.DataFrame) {
	// 这里写你的DataFrame处理逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 22:50:04