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 }