简体   繁体   English

沿着NumPy数组的行在特定位置插入零行

[英]Inserting rows of zeros at specific places along the rows of a NumPy array

I have a two column numpy array. 我有一个两列numpy数组。 I want to go through each row of the 2nd column, and take the difference between each set of 2 numbers (9.6-0, 19.13-9.6, etc). 我想通过第2列的每一行,并取每组2个数字(9.6-0,19.13-9.6等)之间的差异。 If the difference is > 15, I want to insert a row of 0s for both columns. 如果差值> 15,我想为两列插入一行0。 I really only need to end up with values in the first column (I only need the second to determine where to put 0s), so if it's easier to split them up that would be fine. 我真的只需要在第一列中结束值(我只需要第二列来确定将0放在哪里),所以如果更容易将它们拆分,那就没问题了。

This is my input array: 这是我的输入数组:

 [[0.00 0.00]
 [1.85 9.60]
 [2.73 19.13]
 [0.30 28.70]
 [2.64 38.25]
 [2.29 47.77]
 [2.01 57.28]
 [2.61 66.82]
 [2.20 76.33]
 [2.49 85.85]
 [2.55 104.90]
 [2.65 114.47]
 [1.79 123.98]
 [2.86 133.55]]

and it should turn into: 它应该变成:

 [[0.00 0.00]
 [1.85 9.60]
 [2.73 19.13]
 [0.30 28.70]
 [2.64 38.25]
 [2.29 47.77]
 [2.01 57.28]
 [2.61 66.82]
 [2.20 76.33]
 [2.49 85.85]
 [0.00 0.00]
 [2.55 104.90]
 [2.65 114.47]
 [1.79 123.98]
 [2.86 133.55]]

You can do in a one liner using ediff1d , argmax and insert from numpy : 你可以使用ediff1dargmaxnumpy insert进行ediff1d argmax

np.insert(arr, np.argmax(np.append(False, np.ediff1d(arr[:,1])>15)), 0, axis=0)

#array([[   0.  ,    0.  ],
#       [   1.85,    9.6 ],
#       [   2.73,   19.13],
#       [   0.3 ,   28.7 ],
#       [   2.64,   38.25],
#       [   2.29,   47.77],
#       [   2.01,   57.28],
#       [   2.61,   66.82],
#       [   2.2 ,   76.33],
#       [   2.49,   85.85],
#       [   0.  ,    0.  ],
#       [   2.55,  104.9 ],
#       [   2.65,  114.47],
#       [   1.79,  123.98],
#       [   2.86,  133.55]])

Assuming A as the input array, here's a vectorized approach based on initialization with zeros - 假设A作为输入数组,这里是一个基于零初始化的矢量化方法 -

# Get indices at which such diff>15 occur 
cut_idx = np.where(np.diff(A[:,1]) > 15)[0]

# Initiaize output array
out = np.zeros((A.shape[0]+len(cut_idx),2),dtype=A.dtype)

# Get row indices in the output array at which rows from A are to be inserted.
# In other words, avoid rows to be kept as zeros. Finally, insert rows from A.
idx = ~np.in1d(np.arange(out.shape[0]),cut_idx + np.arange(1,len(cut_idx)+1))
out[idx] = A

Sample input, output - 样本输入,输出 -

In [50]: A  # Different from the one posted in question to show variety
Out[50]: 
array([[   0.  ,    0.  ],
       [   1.85,    0.6 ],
       [   2.73,   19.13],
       [   2.2 ,   76.33],
       [   2.49,   85.85],
       [   2.55,  104.9 ],
       [   2.65,  114.47],
       [   1.79,  163.98],
       [   2.86,  169.55]])

In [51]: out
Out[51]: 
array([[   0.  ,    0.  ],
       [   1.85,    0.6 ],
       [   0.  ,    0.  ],
       [   2.73,   19.13],
       [   0.  ,    0.  ],
       [   2.2 ,   76.33],
       [   2.49,   85.85],
       [   0.  ,    0.  ],
       [   2.55,  104.9 ],
       [   2.65,  114.47],
       [   0.  ,    0.  ],
       [   1.79,  163.98],
       [   2.86,  169.55]])
a=[[0.00, 0.00],
 [1.85, 9.60],
 [2.73, 19.13],
 [0.30, 28.70],
 [2.64, 38.25],
 [2.29, 47.77],
 [2.01, 57.28],
 [2.61, 66.82],
 [2.20, 76.33],
 [2.49, 85.85],
 [2.55, 104.90],
 [2.65, 114.47],
 [1.79, 123.98],
 [2.86, 133.55]]

i=0
while i <len(a)-1:
    if (a[i+1][1]-a[i][1])>15:
        a.insert(i+1,[0,0])
        i=i+1
    i=i+1    

for line in a :
    print line

output: 输出:

[0.0, 0.0]
[1.85, 9.6]
[2.73, 19.13]
[0.3, 28.7]
[2.64, 38.25]
[2.29, 47.77]
[2.01, 57.28]
[2.61, 66.82]
[2.2, 76.33]
[2.49, 85.85]
[0, 0]
[2.55, 104.9]
[2.65, 114.47]
[1.79, 123.98]
[2.86, 133.55]

Here's right algorithm: 这是正确的算法:

arr = [ ... ]
result = []
result.append(arr[0])
for i in range(1, len(arr)):
    if arr[i][1] - arr[i-1][1] > 15:
        result.append([0.0,0.0])
    result.append(arr[i])

print(result)

A one liner that can handle more than one fill slot. 一个可以处理多个填充槽的衬垫。 Here I'm testing it on the OP example, with one modified value. 在这里,我在OP示例中测试它,其中包含一个修改后的值。

In [70]: np.insert(a, np.where(np.diff(a[:,1])>15)[0]+2,0, axis=0)


In [71]: Out[70]: 
array([[   0.  ,    0.  ],
       [   1.85,    9.6 ],
       [   2.73,   19.13],
       [   0.3 ,   28.7 ],
       [   2.64,   38.25],
       [   2.29,  140.  ],   # modified
       [   0.  ,    0.  ],
       [   2.01,   57.28],
       [   2.61,   66.82],
       [   2.2 ,   76.33],
       [   2.49,   85.85],
       [   2.55,  104.9 ],
       [   0.  ,    0.  ],
       [   2.65,  114.47],
       [   1.79,  123.98],
       [   2.86,  133.55]])

The use of where instead of argmax ( Colonel's answer) handles more than one slot. 使用where而不是argmaxColonel's答案)处理多个槽。 The +2 is required because diff is one short, and we are inserting after. +2是必需的,因为diff是一个short,我们之后插入。 ediff1d has more options for handling the end points. ediff1d有更多处理端点的选项。

np.insert has various strategies for filling. np.insert有各种填充策略。 In this case it probably is doing something similar to Divakar's answer - create an out , and copy values to the correct slots. 在这种情况下,它可能正在做类似于Divakar's答案 - 创建一个out ,并将值复制到正确的插槽。

Another answer uses np.abs() . 另一个答案使用np.abs() That might be needed, but in my example that would add another 0 row, after the 140 drops back to 57 . 这可能是需要的,但在我的例子中,在140回落到57后会增加另外0行。

I'd be surprised if numpy didn't have some native methods for doing this sort of thing but I think this will work too: 如果numpy没有一些本地方法来做这类事情我会感到惊讶但我认为这也会有用:

i = 1
while i < len(lst):
    if abs(lst[i][1] - lst[i-1][1]) > 15:
        lst[i] = [0.0, 0.0]
        # uncomment to change only the second column
        # lst[i][1] = 0.0
        i += 1
    i += 1

Output: 输出:

>>> lst
array([[   0.  ,    0.  ],
       [   1.85,    9.6 ],
       [   2.73,   19.13],
       [   0.3 ,   28.7 ],
       [   2.64,   38.25],
       [   2.29,   47.77],
       [   2.01,   57.28],
       [   2.61,   66.82],
       [   2.2 ,   76.33],
       [   2.49,   85.85],
       [   2.55,  104.9 ],
       [   2.65,  114.47],
       [   1.79,  123.98],
       [   2.86,  133.55]])
>>> 
>>> i = 1
>>> while i < len(lst):
...     if abs(lst[i][1] - lst[i-1][1]) > 15:
...         lst[i] = [0.0, 0.0]
...         i += 1
...     i += 1
... 
>>> lst
array([[   0.  ,    0.  ],
       [   1.85,    9.6 ],
       [   2.73,   19.13],
       [   0.3 ,   28.7 ],
       [   2.64,   38.25],
       [   2.29,   47.77],
       [   2.01,   57.28],
       [   2.61,   66.82],
       [   2.2 ,   76.33],
       [   2.49,   85.85],
       [   0.  ,    0.  ],
       [   2.65,  114.47],
       [   1.79,  123.98],
       [   2.86,  133.55]])
>>> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM