【问题标题】:Evaluate k adjacent (plus or minus) elements within array评估数组中的 k 个相邻(正负)元素
【发布时间】:2017-04-25 17:20:24
【问题描述】:

我一直在努力解决对一维 numpy 数组中的k 相邻元素施加不等式阈值的任务——我应该在左侧和右侧都添加。例如:

if x[i+-100] < .05:

这是我能表达的最好的,显然它不起作用。但我希望我的观点更清楚。换句话说,我想辨别元素 x 的正负 100 个元素内是否有任何元素的值大于 0.05。这是我的整个上下文功能:(这里我也有 -.05)

def vector_recode(x):
    if (x[i+-100]) > .05 or (x[i+-100]) < -.05:
        return X
    else:
        return 0
recode_function = np.vectorize(vector_recode)

--为了清楚起见,上面的函数试图获取足够接近零的值并将它们刷新为零,或者如果附近有任何 [+-100] 元素的值高于 0.05 in绝对条件,保持 x 不变。

我有一种下沉的感觉,我可能不得不求助于循环,但 np 的效率总是让我感到惊讶,我希望有人有洞察力,可以帮助像我这样处理k相邻的其他人元素。

我对此过程的其他研究涉及scipy.ndimage 和卷积矩阵。但是我不认为这种方法很容易适用于我的情况——这只是一维左右相邻元素。虽然我以前错了。非常感谢任何帮助。

如果有帮助,我会尝试做一个可行的例子:

    >>>A
[0.04,0.03,0.03,0.02,0.04]
    >>>recode_function(A)
[0,0,0,0,0]
    >>>B
[0.03,0.02,0.23,0.01,0.03]
    >>>recode_function(B)
[0.03,0.02,0.23,0.01,0.03]

这里让我们说它的正负 5 不是正负 100。在数组“A”中没有大于 .05 或小于 -.05 的值,因此 x 及其相邻元素将设置为零在向量化函数中。而在数组“B”中有一个大于 0.05 的元素。它是 0.23,因此这意味着该函数将保留 x 以及 x 的正负 5 个相邻元素。正如有人正确指出的那样,可能需要仔细处理边界元素。您可以将“A”和“B”想象为两个不同的数组或 1 个更大数组的分区。我不确定分区是否可行,但我对任何事情都持开放态度。希望这能让你更容易理解。

【问题讨论】:

  • 边界元素左边或右边没有100个元素怎么办?
  • 另外,如果是x[i+-100]) &gt; .05,不也保证(x[i+-100]) &gt; -.05吗?
  • 很好的观察结果,我弄乱了不等号,让我解决这个问题。我想如果元素与值相邻并且在 100 个元素内,则可以处理边界元素,尽管我不确定在这种情况下 python 是否也会抛出越界错误。感谢您的意见。
  • 我的函数有点混乱,我把它写反了,抱歉。它现在是正确的形式。我对边界元素的另一个想法是从[:x] 对数组进行分区。
  • 是的,我确实想要一个or,谢谢。我也会尝试添加一个小例子。谢谢。

标签: python python-3.x numpy


【解决方案1】:

试着让你的 if 子句像这样

if (any(x[i:i+100:1]) > .05) and any((x[i-100:i+1:1]) < -.05):

但是,您还必须在 vector_recode 的定义中指定 i,即向量 x 中的索引。

另外this 的帖子似乎有你想要的更简洁的方式。

【讨论】:

  • 我明白了,谢谢你的领导。我想知道 np.sort() 是否改变了数组的顺序?在我的应用程序中,我需要保持数组原样,并且只引用数组中元素 x 的 100 个邻居,而不管 x 在数组中的哪个位置——并且数组中的每个元素都会变成 x,因为我正在申请np.vectorize()
  • @ArashHowaida np.sort() 没有到位,所以除非您存储函数的结果,否则您的数组将保留其状态
【解决方案2】:

一个技巧是将数组裁剪为分别在-0.050.05 的最小-最大限制,并检查哪些元素发生了变化,表明这些元素超出了这些最小-最大限制。这将导致一个二进制数组。然后,我们使用二元膨胀将这个 ANY 查找扩展到某个窗口大小。最后,基于扩展掩码,我们使用np.where 来选择是保留原始元素还是设置为0。

因此,实现将是 -

from scipy.ndimage.morphology import binary_dilation

def reset_arr(x, W, T): # x: input array, W : window size, T : threshold as +-
    mask = binary_dilation(x.clip(min=-T, max=T) != x,np.ones(2*W+1))
    return np.where(mask, x, 0)

示例运行 -

In [376]: x
Out[376]: 
array([ 0.06821936,  0.66300942,  0.15449635,  1.52260898,  0.41346868,
       -0.48343499,  0.45386276,  2.1888203 ,  0.36947105, -0.17660172])

In [377]: reset_arr(x, W = 1, T = 0.5)
Out[377]: 
array([ 0.06821936,  0.66300942,  0.15449635,  1.52260898,  0.41346868,
        0.        ,  0.45386276,  2.1888203 ,  0.36947105,  0.        ])

【讨论】:

  • 谢谢 divakar,当我最初发现 ndimage 方法相当复杂时,您的方法使我可以理解。效果很好。
【解决方案3】:

请注意,Python 的 abs() 函数也接受 NumPy 数组,并返回组件级结果:

>>> import numpy as np
>>> abs(np.array([-5, 1, -3.3, -2, 0, 11]))
array([  5. ,   1. ,   3.3,   2. ,   0. ,  11. ])

&gt; 运算符也是如此,即使另一个操作数是标量:

>>> abs(np.array([0.01, 0.07, -0.07, -0.02, 5])) > 0.05
array([False,  True,  True, False,  True], dtype=bool)

我们可以将其插入Divakar's answer 的方法中:

from scipy.ndimage.morphology import binary_dilation

def recode_function(data, k, threshold):
    mask = binary_dilation( abs(data) > threshold, np.ones(2 * k + 1) )
    return np.where(mask, data, 0)

如果您不关心零值的符号,只需(按组件)乘以掩码和数据也可以:

from scipy.ndimage.morphology import binary_dilation

def recode_function(data, k, threshold):
    mask = binary_dilation( abs(data) > threshold, np.ones(2 * k + 1) )
    return mask * data

【讨论】:

  • 也谢谢das-g,最后我采纳了你的建议,没有你们的专业我做不到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
相关资源
最近更新 更多