chart_info.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. package line_feature
  2. import (
  3. "errors"
  4. "github.com/shopspring/decimal"
  5. "hongze/hongze_ETA_mobile_api/models/data_manage"
  6. "hongze/hongze_ETA_mobile_api/models/data_manage/line_feature/response"
  7. "hongze/hongze_ETA_mobile_api/services/data"
  8. "hongze/hongze_ETA_mobile_api/utils"
  9. "time"
  10. )
  11. // GetStandardDeviationData 获取标准差图表的指标数据
  12. func GetStandardDeviationData(chartInfoId int, mappingInfo *data_manage.ChartEdbInfoMapping, calculateValue int) (edbList []*data_manage.ChartEdbInfoMapping, dataResp response.LineFeatureDataResp, err error, errMsg string) {
  13. edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
  14. // 指标对应的所有数据
  15. _, edbList, err = data.GetEdbDataMapList(chartInfoId, 1, `公历`, ``, ``, []*data_manage.ChartEdbInfoMapping{mappingInfo})
  16. if err != nil {
  17. return
  18. }
  19. if len(edbList) != 1 {
  20. errMsg = `指标异常`
  21. err = errors.New(errMsg)
  22. return
  23. }
  24. edb := edbList[0]
  25. dataList := edb.DataList.([]*data_manage.EdbDataList)
  26. newDataList := make([]data_manage.EdbDataList, 0)
  27. lenData := len(dataList)
  28. var minVal, maxVal float64
  29. if lenData >= calculateValue {
  30. tmpDataList := make([]float64, 0)
  31. for _, tmpData := range dataList {
  32. tmpDataList = append(tmpDataList, tmpData.Value)
  33. }
  34. for i := calculateValue; i <= lenData; i++ {
  35. tmpV := utils.CalculateStandardDeviation(tmpDataList[i-calculateValue : i])
  36. tmpV, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
  37. newDataList = append(newDataList, data_manage.EdbDataList{
  38. EdbDataId: i,
  39. EdbInfoId: edb.EdbInfoId,
  40. DataTime: dataList[i-1].DataTime,
  41. DataTimestamp: dataList[i-1].DataTimestamp,
  42. Value: tmpV,
  43. })
  44. if tmpV > maxVal {
  45. maxVal = tmpV
  46. }
  47. if tmpV < minVal {
  48. minVal = tmpV
  49. }
  50. }
  51. }
  52. dataResp = response.LineFeatureDataResp{
  53. MaxData: maxVal,
  54. MinData: minVal,
  55. LatestDate: edb.LatestDate,
  56. EdbInfoCategoryType: edb.EdbInfoCategoryType,
  57. ChartColor: `#00F`,
  58. ChartStyle: `spline`,
  59. PredictChartColor: `#00F`,
  60. ChartType: 0,
  61. ChartWidth: 3,
  62. EdbName: "标准差",
  63. EdbNameEn: "standard deviation",
  64. Unit: edb.Unit,
  65. UnitEn: edb.UnitEn,
  66. IsAxis: 1,
  67. DataList: newDataList,
  68. }
  69. return
  70. }
  71. // GetPercentileData 获取百分位图表的指标数据
  72. func GetPercentileData(chartInfoId int, mappingInfo *data_manage.ChartEdbInfoMapping, calculateValue int, calculateUnit string) (edbList []*data_manage.ChartEdbInfoMapping, dataResp response.LineFeatureDataResp, err error, errMsg string) {
  73. edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
  74. moveUnitDays, ok := utils.FrequencyDaysMap[calculateUnit]
  75. if !ok {
  76. errMsg = `错误的周期`
  77. err = errors.New(errMsg)
  78. return
  79. }
  80. calculateDay := calculateValue * moveUnitDays
  81. // 指标对应的所有数据
  82. _, edbList, err = data.GetEdbDataMapList(chartInfoId, 1, `公历`, ``, ``, []*data_manage.ChartEdbInfoMapping{mappingInfo})
  83. if err != nil {
  84. return
  85. }
  86. if len(edbList) != 1 {
  87. errMsg = `指标异常`
  88. err = errors.New(errMsg)
  89. return
  90. }
  91. edb := edbList[0]
  92. dataList := edb.DataList.([]*data_manage.EdbDataList)
  93. newDataList := make([]data_manage.EdbDataList, 0)
  94. var edbMinVal, edbMaxVal float64
  95. dataMap := make(map[time.Time]float64, 0)
  96. for _, tmpData := range dataList {
  97. currDateTime, _ := time.ParseInLocation(utils.FormatDate, tmpData.DataTime, time.Local)
  98. dataMap[currDateTime] = tmpData.Value
  99. }
  100. //百分位:对所选指标滚动地取对应时间长度的数据值,取最大值Max,最小值Min,计算Max-Min,百分位=(现值-Min)/(Max-Min),Max=Min时不予计算。
  101. for i, tmpData := range dataList {
  102. currDateTime, _ := time.ParseInLocation(utils.FormatDate, tmpData.DataTime, time.Local)
  103. maxVal := tmpData.Value
  104. minVal := tmpData.Value
  105. for k := 0; k < calculateDay; k++ {
  106. preVal, ok2 := dataMap[currDateTime.AddDate(0, 0, -k)]
  107. if ok2 {
  108. if preVal > maxVal {
  109. maxVal = preVal
  110. }
  111. if preVal < minVal {
  112. minVal = preVal
  113. }
  114. }
  115. }
  116. if maxVal == minVal {
  117. continue
  118. }
  119. //百分位=(现值-Min)/(Max-Min)
  120. tmpV := (tmpData.Value - minVal) / (maxVal - minVal) * 100
  121. tmpV, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
  122. newDataList = append(newDataList, data_manage.EdbDataList{
  123. EdbDataId: i,
  124. EdbInfoId: edb.EdbInfoId,
  125. DataTime: dataList[i].DataTime,
  126. DataTimestamp: dataList[i].DataTimestamp,
  127. Value: tmpV,
  128. })
  129. if tmpV < edbMinVal {
  130. edbMinVal = tmpV
  131. }
  132. if tmpV > edbMaxVal {
  133. edbMaxVal = tmpV
  134. }
  135. }
  136. dataResp = response.LineFeatureDataResp{
  137. MaxData: edbMaxVal,
  138. MinData: edbMinVal,
  139. LatestDate: edb.LatestDate,
  140. EdbInfoCategoryType: edb.EdbInfoCategoryType,
  141. ChartColor: `#00F`,
  142. ChartStyle: `spline`,
  143. PredictChartColor: `#00F`,
  144. ChartType: 0,
  145. ChartWidth: 3,
  146. EdbName: "百分位",
  147. EdbNameEn: "percentile",
  148. Unit: "%",
  149. UnitEn: "%",
  150. IsAxis: 1,
  151. DataList: newDataList,
  152. }
  153. return
  154. }
  155. // GetFrequencyDistributionData 获取频率分布的图表数据
  156. func GetFrequencyDistributionData(chartInfoId int, mappingInfo *data_manage.ChartEdbInfoMapping, dateType, stepVal int, startDate, endDate string) (edbList []*data_manage.ChartEdbInfoMapping, dataResp response.FrequencyDistributionResp, err error, errMsg string) {
  157. XDataList := make([]float64, 0)
  158. // 频度
  159. Y1DataList := make([]response.FrequencyDistributionYData, 0)
  160. // 累计频率
  161. Y2DataList := make([]response.FrequencyDistributionYData, 0)
  162. edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
  163. // 指标对应的所有数据
  164. _, edbList, err = data.GetEdbDataMapList(chartInfoId, 1, `公历`, startDate, endDate, []*data_manage.ChartEdbInfoMapping{mappingInfo})
  165. if err != nil {
  166. return
  167. }
  168. if len(edbList) != 1 {
  169. err = errors.New("指标异常")
  170. return
  171. }
  172. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  173. var endDateTime time.Time
  174. if endDate != `` {
  175. endDateTime, _ = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  176. }
  177. edb := edbList[0]
  178. dataList := edb.DataList.([]*data_manage.EdbDataList)
  179. if len(dataList) <= 0 {
  180. return
  181. }
  182. // 非自定义
  183. if dateType != 8 {
  184. endDate = dataList[len(dataList)-1].DataTime
  185. endDateTime, err = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  186. if err != nil {
  187. return
  188. }
  189. //日期类型:1:最近3月;2:最近6月;3:最近1年;4:最近2年;5:最近3年;6:最近5年;7:最近10年,8:自定义时间
  190. startDateTime = utils.GetDateByDateType2(dateType, endDateTime)
  191. startDate = startDateTime.Format(utils.FormatDate)
  192. newDataList := make([]*data_manage.EdbDataList, 0)
  193. for _, v := range dataList {
  194. tmpDataTime, tmpErr := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  195. if tmpErr != nil {
  196. err = tmpErr
  197. return
  198. }
  199. if tmpDataTime.Equal(startDateTime) || tmpDataTime.After(startDateTime) {
  200. newDataList = append(newDataList, v)
  201. }
  202. }
  203. dataList = newDataList
  204. }
  205. maxVal := dataList[0].Value
  206. minVal := dataList[0].Value
  207. dataValMap := make(map[float64]int)
  208. total := 0 // 数据总量
  209. for _, tmpData := range dataList {
  210. currDateTime, _ := time.ParseInLocation(utils.FormatDate, tmpData.DataTime, time.Local)
  211. if (currDateTime.Equal(startDateTime) || currDateTime.After(startDateTime)) && (endDateTime.IsZero() || currDateTime.Before(endDateTime)) {
  212. if maxVal < tmpData.Value {
  213. maxVal = tmpData.Value
  214. }
  215. if minVal > tmpData.Value {
  216. minVal = tmpData.Value
  217. }
  218. num, ok := dataValMap[tmpData.Value]
  219. if ok {
  220. dataValMap[tmpData.Value] = num + 1
  221. } else {
  222. dataValMap[tmpData.Value] = 1
  223. }
  224. total++
  225. }
  226. }
  227. if total <= 0 {
  228. errMsg = `没有数据`
  229. err = errors.New(errMsg)
  230. return
  231. }
  232. // 最大最小值 向上/下取整
  233. minVal = utils.GetFloorNewNum(minVal, 2)
  234. maxVal = utils.GetCeilNewNum(maxVal, 2)
  235. //间距
  236. spacing, _ := (decimal.NewFromFloat(maxVal).Sub(decimal.NewFromFloat(minVal))).Div(decimal.NewFromInt(int64(stepVal))).Float64()
  237. distributionDataNumMap := make(map[float64]int)
  238. for i := 1; i <= stepVal; i++ {
  239. tmpMinVal, _ := decimal.NewFromFloat(minVal).Add((decimal.NewFromFloat(spacing)).Mul(decimal.NewFromInt(int64(i - 1)))).Float64()
  240. tmpMaxVal, _ := decimal.NewFromFloat(minVal).Add((decimal.NewFromFloat(spacing)).Mul(decimal.NewFromInt(int64(i)))).Float64()
  241. XDataList = append(XDataList, tmpMinVal)
  242. distributionDataNumMap[tmpMinVal] = 0
  243. for tmpVal, num := range dataValMap {
  244. if tmpMinVal <= tmpVal {
  245. // 最后一期数据是要小于等于
  246. if i == stepVal {
  247. if tmpVal <= tmpMaxVal {
  248. distributionDataNumMap[tmpMinVal] += num
  249. }
  250. } else {
  251. if tmpVal < tmpMaxVal {
  252. distributionDataNumMap[tmpMinVal] += num
  253. }
  254. }
  255. }
  256. }
  257. }
  258. var minFrequency, maxFrequency float64
  259. tmpNum := 0
  260. for k, tmpMinVal := range XDataList {
  261. // 数量
  262. frequencyYNum := distributionDataNumMap[tmpMinVal]
  263. // 频率
  264. tmpFrequency, _ := decimal.NewFromInt(int64(frequencyYNum)).Div(decimal.NewFromInt(int64(total))).Mul(decimal.NewFromInt(100)).Round(4).Float64()
  265. Y1DataList = append(Y1DataList, response.FrequencyDistributionYData{
  266. X: tmpMinVal,
  267. Y: tmpFrequency,
  268. })
  269. if k == 0 {
  270. minFrequency = tmpFrequency
  271. maxFrequency = tmpFrequency
  272. } else {
  273. if tmpFrequency < minFrequency {
  274. minFrequency = tmpFrequency
  275. }
  276. if tmpFrequency > maxFrequency {
  277. maxFrequency = tmpFrequency
  278. }
  279. }
  280. // 累计数
  281. tmpNum += frequencyYNum
  282. // 累计频率
  283. tmpTotalFrequency, _ := decimal.NewFromInt(int64(tmpNum)).Div(decimal.NewFromInt(int64(total))).Mul(decimal.NewFromInt(100)).Round(4).Float64()
  284. Y2DataList = append(Y2DataList, response.FrequencyDistributionYData{
  285. X: tmpMinVal,
  286. Y: tmpTotalFrequency,
  287. })
  288. }
  289. newDataList := []response.FrequencyDistributionData{
  290. {
  291. Name: "频率",
  292. NameEn: "Frequency",
  293. Unit: "%",
  294. UnitEn: "%",
  295. Value: Y1DataList,
  296. Color: "#00F",
  297. IsAxis: 1,
  298. }, {
  299. Name: "累计频率",
  300. NameEn: "Total Frequency",
  301. Unit: "%",
  302. UnitEn: "%",
  303. Value: Y2DataList,
  304. Color: "#F00",
  305. IsAxis: 0,
  306. },
  307. }
  308. edbList[0].DataList = nil
  309. dataResp = response.FrequencyDistributionResp{
  310. LeftMinValue: minFrequency,
  311. LeftMaxValue: maxFrequency,
  312. RightMinValue: 0,
  313. RightMaxValue: 100,
  314. DataList: newDataList,
  315. }
  316. return
  317. }