Python 区分两个“;对称的;使用numpy的数组
我有两个以弧度为单位的角度值数组。这两个阵列相对于已知的恒定角度对称。阵列如图所示: 示例值如下所示:Python 区分两个“;对称的;使用numpy的数组,python,arrays,numpy,Python,Arrays,Numpy,我有两个以弧度为单位的角度值数组。这两个阵列相对于已知的恒定角度对称。阵列如图所示: 示例值如下所示: one = [ 2.98153965 -1.33298928 2.94993567 -1.39909924 2.99214403 3.00138863 3.04390642 -1.59098448 -1.65660299 -1.73146174 -1.8166248 -2.85595599 -2.02035274 -2.64530394 -2.26451127 -2.39
one = [ 2.98153965 -1.33298928 2.94993567 -1.39909924 2.99214403 3.00138863
3.04390642 -1.59098448 -1.65660299 -1.73146174 -1.8166248 -2.85595599
-2.02035274 -2.64530394 -2.26451127 -2.3982946 -2.52735954 -2.17570346
-2.77544658 -2.88566686 -1.84913768 -3.07261908 -1.66738719 -1.6029932
-1.54596053 -1.50177363 -1.46133745 -1.42288915 -1.38241718 2.79925996
-1.30775884 -1.27309395 2.72153718 -1.20592812 -1.18113435 -1.15029987]
two = [-1.30507254 2.9385436 -1.36415496 2.95897805 -1.43845065 -1.48295087
-1.53346541 3.09685482 -3.11358085 -3.0466034 -2.95794156 -1.9128659
-2.75067133 -2.13826992 -2.51567194 -2.39565127 -2.28148844 -2.65519436
-2.05312249 -1.95523663 -2.98473857 -1.75415233 3.13322155 3.06539723
3.00595703 2.95378704 2.90786779 2.86730208 2.831318 -1.34113191
2.77057495 2.74479777 -1.23620286 2.70046364 2.68129889 2.66380717]
可以看出,这些值“遵循”两条对称的arctan线,我的问题是如何区分这两条线,并得到如下结果:
我尝试过几种方法,但无法找到一种在所有情况下都适用的通用方法,通常会有一个错误的部分分配给错误的数组
欢迎任何意见!
谢谢 难度来自2π跳跃,可通过以下方式解决:
def transform(x):
return x+2*pi*(x<0)
诱导要做的事情:
i=maxi.argmin()
dicrease = np.choose(np.logical_xor(tone>ttwo,t<i),[tone,ttwo])
increase = np.choose(np.logical_xor(tone>ttwo,t<i),[ttwo,tone])
subplot(212)
plot(t,dicrease,label='dicrease')
plot(t,increase,label='increase')
legend()
还有一个吵闹的例子:
这里有一个解决方案,它可以最小化连续点之间的距离以及斜率的变化(通过参数
lam
加权)。在交叉点处,距离单独失效
当
maxi
和mini
函数满足要求时,以及当出现“跳转”时,这两种情况都适用。尽管如此,仍有一个常数需要调整(在我的例子中为0.8),以覆盖mini或maxi的微小变化
one = one + 2*np.pi*(one < 0)
two = two + 2*np.pi*(two < 0)
plt.figure(figsize=(8, 8))
plt.title(run)
t = np.arange(one.size)
maxi = np.maximum(one, two)
mini = np.minimum(one, two)
breaks = np.array([0])
ct = 0
first = np.array([])
second = np.array([])
ch = [maxi, mini]
for i in range(1, maxi.size):
if maxi[i] < mini[i-1] or mini[i] > maxi[i-1]:
breaks = np.append(breaks, [i])
ct += 1
first = np.append(first, ch[0][breaks[ct-1]:breaks[ct]])
second = np.append(second, ch[1][breaks[ct-1]:breaks[ct]])
ch = ch[::-1]
elif i != maxi.size-1:
if maxi[i] - mini[i] < 0.8*min(maxi[i-1] - mini[i-1], maxi[i+1] - mini[i+1]):
breaks = np.append(breaks, [i])
ct += 1
first = np.append(first, ch[0][breaks[ct - 1]:breaks[ct]])
second = np.append(second, ch[1][breaks[ct - 1]:breaks[ct]])
ch = ch[::-1]
first = np.append(first, ch[0][breaks[ct]:])
second = np.append(second, ch[1][breaks[ct]:])
plt.plot(maxi, 'r.', label='maxi')
plt.plot(mini, 'b.', label='mini')
plt.plot(first, label='first')
plt.plot(second, label='second')
plt.legend(prop={'size': 8})
plt.show()
one=one+2*np.pi*(one<0)
二=二+2*np.pi*(二<0)
plt.图(figsize=(8,8))
项目名称(运行)
t=np.arange(一个尺寸)
最大值=np.最大值(一,二)
最小值=np.最小值(一个,两个)
breaks=np.array([0])
ct=0
first=np.array([])
second=np.array([])
ch=[maxi,mini]
对于范围内的i(1,最大尺寸):
如果maxi[i]maxi[i-1]:
breaks=np.append(breaks,[i])
ct+=1
first=np.append(first,ch[0][breaks[ct-1]:breaks[ct]]
second=np.append(second,ch[1][breaks[ct-1]:breaks[ct]]
ch=ch[:-1]
伊里夫一世maxi.size-1:
如果maxi[i]-mini[i]<0.8*min(maxi[i-1]-mini[i-1],maxi[i+1]-mini[i+1]):
breaks=np.append(breaks,[i])
ct+=1
first=np.append(first,ch[0][breaks[ct-1]:breaks[ct]]
second=np.append(second,ch[1][breaks[ct-1]:breaks[ct]]
ch=ch[:-1]
first=np.append(first,ch[0][breaks[ct]:])
second=np.append(second,ch[1][breaks[ct]:])
plt.plot(maxi,'r',label='maxi')
plt.plot(mini'b',label='mini')
plt.plot(第一个,标签='first')
plt.plot(第二个,label='second')
plt.legend(prop={'size':8})
plt.show()
所以结果是这样的:
或者这个:
这些是真值数据集,只有当我开始使用估算算法的噪声输出时,它才会变得有趣。它们是否需要分开?看起来这些值只是在两个数组中拆分。为什么不把它们合并成一个数组呢?你显示的图似乎不是完全对称的。。。否则,可以使用交点周围的镜像对称来分隔阵列。提示:y=const处横截面的导数符号相反。如果函数是单调的,您只需要交点周围的三个值。@erapert-它们不是,第一个图中的两个数组的值都在0到35的整个范围内。这两个数组相对于已知的恒定角度是对称的(因此应该给出,假设给定)以弧度为单位的角度值似乎是有价值的信息-“相位取消包装”将仅由int*pi确定。未包装的数据是否会跨越一个以上的2*pi间隔?包装的数据是由一种算法生成的,该算法始终将其包装到[-pi,pi)范围。当展开时,它将只跨越一个2*pi间隔,是的。这在某些情况下有效,就像我所做的其他一些方法一样。在某些情况下,所有值在“连续化”后都大于0你提出了,但函数仍然不是连续的。比如。不过,感谢你的想法,我想我需要找到所有的交点,或者顶部和底部之间的闭合点,这是我从一开始就尝试使用的,但总是有一两个错误……嗯……让我考虑一个更健壮的变换。我提出了另一个变换sform。告诉我它是否改善了流程。我不确定我应该如何设置间隙参数,但我想如果没有所有不同的数据集,任何人都很难提供帮助。我想我最终会调整并合并所有建议的解决方案。另外,我的“噪音”来自估计误差,这是巨大的,因此很容易被忽略在两条所需的对称线之间的间距。在您的情况下,间距为
2pi
。我知道这是一个数学伪影,不受噪音影响,所以不太难管理。我想这将是正确的答案,在发布我的“答案”之前没有刷新页面。我会在更多的情况下测试它,但如果它像你说的那样涵盖了这两种情况,它应该会工作。而且比我的更正式,没有0.8的调整。谢谢!在各种数据集上进行了尝试,显示了与我以前尝试相同的弱点,你能尝试启动lam
?这将增加对尖点的惩罚。使用你共享的一个数据集我可以将lam
设置为100而不破坏任何东西。我将在接下来的几天内尝试并跟进。谢谢!
def transform2(y,gap):
breaks=np.diff(y)**2>gap**2/2
signs=np.sign(np.diff(y))
offset=np.concatenate(([0],(breaks*signs).cumsum()))*gap
return y-offset
import numpy as np
one = list(map(float, """ 2.98153965 -1.33298928 2.94993567 -1.39909924 2.99214403 3.00138863
3.04390642 -1.59098448 -1.65660299 -1.73146174 -1.8166248 -2.85595599
-2.02035274 -2.64530394 -2.26451127 -2.3982946 -2.52735954 -2.17570346
-2.77544658 -2.88566686 -1.84913768 -3.07261908 -1.66738719 -1.6029932
-1.54596053 -1.50177363 -1.46133745 -1.42288915 -1.38241718 2.79925996
-1.30775884 -1.27309395 2.72153718 -1.20592812 -1.18113435 -1.15029987""".split()))
two = list(map(float, """-1.30507254 2.9385436 -1.36415496 2.95897805 -1.43845065 -1.48295087
-1.53346541 3.09685482 -3.11358085 -3.0466034 -2.95794156 -1.9128659
-2.75067133 -2.13826992 -2.51567194 -2.39565127 -2.28148844 -2.65519436
-2.05312249 -1.95523663 -2.98473857 -1.75415233 3.13322155 3.06539723
3.00595703 2.95378704 2.90786779 2.86730208 2.831318 -1.34113191
2.77057495 2.74479777 -1.23620286 2.70046364 2.68129889 2.66380717""".split()))
data = np.array([one, two])
dd = (data[[[0, 1], [1, 0]], 1:] - data[:, None, :-1] + np.pi)%(2*np.pi) - np.pi
dde2 = np.einsum('ijk,ijk->jk', dd, dd)
xovr1 = np.argmin(dde2, axis=0)
pick1 = np.r_[0, np.cumsum(xovr1) & 1]
d2d = dd[:, :, None, 1:] - dd[[[1, 0], [0, 1]], :, :-1]
d2de2 = np.r_['2', np.zeros((2, 2, 1)), np.einsum('ijkl,ijkl->jkl', d2d, d2d)]
lam = 0.5
e2 = (dde2[:, None, :] + lam * d2de2).reshape(4, -1)
xovr2 = np.argmin(e2, axis=0)>>1
pick2 = np.r_[0, np.cumsum(xovr2) & 1]
print('by position only')
print(data[pick1, np.arange(data.shape[1])])
print(data[1-pick1, np.arange(data.shape[1])])
print('by position and slope')
print(data[pick2, np.arange(data.shape[1])])
print(data[1-pick2, np.arange(data.shape[1])])
# by position only
# [ 2.98153965 2.9385436 2.94993567 2.95897805 2.99214403 3.00138863
# 3.04390642 3.09685482 -3.11358085 -3.0466034 -2.95794156 -2.85595599
# -2.75067133 -2.64530394 -2.51567194 -2.3982946 -2.52735954 -2.65519436
# -2.77544658 -2.88566686 -2.98473857 -3.07261908 3.13322155 3.06539723
# 3.00595703 2.95378704 2.90786779 2.86730208 2.831318 2.79925996
# 2.77057495 2.74479777 2.72153718 2.70046364 2.68129889 2.66380717]
# [-1.30507254 -1.33298928 -1.36415496 -1.39909924 -1.43845065 -1.48295087
# -1.53346541 -1.59098448 -1.65660299 -1.73146174 -1.8166248 -1.9128659
# -2.02035274 -2.13826992 -2.26451127 -2.39565127 -2.28148844 -2.17570346
# -2.05312249 -1.95523663 -1.84913768 -1.75415233 -1.66738719 -1.6029932
# -1.54596053 -1.50177363 -1.46133745 -1.42288915 -1.38241718 -1.34113191
# -1.30775884 -1.27309395 -1.23620286 -1.20592812 -1.18113435 -1.15029987]
# by position and slope
# [ 2.98153965 2.9385436 2.94993567 2.95897805 2.99214403 3.00138863
# 3.04390642 3.09685482 -3.11358085 -3.0466034 -2.95794156 -2.85595599
# -2.75067133 -2.64530394 -2.51567194 -2.39565127 -2.28148844 -2.17570346
# -2.05312249 -1.95523663 -1.84913768 -1.75415233 -1.66738719 -1.6029932
# -1.54596053 -1.50177363 -1.46133745 -1.42288915 -1.38241718 -1.34113191
# -1.30775884 -1.27309395 -1.23620286 -1.20592812 -1.18113435 -1.15029987]
# [-1.30507254 -1.33298928 -1.36415496 -1.39909924 -1.43845065 -1.48295087
# -1.53346541 -1.59098448 -1.65660299 -1.73146174 -1.8166248 -1.9128659
# -2.02035274 -2.13826992 -2.26451127 -2.3982946 -2.52735954 -2.65519436
# -2.77544658 -2.88566686 -2.98473857 -3.07261908 3.13322155 3.06539723
# 3.00595703 2.95378704 2.90786779 2.86730208 2.831318 2.79925996
# 2.77057495 2.74479777 2.72153718 2.70046364 2.68129889 2.66380717]
one = one + 2*np.pi*(one < 0)
two = two + 2*np.pi*(two < 0)
plt.figure(figsize=(8, 8))
plt.title(run)
t = np.arange(one.size)
maxi = np.maximum(one, two)
mini = np.minimum(one, two)
breaks = np.array([0])
ct = 0
first = np.array([])
second = np.array([])
ch = [maxi, mini]
for i in range(1, maxi.size):
if maxi[i] < mini[i-1] or mini[i] > maxi[i-1]:
breaks = np.append(breaks, [i])
ct += 1
first = np.append(first, ch[0][breaks[ct-1]:breaks[ct]])
second = np.append(second, ch[1][breaks[ct-1]:breaks[ct]])
ch = ch[::-1]
elif i != maxi.size-1:
if maxi[i] - mini[i] < 0.8*min(maxi[i-1] - mini[i-1], maxi[i+1] - mini[i+1]):
breaks = np.append(breaks, [i])
ct += 1
first = np.append(first, ch[0][breaks[ct - 1]:breaks[ct]])
second = np.append(second, ch[1][breaks[ct - 1]:breaks[ct]])
ch = ch[::-1]
first = np.append(first, ch[0][breaks[ct]:])
second = np.append(second, ch[1][breaks[ct]:])
plt.plot(maxi, 'r.', label='maxi')
plt.plot(mini, 'b.', label='mini')
plt.plot(first, label='first')
plt.plot(second, label='second')
plt.legend(prop={'size': 8})
plt.show()