天天看點

用PostgreSQL描繪人生的高潮、尿點、低谷 - 視窗/幀 or 斜率/導數/曲率/微積分?

postgresql , 曲線拐點 , 視窗查詢 , 幀 , 視窗 , 導數 , 曲率 , 微積分 , 斜率

人生就像一場戲,有高潮,有尿點,有低谷。如果用曲線來描述漫漫人生路的話,怎麼找出高潮、尿點、低谷呢?

其實類似的場景還有很多,比如來自傳感器(比如人身上可以探測的名額就有很多)的監控資料;伺服器的監控資料;溫度,濕度的變化資料;等等,都可以數字化,用曲線來表示。

找高潮、尿點、低谷有什麼好的方法嗎?

如果你是剛畢業不久的學生,可能會往學校裡學到的知識去思考,怎麼找曲線的拐點?

導數、微積分、斜率、曲率、面積?

沒錯,postgresql可以算這些,math相關的函數裡有,如果沒有,也可以寫udf來實作。

如果你把這些都忘了,還有什麼方法能找出高潮、尿點、低谷麼?

當然,還是有方法的,也是postgresql,它支援視窗,幀的查詢。

用幾張圖來表示一下什麼是高潮、尿點、低谷?

不要以為我是算命的,我其實是搞postgresql的。

用PostgreSQL描繪人生的高潮、尿點、低谷 - 視窗/幀 or 斜率/導數/曲率/微積分?

這段曲線表示了一段奮力拼搏,快速到達人生巅峰,然後在巅峰期有些許的抖動,一段時間之後遭遇打擊急速掉入谷底的情況,由于底子好,東山再起也很快,不過此命注定要在一波三折中度過,最後持續的保持在平滑的巅峰狀态。

用PostgreSQL描繪人生的高潮、尿點、低谷 - 視窗/幀 or 斜率/導數/曲率/微積分?

而這一段人生屬于不積跬步無以至千裡的模式,主人公慢慢的積累,終于到達了人生的巅峰,而且在巅峰期主人公應該是想繼續突破,很可惜,隻是一個小的突破,馬上有跌下來了,在過了一段時間,主人公可能遭遇了不可逆轉的挫折,進入了人生的谷底之後,就一蹶不振,甚至還想過自殺,不過還好躲過一劫,可惜此命太薄,後來也隻能郁郁不得終。

用PostgreSQL描繪人生的高潮、尿點、低谷 - 視窗/幀 or 斜率/導數/曲率/微積分?

這一段有意思了,也是屬于不積跬步無以至千裡的模式,主人公慢慢的積累,終于到達了人生的巅峰。但是好景不長,可能娶了個即會敗家又不旺夫的敗家娘們,慢慢的開始走下坡路,直到精盡人亡。

用PostgreSQL描繪人生的高潮、尿點、低谷 - 視窗/幀 or 斜率/導數/曲率/微積分?

這個主人公絕對屬于可以拍電視劇的傳奇人物類型,可能是富豪家族的小孩出生後被醫院抱錯的情況,從小在屌絲家庭長大,後來機緣巧合又回到了富豪家庭,是以經曆了急速的從屌絲到高富帥的過程。但是可能不習慣富豪家的勾心鬥角,被可惡的後媽搞走,又從高富帥摔入谷底。還好親爸在世時的庇護下,經曆了富豪家的一波三折,中間還出現過幾次小的高峰,可惜好景不長,後來還是逐漸的衰退。

用PostgreSQL描繪人生的高潮、尿點、低谷 - 視窗/幀 or 斜率/導數/曲率/微積分?

最後這一段一定是一個從屌絲到人生赢家的勵志故事,主人公在屌絲家庭長大,經過自己的堅持不懈的努力,到達了人生的巅峰,整個過程非常的平滑,還創造了不少小的高潮,直到風光逝去。

看了這麼多曲線,我們怎麼把拐點找出來?

在機關時間内采樣的點越多,分辨率就越高。

對于分辨率較低的曲線,看起來可能就不像曲線了,是一些跳躍的點,按斜率找到有意義的拐點也比較麻煩,也是難點之一。

在曆史的長河中,一個人的詳細經曆或故事(除了一些對曆史有重大影響的人)可能是不起眼的,但是對于這個人來說,他的經曆,他遇到的人和事,就可以抓出很多值得說道的點來。

是以說我們要分析曲線的拐點,和曲線的長度也是有莫大的關系的,你是要看1年的曲線拐點呢,還是要看1天的曲線拐點?

在1天的曲線中能找出來10個拐點,但是這一天的資料可能在一年的曲線中出現在一個很平淡的段落中,那麼可能就一個點都找不到。

即曲線的總體落差,假設我們要分析一條1年的曲線,總體落差指的是1年的資料中最大值和最小值的差。

總體落差可以描述一段資料的高潮和低谷的差異,可以作為判斷關鍵點的一個評判系數。

區間落差,指以某個點為中心,它的輻射半徑内的最大值和最小值的落差。可以用來評判這個點所處的區域中的落差,判斷平凡人生路中的小尖刺,比如在平淡期的一些小的波動,小高潮或者小低谷。

掌握了整體曲線的落差後,其實就可以設定高低水位,或者按大局來設定高低水位。

比如股市,有大盤走勢,有個股走勢。

什麼是低水位,什麼是高水位,是有參照的情況下來設定的。

打個比方,一組監控資料,監控的是伺服器的負載,伺服器有32核,那麼我們就可以根據這些參照設定負載的高低水位,比如低水位為1以下,高水位為24以上。

需要用到postgresql的視窗查詢和幀,用來實作對以上曲線分析的計算。

視窗指計算的資料區間,指與目前row在同一個分組中的資料。

幀也是指計算的資料區間,但是是在分組内的指定,可以根據目前row設定輻射半徑,或者目前row的前後分開設定輻射範圍。

求凸點和凹點其實可以用前後值的大小比較就可以了,使用lead()和lag()視窗函數 即可。

但是有其缺陷,沒有落差,沒有意義。

沒有範圍資料,無法檢測漸進資料的凹凸。

建立測試表:

結果

功能

可以找到全局高潮、低谷

可以找到平滑變化的拐點(設定10,或者更大,越大,越能找出平滑變化的拐點)

缺陷

無法找到平滑變化後正式進入平滑高潮或低谷期(>10)的點。

無法找到在平滑高潮或低谷期中的小波峰和波谷(即局部高潮或低谷)。

可以覆寫到越過高水位或低水位的點

可以找到越過高水位或低水位後,平滑過渡的高潮或低谷的點

可以找到在平滑高潮或低谷期中的小波峰和波谷(即局部高潮或低谷)。

無法找到單邊驟變的點,例如新增一下驟變點。

可以找到單邊驟變的點。

無法輸出跳躍點

輸出跳躍點,與左右相鄰的任一點內插補點大于局部落差%?的點

把以上幾個query結合起來

相鄰點的個數,建議根據總的個數除以一個百分比,例如1萬條記錄,去百分之一作為評判标準,那麼10000*0.01=100,取值100.

截取1-1000進行繪圖,看看找出來的是不是關鍵點

用PostgreSQL描繪人生的高潮、尿點、低谷 - 視窗/幀 or 斜率/導數/曲率/微積分?

使用以下query可以列印稀疏點,進行比對

造一批波動資料

資料如圖

用PostgreSQL描繪人生的高潮、尿點、低谷 - 視窗/幀 or 斜率/導數/曲率/微積分?

query 5 輸出

使用本文的方法,一定要注意設定好對應的變量,包括範圍記錄數,落差比例,抖動比例。。

才能得到想要的關鍵點 。

繼續閱讀