簡體   English   中英

如何在 x,y 點的二維數組中找到第一個極值?

[英]How to find the first extremum in 2D array of x,y points?

我有一組點x_i, y_i表示不是雙射映射(沒有一一對應。見附圖: 在此處輸入圖片說明

(不要注意第二行。它只是顯示一個中心質量)。 我試圖找到它的第一個峰值(如您所見,它發現不正確)。 代碼如下。 在這里,我按 Ox 軸對點進行排序,然后使用find_peaks函數:

# sort points by X axis
aa = zip(x,y)
bb = sorted(aa, key=lambda x: (x[0], x[1]))
x,y = zip(*bb)
x = np.array(x)
y = np.array(y)
# find all peaks
peaks, props = find_peaks(y, prominence=0.01, height=0.4)
print('rmax candidates=', y[peaks])
rmax = y[peaks[0]] # first peak is not correct

我注意到這里的排序處理不正確 如果我只繪制y數組,那么我會看到圖片: 在此處輸入圖片說明 . 我們看到的“齒輪非常鋒利”。

因此,如何以最接近的方式對點進行排序(如果我可以設置一個起點)。 對於人類來說,在圖形上畫一條線是一件容易的事,但如何為計算機開發算法呢? 我知道Online Digitizer 中已經使用了類似的算法。 可以輕松提取圖形中的點坐標。

也許你有更好的算法來找到第一個峰值? 如果您有任何問題,請問我。

數據可以在這里找到:

可以給出以下想法:

讀取文件並將數據放入二維 NumPy 數組中。

arr = []        
with open(str(Path('example.csv'))) as csv_file:
    reader = csv.reader(csv_file, delimiter=',')
    for row in reader:
        arr.append([float(row[0]),float(row[1])])
arr = np.array(arr)

由於數據是無序的,因此當我們隨后連接點時,我們會觀察到一個丑陋的圖。

fig0 = go.Figure(go.Scatter(x=arr[:,0],y=arr[:,1], mode='lines'))
fig0.show()

在此處輸入圖片說明

為了獲得合適的圖片,我們需要從某個起點對點進行排序,以便僅連接最近的點

arx, x0, xmin, xmax = sort_by_nearest(arr)
x = arx[:,0]
y = arx[:,1]

排序后的數據y看起來像: 在此處輸入圖片說明 並且非雙射行為消失了,我們可以使用find_peaks函數輕松找到僅y數據的第一個峰值。 prominence是從一個峰到下一個峰的下降和上升的最小高度。 因此,小的嘈雜峰將被丟棄。 height負責一個參數,其中僅在y>height區域中搜索峰值

peaks, props = find_peaks(y, prominence=0.01, height=0.4)

這里我們有幾個候選人

print('rmax candidates=', y[peaks])

當然,我們取第一個

rmax = y[peaks[0]]
x_rmax = x[peaks[0]] - x0

讓我們繪制結果: 在此處輸入圖片說明

fig0 = go.Figure(go.Scatter(y=arx[:,1], mode='lines'))
fig0.show()

fig0 = go.Figure(go.Scatter(x=arx[:,0]-x0, y=arx[:,1], name='my_line', mode='lines'))
fig0.add_trace(go.Scatter(x=[x_rmax,x_rmax], y=[0,0.5], name='peak coord', mode='lines', line=dict(color='black', width=2, dash='dot')))

fig0.show()

讓我們專注於按鄰居對數據進行排序的算法。

import pandas as pd
import numpy as np
import plotly.graph_objects as go
import csv
from scipy.signal import find_peaks
import scipy.spatial.distance as ds
from pathlib import Path

搜索最近點的函數很棘手,我們需要以某種方式標記已經觀察到的點以避免無限循環。 我們只是通過大數字修改點坐標來做到這一點 數組arr_full的副本

def closest_point(arr_full, xi, yi, inds):
    N = arr_full.shape[0]
    arr_full[inds] = 1e+30
    dist = (arr_full[:, 0] - xi)**2 + (arr_full[:, 1] - yi)**2
    i_min = dist.argmin()
    #returns an index of the nearest point and its coordinate
    return i_min, arr_full[i_min][0], arr_full[i_min][1]

def sort_by_nearest(arr):
    N = arr.shape[0]
    nearest_point = [None]*N
    #find initial point
    xmin = min(arr[:,0])
    xmax = max(arr[:,0])
    # we copy the original array
    arr_cut = np.copy(arr)
    # the area in which we are 100% sure in absence of the starting point we flag by big value
    arr_cut[arr[:,0] > 0.5*(xmin + xmax)] = 10e+30
    iymin = arr_cut[:,1].argmin()
    # the staring points are
    x0, y0 = arr[iymin, 0], arr[iymin, 1]
    # we initialize the sorted value nearest_point
    nearest_point[0] = [arr[iymin,0],arr[iymin,1]]
    print('Starting point:', x0, y0)
    # we put in it the indices of visited points
    observed = [iymin]
    i_min = iymin
    for i in range(1,N):
        xi, yi = arr[i_min]
        i_min, xip, yip = closest_point(arr, xi, yi, i_min)
        nearest_point[i] = [xip, yip]
        observed.append(i_min)
    nearest_point = np.array(nearest_point)
    return np.array(nearest_point), x0, xmin, xmax

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM