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()