使用strconv将csv数据([]字符串)转换为float64,然后对数据求和

使用strconv将csv数据([]字符串)转换为float64,然后对数据求和,csv,go,Csv,Go,我正在尝试对以前函数创建的CSV文件中的数据求和。以下是该文件的一个片段: datetime,open,high,low,close,volume 2020-11-09 00:00,69.58,137.45,69.00,100.00,273517274.00 2020-11-10 00:00,104.65,128.80,101.75,107.00,141284399.00 2020-11-11 00:00,109.00,114.45,96.76,98.42,96648953.00 2020-11

我正在尝试对以前函数创建的CSV文件中的数据求和。以下是该文件的一个片段:

datetime,open,high,low,close,volume
2020-11-09 00:00,69.58,137.45,69.00,100.00,273517274.00
2020-11-10 00:00,104.65,128.80,101.75,107.00,141284399.00
2020-11-11 00:00,109.00,114.45,96.76,98.42,96648953.00
2020-11-12 00:00,95.98,106.60,89.15,90.00,149794913.00
[上下文:这是雅虎金融公司提供的劳斯莱斯控股公司股票价格的历史价格数据。我计划使用最多200行]

我面临的问题是将
[]字符串
数据从CSV转换为float64。
ParseFloat()
函数正在尝试转换我的标题,显然无法转换,因为它是“无效语法”。以下是错误代码:

Error converting string: strconv.ParseFloat: parsing "open": invalid syntaxError converting string: strconv.ParseFloat: parsing "high": invalid syntaxError converting string: strconv.ParseFloat: parsing "low": invalid syntaxError converting string: strconv.ParseFloat: parsing "close": invalid syntaxError converting string: strconv.ParseFloat: parsing "volume": invalid syntax&{ 0 0 0 0 0}
我的代码如下,以供参考:

package main

import (
    "encoding/csv"
    "fmt"
    "log"
    "os"
    "strconv"
)

const file = "./rr.csv"

// Data struct is the data from the csv file
type Data struct {
    datetime string
    open     float64
    high     float64
    low      float64
    close    float64
    volume   float64
}

func readAmounts(r []string) (d *Data, err error) {
    d = new(Data)
    open := r[1]
    d.open, err = strconv.ParseFloat(open, 64)
    if err != nil {
        fmt.Printf("Error converting string: %v", err)
    }
    high := r[2]
    d.high, err = strconv.ParseFloat(high, 64)
    if err != nil {
        fmt.Printf("Error converting string: %v", err)
    }
    low := r[3]
    d.low, err = strconv.ParseFloat(low, 64)
    if err != nil {
        fmt.Printf("Error converting string: %v", err)
    }
    close := r[4]
    d.close, err = strconv.ParseFloat(close, 64)
    if err != nil {
        fmt.Printf("Error converting string: %v", err)
    }
    volume := r[5]
    d.volume, err = strconv.ParseFloat(volume, 64)
    if err != nil {
        fmt.Printf("Error converting string: %v", err)
    }
    return d, nil
}

func main() {
    csvFile, err := os.Open(file)
    if err != nil {
        log.Fatal(err)
    }

    r := csv.NewReader(csvFile)
    lines, err := r.Read()
    if err != nil {
        log.Fatal(err)
    }

    data, err := readAmounts(lines)
    if err != nil {
        fmt.Printf("Error reading file: %v", err)
    }
    fmt.Println(data)

}
我只是打印数据,看看ParseFloat()是否有效,然后我将创建一个函数来对列求和。 所以,我要问的是;我如何忽略标题行而只阅读数字行


仅供参考:我已经阅读了其他答案(例如:FieldsPerRecord),但它们并没有解决我的具体问题,因为我随后将尝试对所有列进行求和。

您可以将文件加载到CSV中,然后逐行处理文件:

datetime,open,high,low,close,volume
2020-11-09 00:00,69.58,137.45,69.00,100.00,273517274.00
2020-11-10 00:00,104.65,128.80,101.75,107.00,141284399.00
2020-11-11 00:00,109.00,114.45,96.76,98.42,96648953.00
2020-11-12 00:00,95.98,106.60,89.15,90.00,149794913.00
主程序包
进口(
“字节”
“编码/csv”
“fmt”
“io/ioutil”
“strconv”
)
const file=“./data.csv”
//Data struct是csv文件中的数据
类型数据结构{
日期时间字符串
开放式浮动64
高浮动64
低浮动64
关闭浮动64
卷浮动64
}
func main(){
f、 错误:=ioutil.ReadFile(文件)
如果错误!=零{
恐慌(错误)
}
rawData,err:=readCsv(f,,)
如果错误!=零{
恐慌(错误)
}
金额,错误:=读取金额(原始数据[1:])
如果错误!=零{
恐慌(错误)
}
格式打印F(“%+v\n”,金额)
}
func readAmounts(r[][]字符串)([]数据,错误){
var d[]数据=制造([]数据,长度(r))
变量错误
对于i,行:=范围r{
d[i].日期时间=行[0]
如果错误!=零{
fmt.Printf(“转换字符串时出错:%v”,错误)
}
d[i].open,err=strconv.ParseFloat(第[1]行,64)
如果错误!=零{
fmt.Printf(“转换字符串时出错:%v”,错误)
}
d[i]。高,err=strconv.ParseFloat(第[2]行,64)
如果错误!=零{
fmt.Printf(“转换字符串时出错:%v”,错误)
}
d[i].low,err=strconv.ParseFloat(第[3]行,64)
如果错误!=零{
fmt.Printf(“转换字符串时出错:%v”,错误)
}
d[i].close,err=strconv.ParseFloat(第[4]行,64)
如果错误!=零{
fmt.Printf(“转换字符串时出错:%v”,错误)
}
d[i]。卷,err=strconv.ParseFloat(第[5]行,64)
如果错误!=零{
fmt.Printf(“转换字符串时出错:%v”,错误)
}
}
返回d,无
}
func readCsv(数据[]字节,分隔符符符)([]字符串,错误){
csvReader:=csv.NewReader(bytes.NewReader(数据))
csvReader.逗号=分隔符
行,错误:=csvReader.ReadAll()
如果错误!=零{
返回零,错误
}
返回线路,无
}
输出示例:

[{datetime:2020-11-09 00:00 open:69.58 high:137.45 low:69 close:100 volume:2.73517274e+08} {datetime:2020-11-10 00:00 open:104.65 high:128.8 low:101.75 close:107 volume:1.41284399e+08} {datetime:2020-11-11 00:00 open:109 high:114.45 low:96.76 close:98.42 volume:9.6648953e+07} {datetime:2020-11-12 00:00 open:95.
98 high:106.6 low:89.15 close:90 volume:1.49794913e+08}]
注:
您可以找到一些使用
CSV
库工作的代码示例,您可以查看以下存储库:

我已注释掉该程序,因此易于理解。基本思想是忽略标题。此外,当您索引和获取记录的字段时;最好检查记录中存在的字段数(
FieldsPerRecord

主程序包
进口(
“编码/csv”
“错误”
“fmt”
“io”
“日志”
“操作系统”
“strconv”
)
//文件存储文件路径
const file=“./rr.csv”
//数据存储元数据
类型数据结构{
日期时间字符串
开放式浮动64
高浮动64
低浮动64
关闭浮动64
卷浮动64
}
//s2f将字符串转换为浮点64
func s2f(str字符串)(浮点64,错误){
f、 err:=strconv.ParseFloat(str,64)
如果错误!=零{
返回0,fmt.Errorf(“将字符串\%v\”转换为浮点时出错”,err)
}
返回f,无
}
//ReadAmounts处理记录中的字段并将其存储在数据中
func ReadAmounts(r[]字符串)(*数据,错误){
变量(
dt=r[0]
open=r[1]
高=r[2]
低=r[3]
关闭=r[4]
体积=r[5]
d=新(数据)
错误
)
d、 日期时间=dt
d、 打开,错误=s2f(打开)
如果错误!=零{
返回零,错误
}
d、 高,err=s2f(高)
如果错误!=零{
返回零,错误
}
d、 低,err=s2f(低)
如果错误!=零{
返回零,错误
}
d、 关闭,错误=s2f(关闭)
如果错误!=零{
返回零,错误
}
d、 音量,err=s2f(音量)
如果错误!=零{
返回零,错误
}
返回d,无
}
func main(){
//打开文件
文件,错误:=os.Open(文件)
如果错误!=零{
log.Fatalln(错误)
}
//CSV阅读器
r:=csv.NewReader(文件)
//为读卡器设置选项
{
r、 逗号=','//分隔符
r、 TrimLeadingSpace=true//修剪前导空格
r、 FieldsPerRecord=0//行的列数应与标头的列数相同
r、 ReuseRecord=true//重用相同的备份阵列(高效)
}
//或者,也可以使用r.ReadAll()并使用[1:]对其进行切片
//头球也是。
//忽略标题
_,ur=r.Read()
为了{
//读取记录(逐个)
记录,错误:=r.Read()
如果错误!=零{
//退出,完毕!
if errors.Is(err,io.EOF){
打破
}
//记录并继续
log.Printf(“读取记录时出错:%v\n”,错误)
持续
}
//过程
数据,错误:=读取金额(记录)
如果错误!=零{
//记录并继续
fmt.Printf(“读取记录时出错:%v\n”,错误)
持续
}
//打印填充的数据结构
fmt.Printf(“记录:%+v\n”