python - python自动重采样数据
问题描述
假设我有以下数据(测量值):
如您所见,有很多尖点(即斜率变化很大的地方)。因此,最好围绕这些点进行更多测量。为此,我编写了一个脚本:
我计算了 3 个连续点的曲率:Menger 曲率:https ://en.wikipedia.org/wiki/Menger_curvature#Definition
然后我根据曲率决定我应该重新采样哪些值。
......我迭代直到平均曲率下降......但它不起作用,因为它上升了。你知道为什么吗 ?
这是完整的代码(在 x 值的长度达到 60 后停止):
import numpy as np
import matplotlib.pyplot as plt
def curvature(A,B,C):
"""Calculates the Menger curvature fro three Points, given as numpy arrays.
Sources:
Menger curvature: https://en.wikipedia.org/wiki/Menger_curvature#Definition
Area of a triangle given 3 points: https://math.stackexchange.com/questions/516219/finding-out-the-area-of-a-triangle-if-the-coordinates-of-the-three-vertices-are
"""
# Pre-check: Making sure that the input points are all numpy arrays
if any(x is not np.ndarray for x in [type(A),type(B),type(C)]):
print("The input points need to be a numpy array, currently it is a ", type(A))
# Augment Columns
A_aug = np.append(A,1)
B_aug = np.append(B,1)
C_aug = np.append(C,1)
# Caclulate Area of Triangle
matrix = np.column_stack((A_aug,B_aug,C_aug))
area = 1/2*np.linalg.det(matrix)
# Special case: Two or more points are equal
if np.all(A == B) or np.all(B == C):
curvature = 0
else:
curvature = 4*area/(np.linalg.norm(A-B)*np.linalg.norm(B-C)*np.linalg.norm(C-A))
# Return Menger curvature
return curvature
def values_to_calulate(x,curvature_list, max_curvature):
"""Calculates the new x values which need to be calculated
Middle point between the three points that were used to calculate the curvature """
i = 0
new_x = np.empty(0)
for curvature in curvature_list:
if curvature > max_curvature:
new_x = np.append(new_x, x[i]+(x[i+2]-x[i])/3 )
i = i+1
return new_x
def plot(x,y, title, xLabel, yLabel):
"""Just to visualize"""
# Plot
plt.scatter(x,y)
plt.plot(x, y, '-o')
# Give a title for the sine wave plot
plt.title(title)
# Give x axis label for the sine wave plot
plt.xlabel(xLabel)
# Give y axis label for the sine wave plot
plt.ylabel(yLabel)
plt.grid(True, which='both')
plt.axhline(y=0, color='k')
# Display the sine wave
plt.show
plt.pause(0.05)
### STARTS HERE
# Get x values of the sine wave
x = np.arange(0, 10, 1);
# Amplitude of the sine wave is sine of a variable like time
def function(x):
return 1+np.sin(x)*np.cos(x)**2
y = function(x)
# Plot it
plot(x,y, title='Data', xLabel='Time', yLabel='Amplitude')
continue_Loop = True
while continue_Loop == True :
curvature_list = np.empty(0)
for i in range(len(x)-2):
# Get the three points
A = np.array([x[i],y[i]])
B = np.array([x[i+1],y[i+1]])
C = np.array([x[i+2],y[i+2]])
# Calculate the curvature
curvature_value = abs(curvature(A,B,C))
curvature_list = np.append(curvature_list, curvature_value)
print("len: ", len(x) )
print("average curvature: ", np.average(curvature_list))
# Calculate the points that need to be added
x_new = values_to_calulate(x,curvature_list, max_curvature=0.3)
# Add those values to the current x list:
x = np.sort(np.append(x, x_new))
# STOPED IT AFTER len(x) == 60
if len(x) >= 60:
continue_Loop = False
# Amplitude of the sine wave is sine of a variable like time
y = function(x)
# Plot it
plot(x,y, title='Data', xLabel='Time', yLabel='Amplitude')
它应该是这样的:
编辑:
如果你让它运行得更远......:
解决方案
所以总结一下我上面的评论:
你正在计算你的曲线的平均曲率,它没有理由去 0。在每一点,无论你的点有多接近,圆半径都会收敛到那个点的曲率,而不是 0。
另一种方法是使用两点之间的绝对导数变化:保持采样
abs(d(df/dx)) < some_threshold
直到d(df/dx) = (df/dx)[n] - (df/dx)[n-1]
推荐阅读
- flutter - 有没有办法在颤动中按下按钮时自动填充文本表单字段
- c - 在 VSCode 中使用 gcov
- keras - 可变长度视频分类的数据准备
- python - 如何仅从 Bigquery Client 中的 insert_rows_from_dataframe 方法中获取错误?
- ansys - Ansys Fluent 网格划分和分析
- java - 错误:在类 ca.ab.bc.framework.FormData 中找不到主要方法
- python - 使用异常子句每隔 x 时间运行一段代码
- mysql - MySQL JSON 函数创建分组数据的问题
- javascript - 为什么我会收到此错误:未捕获的 TypeError:this.createLink is not a function at new Link at
1:9? - ruby - 如何使 Ruby Mocha 模拟只检查一个参数