123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- package models
- import (
- "errors"
- "eta/eta_index_lib/utils"
- "github.com/shopspring/decimal"
- "math"
- "time"
- )
- // HandleDataByLinearRegression 插值法补充数据(线性方程式)
- func HandleDataByLinearRegression(edbInfoDataList []*EdbInfoSearchData, handleDataMap map[string]float64) (newList []*EdbInfoSearchData, err error) {
- if len(edbInfoDataList) < 2 {
- return
- }
- var startEdbInfoData *EdbInfoSearchData
- for _, v := range edbInfoDataList {
- handleDataMap[v.DataTime] = v.Value
- // 第一个数据就给过滤了,给后面的试用
- if startEdbInfoData == nil {
- startEdbInfoData = v
- newList = append(newList, &EdbInfoSearchData{
- EdbDataId: v.EdbDataId,
- DataTime: v.DataTime,
- Value: v.Value,
- })
- continue
- }
- // 获取两条数据之间相差的天数
- startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
- currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
- betweenHour := int(currDataTime.Sub(startDataTime).Hours())
- betweenDay := betweenHour / 24
- // 如果相差一天,那么过滤
- if betweenDay <= 1 {
- startEdbInfoData = v
- newList = append(newList, &EdbInfoSearchData{
- EdbDataId: v.EdbDataId,
- DataTime: v.DataTime,
- Value: v.Value,
- })
- continue
- }
- // 生成线性方程式
- var a, b float64
- {
- coordinateData := make([]utils.Coordinate, 0)
- tmpCoordinate1 := utils.Coordinate{
- X: 1,
- Y: startEdbInfoData.Value,
- }
- coordinateData = append(coordinateData, tmpCoordinate1)
- tmpCoordinate2 := utils.Coordinate{
- X: float64(betweenDay) + 1,
- Y: v.Value,
- }
- coordinateData = append(coordinateData, tmpCoordinate2)
- a, b = utils.GetLinearResult(coordinateData)
- if math.IsNaN(a) || math.IsNaN(b) {
- err = errors.New("线性方程公式生成失败")
- return
- }
- }
- // 生成对应的值
- {
- for i := 1; i < betweenDay; i++ {
- tmpDataTime := startDataTime.AddDate(0, 0, i)
- aDecimal := decimal.NewFromFloat(a)
- xDecimal := decimal.NewFromInt(int64(i) + 1)
- bDecimal := decimal.NewFromFloat(b)
- val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
- handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
- newList = append(newList, &EdbInfoSearchData{
- DataTime: tmpDataTime.Format(utils.FormatDate),
- Value: val,
- })
- }
- }
- // 最后将自己赋值
- newList = append(newList, &EdbInfoSearchData{
- EdbDataId: v.EdbDataId,
- DataTime: v.DataTime,
- Value: v.Value,
- })
- startEdbInfoData = v
- }
- return
- }
- // HandleDataByPreviousData 当前日期无值时,用上一个日期的数据补充当前日期的数据
- func HandleDataByPreviousData(edbInfoDataList []*EdbInfoSearchData, handleDataMap map[string]float64) (err error) {
- if len(edbInfoDataList) < 2 {
- return
- }
- var startEdbInfoData *EdbInfoSearchData
- for _, v := range edbInfoDataList {
- handleDataMap[v.DataTime] = v.Value
- // 第一个数据就给过滤了,给后面的试用
- if startEdbInfoData == nil {
- startEdbInfoData = v
- continue
- }
- // 获取两条数据之间相差的天数
- startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
- currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
- betweenHour := int(currDataTime.Sub(startDataTime).Hours())
- betweenDay := betweenHour / 24
- // 如果相差一天,那么过滤
- if betweenDay <= 1 {
- startEdbInfoData = v
- continue
- }
- // 生成对应的值
- {
- for i := 1; i < betweenDay; i++ {
- tmpDataTime := startDataTime.AddDate(0, 0, i)
- handleDataMap[tmpDataTime.Format(utils.FormatDate)] = startEdbInfoData.Value
- }
- }
- startEdbInfoData = v
- }
- return
- }
- // HandleDataByLinearRegressionByTime 插值法补充数据(线性方程式) 时间为日期格式,而不是字符串
- func HandleDataByLinearRegressionByTime(edbInfoDataList []*EdbInfoData, handleDataMap map[time.Time]float64) (newList []*EdbInfoData, err error) {
- if len(edbInfoDataList) < 2 {
- return
- }
- var startEdbInfoData *EdbInfoData
- for _, v := range edbInfoDataList {
- handleDataMap[v.DataTime] = v.Value
- // 第一个数据就给过滤了,给后面的试用
- if startEdbInfoData == nil {
- startEdbInfoData = v
- newList = append(newList, &EdbInfoData{
- EdbDataId: v.EdbDataId,
- DataTime: v.DataTime,
- Value: v.Value,
- })
- continue
- }
- // 获取两条数据之间相差的天数
- startDataTime := startEdbInfoData.DataTime
- currDataTime := v.DataTime
- betweenHour := int(currDataTime.Sub(startDataTime).Hours())
- betweenDay := betweenHour / 24
- // 如果相差一天,那么过滤
- if betweenDay <= 1 {
- startEdbInfoData = v
- newList = append(newList, &EdbInfoData{
- EdbDataId: v.EdbDataId,
- DataTime: v.DataTime,
- Value: v.Value,
- })
- continue
- }
- // 生成线性方程式
- var a, b float64
- {
- coordinateData := make([]utils.Coordinate, 0)
- tmpCoordinate1 := utils.Coordinate{
- X: 1,
- Y: startEdbInfoData.Value,
- }
- coordinateData = append(coordinateData, tmpCoordinate1)
- tmpCoordinate2 := utils.Coordinate{
- X: float64(betweenDay) + 1,
- Y: v.Value,
- }
- coordinateData = append(coordinateData, tmpCoordinate2)
- a, b = utils.GetLinearResult(coordinateData)
- if math.IsNaN(a) || math.IsNaN(b) {
- err = errors.New("线性方程公式生成失败")
- return
- }
- }
- // 生成对应的值
- {
- for i := 1; i < betweenDay; i++ {
- tmpDataTime := startDataTime.AddDate(0, 0, i)
- aDecimal := decimal.NewFromFloat(a)
- xDecimal := decimal.NewFromInt(int64(i) + 1)
- bDecimal := decimal.NewFromFloat(b)
- val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
- handleDataMap[tmpDataTime] = val
- newList = append(newList, &EdbInfoData{
- DataTime: tmpDataTime,
- Value: val,
- })
- }
- }
- // 最后将自己赋值
- newList = append(newList, &EdbInfoData{
- EdbDataId: v.EdbDataId,
- DataTime: v.DataTime,
- Value: v.Value,
- })
- startEdbInfoData = v
- }
- return
- }
|