为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕神8447489 2022-08-01 15:35:08
我正在尝试从我从上一个函数创建的CSV文件中的数据进行汇总。下面是该文件的一个片段:datetime,open,high,low,close,volume2020-11-09 00:00,69.58,137.45,69.00,100.00,273517274.002020-11-10 00:00,104.65,128.80,101.75,107.00,141284399.002020-11-11 00:00,109.00,114.45,96.76,98.42,96648953.002020-11-12 00:00,95.98,106.60,89.15,90.00,149794913.00[对于上下文:这是雅虎财经的劳斯莱斯控股股价的历史价格数据。我计划使用最多 200 行]。我面临的问题是将数据从CSV转换为float64。该函数正在尝试转换我的标题,显然不能,因为它是“无效语法”。下面是错误代码:[]stringParseFloat()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 mainimport (    "encoding/csv"    "fmt"    "log"    "os"    "strconv")const file = "./rr.csv"// Data struct is the data from the csv filetype 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)    }我只是打印数据以查看ParseFloat()是否有效,然后我将创建一个函数来对列求和。所以,我要问的是;我如何忽略标题行,只是通读数字行。仅供参考:我读过其他答案(例如:FieldsPerRecord),但它们没有为我的具体问题工作,因为我随后试图对整个列进行求和。
查看完整描述

3 回答

?
紫衣仙女

TA贡献1839条经验 获得超15个赞

一些不同的选项:

  1. 跳过解析第一行。这假设每个文件都以标头开头。

  2. 跳过存在解析错误的行。最简单的方法,但在出现问题时很难调试。

  3. 如果第一行有解析错误,请跳过它,因为它可能是标题行。

另外,您应该在代码中正确处理错误,而您当前没有这样做。


查看完整回答
反对 回复 2022-08-01
?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

我已经注释掉了程序,所以很容易理解。基本思想是忽略标头。此外,当您编制索引并获取记录的字段时;最好检查记录中存在的字段数()。FieldsPerRecord


package main


import (

    "encoding/csv"

    "errors"

    "fmt"

    "io"

    "log"

    "os"

    "strconv"

)


// file stores the filepath

const file = "./rr.csv"


// Data store metadata

type Data struct {

    datetime string

    open     float64

    high     float64

    low      float64

    close    float64

    volume   float64

}


// s2f converts string to float64

func s2f(str string) (float64, error) {

    f, err := strconv.ParseFloat(str, 64)

    if err != nil {

        return 0, fmt.Errorf("Error converting string \"%v\" to float", err)

    }

    return f, nil

}


// ReadAmounts processes the fields from the record and stores them in Data

func ReadAmounts(r []string) (*Data, error) {


    var (

        dt     = r[0]

        open   = r[1]

        high   = r[2]

        low    = r[3]

        close  = r[4]

        volume = r[5]


        d   = new(Data)

        err error

    )


    d.datetime = dt


    d.open, err = s2f(open)

    if err != nil {

        return nil, err

    }


    d.high, err = s2f(high)

    if err != nil {

        return nil, err

    }


    d.low, err = s2f(low)

    if err != nil {

        return nil, err

    }


    d.close, err = s2f(close)

    if err != nil {

        return nil, err

    }


    d.volume, err = s2f(volume)

    if err != nil {

        return nil, err

    }


    return d, nil

}


func main() {

    // Open the file

    file, err := os.Open(file)

    if err != nil {

        log.Fatalln(err)

    }


    // CSV Reader

    r := csv.NewReader(file)

    // Set Options for the reader

    {

        r.Comma = ','             // Delimiter

        r.TrimLeadingSpace = true // Trim the leading spaces

        r.FieldsPerRecord = 0     // Rows should have same number of columns as header

        r.ReuseRecord = true      // Reuse the same backing array (Efficient)

    }


    // Alternatively, r.ReadAll() could be also used and slicing it using [1:] ignores

    // the header as well.


    // Ignore header

    _, _ = r.Read()


    for {

        // Read record (one by one)

        record, err := r.Read()

        if err != nil {

            // Exit out. Done!

            if errors.Is(err, io.EOF) {

                break

            }

            // Log and continue

            log.Printf("Error reading record: %v\n", err)

            continue

        }


        // Process

        data, err := ReadAmounts(record)

        if err != nil {

            // Log and continue

            fmt.Printf("Error reading record: %v\n", err)

            continue

        }


        // Print the filled Data struct

        fmt.Printf("Record: %+v\n", *data)

    }

}


输出:


Record: {datetime:2020-11-09 00:00 open:69.58 high:137.45 low:69 close:100 volume:2.73517274e+08}

Record: {datetime:2020-11-10 00:00 open:104.65 high:128.8 low:101.75 close:107 volume:1.41284399e+08}

Record: {datetime:2020-11-11 00:00 open:109 high:114.45 low:96.76 close:98.42 volume:9.6648953e+07}

Record: {datetime:2020-11-12 00:00 open:95.98 high:106.6 low:89.15 close:90 volume:1.49794913e+08}



查看完整回答
反对 回复 2022-08-01
?
婷婷同学_

TA贡献1844条经验 获得超8个赞

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


package main


import (

    "bytes"

    "encoding/csv"

    "fmt"

    "io/ioutil"

    "strconv"

)


const file = "./data.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 main() {


    f, err := ioutil.ReadFile(file)

    if err != nil {

        panic(err)

    }

    rawData, err := readCsv(f, ',')

    if err != nil {

        panic(err)

    }


    amounts, err := readAmounts(rawData[1:])

    if err != nil {

        panic(err)

    }

    fmt.Printf("%+v\n", amounts)


}


func readAmounts(r [][]string) ([]Data, error) {

    var d []Data = make([]Data, len(r))

    var err error

    for i, row := range r {


        d[i].datetime = row[0]

        if err != nil {

            fmt.Printf("Error converting string: %v", err)

        }

        d[i].open, err = strconv.ParseFloat(row[1], 64)

        if err != nil {

            fmt.Printf("Error converting string: %v", err)

        }

        d[i].high, err = strconv.ParseFloat(row[2], 64)

        if err != nil {

            fmt.Printf("Error converting string: %v", err)

        }

        d[i].low, err = strconv.ParseFloat(row[3], 64)

        if err != nil {

            fmt.Printf("Error converting string: %v", err)

        }

        d[i].close, err = strconv.ParseFloat(row[4], 64)

        if err != nil {

            fmt.Printf("Error converting string: %v", err)

        }


        d[i].volume, err = strconv.ParseFloat(row[5], 64)

        if err != nil {

            fmt.Printf("Error converting string: %v", err)

        }

    }

    return d, nil


}


func readCsv(data []byte, separator rune) ([][]string, error) {

    csvReader := csv.NewReader(bytes.NewReader(data))

    csvReader.Comma = separator

    lines, err := csvReader.ReadAll()

    if err != nil {

        return nil, err

    }

    return lines, nil

}

输出示例:


[{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}]

注意:

您可以找到一些使用该库工作的代码示例,您可以查看以下存储库:https://github.com/alessiosavi/GoSFTPtoS3CSV


查看完整回答
反对 回复 2022-08-01
  • 3 回答
  • 0 关注
  • 101 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号