handle_data.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package models
  2. import (
  3. "errors"
  4. "eta/eta_index_lib/utils"
  5. "github.com/shopspring/decimal"
  6. "math"
  7. "time"
  8. )
  9. // HandleDataByLinearRegression 插值法补充数据(线性方程式)
  10. func HandleDataByLinearRegression(edbInfoDataList []*EdbInfoSearchData, handleDataMap map[string]float64) (newList []*EdbInfoSearchData, err error) {
  11. if len(edbInfoDataList) < 2 {
  12. return
  13. }
  14. var startEdbInfoData *EdbInfoSearchData
  15. for _, v := range edbInfoDataList {
  16. handleDataMap[v.DataTime] = v.Value
  17. // 第一个数据就给过滤了,给后面的试用
  18. if startEdbInfoData == nil {
  19. startEdbInfoData = v
  20. newList = append(newList, &EdbInfoSearchData{
  21. EdbDataId: v.EdbDataId,
  22. DataTime: v.DataTime,
  23. Value: v.Value,
  24. })
  25. continue
  26. }
  27. // 获取两条数据之间相差的天数
  28. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  29. currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  30. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  31. betweenDay := betweenHour / 24
  32. // 如果相差一天,那么过滤
  33. if betweenDay <= 1 {
  34. startEdbInfoData = v
  35. newList = append(newList, &EdbInfoSearchData{
  36. EdbDataId: v.EdbDataId,
  37. DataTime: v.DataTime,
  38. Value: v.Value,
  39. })
  40. continue
  41. }
  42. // 生成线性方程式
  43. var a, b float64
  44. {
  45. coordinateData := make([]utils.Coordinate, 0)
  46. tmpCoordinate1 := utils.Coordinate{
  47. X: 1,
  48. Y: startEdbInfoData.Value,
  49. }
  50. coordinateData = append(coordinateData, tmpCoordinate1)
  51. tmpCoordinate2 := utils.Coordinate{
  52. X: float64(betweenDay) + 1,
  53. Y: v.Value,
  54. }
  55. coordinateData = append(coordinateData, tmpCoordinate2)
  56. a, b = utils.GetLinearResult(coordinateData)
  57. if math.IsNaN(a) || math.IsNaN(b) {
  58. err = errors.New("线性方程公式生成失败")
  59. return
  60. }
  61. }
  62. // 生成对应的值
  63. {
  64. for i := 1; i < betweenDay; i++ {
  65. tmpDataTime := startDataTime.AddDate(0, 0, i)
  66. aDecimal := decimal.NewFromFloat(a)
  67. xDecimal := decimal.NewFromInt(int64(i) + 1)
  68. bDecimal := decimal.NewFromFloat(b)
  69. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  70. handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
  71. newList = append(newList, &EdbInfoSearchData{
  72. DataTime: tmpDataTime.Format(utils.FormatDate),
  73. Value: val,
  74. })
  75. }
  76. }
  77. // 最后将自己赋值
  78. newList = append(newList, &EdbInfoSearchData{
  79. EdbDataId: v.EdbDataId,
  80. DataTime: v.DataTime,
  81. Value: v.Value,
  82. })
  83. startEdbInfoData = v
  84. }
  85. return
  86. }
  87. // HandleDataByPreviousData 当前日期无值时,用上一个日期的数据补充当前日期的数据
  88. func HandleDataByPreviousData(edbInfoDataList []*EdbInfoSearchData, handleDataMap map[string]float64) (err error) {
  89. if len(edbInfoDataList) < 2 {
  90. return
  91. }
  92. var startEdbInfoData *EdbInfoSearchData
  93. for _, v := range edbInfoDataList {
  94. handleDataMap[v.DataTime] = v.Value
  95. // 第一个数据就给过滤了,给后面的试用
  96. if startEdbInfoData == nil {
  97. startEdbInfoData = v
  98. continue
  99. }
  100. // 获取两条数据之间相差的天数
  101. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  102. currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  103. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  104. betweenDay := betweenHour / 24
  105. // 如果相差一天,那么过滤
  106. if betweenDay <= 1 {
  107. startEdbInfoData = v
  108. continue
  109. }
  110. // 生成对应的值
  111. {
  112. for i := 1; i < betweenDay; i++ {
  113. tmpDataTime := startDataTime.AddDate(0, 0, i)
  114. handleDataMap[tmpDataTime.Format(utils.FormatDate)] = startEdbInfoData.Value
  115. }
  116. }
  117. startEdbInfoData = v
  118. }
  119. return
  120. }
  121. // HandleDataByLinearRegressionByTime 插值法补充数据(线性方程式) 时间为日期格式,而不是字符串
  122. func HandleDataByLinearRegressionByTime(edbInfoDataList []*EdbInfoData, handleDataMap map[time.Time]float64) (newList []*EdbInfoData, err error) {
  123. if len(edbInfoDataList) < 2 {
  124. return
  125. }
  126. var startEdbInfoData *EdbInfoData
  127. for _, v := range edbInfoDataList {
  128. handleDataMap[v.DataTime] = v.Value
  129. // 第一个数据就给过滤了,给后面的试用
  130. if startEdbInfoData == nil {
  131. startEdbInfoData = v
  132. newList = append(newList, &EdbInfoData{
  133. EdbDataId: v.EdbDataId,
  134. DataTime: v.DataTime,
  135. Value: v.Value,
  136. })
  137. continue
  138. }
  139. // 获取两条数据之间相差的天数
  140. startDataTime := startEdbInfoData.DataTime
  141. currDataTime := v.DataTime
  142. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  143. betweenDay := betweenHour / 24
  144. // 如果相差一天,那么过滤
  145. if betweenDay <= 1 {
  146. startEdbInfoData = v
  147. newList = append(newList, &EdbInfoData{
  148. EdbDataId: v.EdbDataId,
  149. DataTime: v.DataTime,
  150. Value: v.Value,
  151. })
  152. continue
  153. }
  154. // 生成线性方程式
  155. var a, b float64
  156. {
  157. coordinateData := make([]utils.Coordinate, 0)
  158. tmpCoordinate1 := utils.Coordinate{
  159. X: 1,
  160. Y: startEdbInfoData.Value,
  161. }
  162. coordinateData = append(coordinateData, tmpCoordinate1)
  163. tmpCoordinate2 := utils.Coordinate{
  164. X: float64(betweenDay) + 1,
  165. Y: v.Value,
  166. }
  167. coordinateData = append(coordinateData, tmpCoordinate2)
  168. a, b = utils.GetLinearResult(coordinateData)
  169. if math.IsNaN(a) || math.IsNaN(b) {
  170. err = errors.New("线性方程公式生成失败")
  171. return
  172. }
  173. }
  174. // 生成对应的值
  175. {
  176. for i := 1; i < betweenDay; i++ {
  177. tmpDataTime := startDataTime.AddDate(0, 0, i)
  178. aDecimal := decimal.NewFromFloat(a)
  179. xDecimal := decimal.NewFromInt(int64(i) + 1)
  180. bDecimal := decimal.NewFromFloat(b)
  181. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  182. handleDataMap[tmpDataTime] = val
  183. newList = append(newList, &EdbInfoData{
  184. DataTime: tmpDataTime,
  185. Value: val,
  186. })
  187. }
  188. }
  189. // 最后将自己赋值
  190. newList = append(newList, &EdbInfoData{
  191. EdbDataId: v.EdbDataId,
  192. DataTime: v.DataTime,
  193. Value: v.Value,
  194. })
  195. startEdbInfoData = v
  196. }
  197. return
  198. }