下面的 Go 代码读取 10,000 条记录的 CSV(时间戳 times
和 float values
),对数据运行一些操作,然后将原始值写入另一个 CSV 以及用于 score
的附加列。然而,它非常慢(即几个小时,但其中大部分是 calculateStuff()
),我很好奇 CSV 读/写中是否存在任何我可以处理的低效率问题。
package main
import (
"encoding/csv"
"log"
"os"
"strconv"
)
func ReadCSV(filepath string) ([][]string, error) {
csvfile, err := os.Open(filepath)
if err != nil {
return nil, err
}
defer csvfile.Close()
reader := csv.NewReader(csvfile)
fields, err := reader.ReadAll()
return fields, nil
}
func main() {
// load data csv
records, err := ReadCSV("./path/to/datafile.csv")
if err != nil {
log.Fatal(err)
}
// write results to a new csv
outfile, err := os.Create("./where/to/write/resultsfile.csv"))
if err != nil {
log.Fatal("Unable to open output")
}
defer outfile.Close()
writer := csv.NewWriter(outfile)
for i, record := range records {
time := record[0]
value := record[1]
// skip header row
if i == 0 {
writer.Write([]string{time, value, "score"})
continue
}
// get float values
floatValue, err := strconv.ParseFloat(value, 64)
if err != nil {
log.Fatal("Record: %v, Error: %v", floatValue, err)
}
// calculate scores; THIS EXTERNAL METHOD CANNOT BE CHANGED
score := calculateStuff(floatValue)
valueString := strconv.FormatFloat(floatValue, 'f', 8, 64)
scoreString := strconv.FormatFloat(prob, 'f', 8, 64)
//fmt.Printf("Result: %v\n", []string{time, valueString, scoreString})
writer.Write([]string{time, valueString, scoreString})
}
writer.Flush()
}
我正在寻求帮助,以尽可能快地完成此 CSV 读/写模板代码。对于这个问题的范围,我们不必担心 calculateStuff
方法。
最佳答案
您首先将文件加载到内存中,然后再对其进行处理,这对于大文件来说可能会很慢。
您需要循环调用.Read
并一次处理一行。
func processCSV(rc io.Reader) (ch chan []string) {
ch = make(chan []string, 10)
go func() {
r := csv.NewReader(rc)
if _, err := r.Read(); err != nil { //read header
log.Fatal(err)
}
defer close(ch)
for {
rec, err := r.Read()
if err != nil {
if err == io.EOF {
break
}
log.Fatal(err)
}
ch <- rec
}
}()
return
}
//请注意,它大致基于 DaveC 的评论。
关于csv - 在 Go 中高效读写 CSV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32027590/