[英]Summing three consecutive number when equal to or great than 0 - Python
I am using numpy in Python我在 Python 中使用 numpy
I have an array of numbers, for example:我有一个数字数组,例如:
arr = np.array([0.1, 1, 1.2, 0.5, -0.3, -0.2, 0.1, 0.5, 1)
If i
is a position in the array, I want to create a function which creates a running sum of i
and the two previous numbers, but only accumulating the number if it is equal to or greater than 0.如果
i
是数组中的 position ,我想创建一个 function ,它创建i
和前两个数字的运行总和,但只有当它等于或大于 0 时才累加该数字。
In other words, negative numbers in the array become equal to 0 when calculating the three number running sum.换句话说,数组中的负数在计算三数运行和时等于0。
For example, the answer I would be looking for here is例如,我要在这里寻找的答案是
2.3, 2.7, 1.7, 0.5, 0.1, 0.6, 1.6
The new array has two elements less than the original array as the calculation can't be completed for the first two number.新数组的元素比原始数组少两个,因为前两个数字的计算无法完成。
Thank you !谢谢 !
As Dani Mesejo answered, you can use stride tricks.正如 Dani Mesejo 回答的那样,您可以使用跨步技巧。 You can either use clip or boolean indexing to handle the <0 elements.
您可以使用剪辑或 boolean 索引来处理 <0 元素。 I have explained how stride tricks work below -
我在下面解释了步幅技巧的工作原理 -
arr[arr<0]=0
sets all elements below 0 as 0 arr[arr<0]=0
将所有低于 0 的元素设置为 0as_strided
takes in the array, the expected shape of the view (7,3)
and the number of strides in the respective axes, (8,8)
. as_strided
接受数组、视图的预期形状(7,3)
和各个轴上的步幅数(8,8)
。 This is the number of bytes you have to move in axis0
and axis1
respectively to access the next element.axis0
和axis1
中移动以访问下一个元素的字节数。 Eg If you want to move every 2 elements, then you can set it to (16,8)
.(16,8)
。 This means you would move 16 bytes each time to get the element in axis0 (which is 0.1->1.2->0->0.1->..
, till a shape of 7
) and 8 bytes each time to get element in axis1 (which is 0.1->1->1.2
, till a shape of 3
)0.1->1.2->0->0.1->..
,直到形状为7
),每次移动 8 个字节以获取 axis1 中的元素(这是0.1->1->1.2
,直到形状为3
)Use this function with caution.
请谨慎使用此 function。 Always use x.strides to define the strides parameter to avoid corrupting memory!
始终使用 x.strides 来定义 strides 参数以避免损坏内存!
axis=1
to get your rolling sum.axis=1
上对这个数组视图求和以获得滚动总和。arr = np.array([0.1, 1, 1.2, 0.5, -0.3, -0.2, 0.1, 0.5, 1])
w = 3 #rolling window
arr[arr<0]=0
shape = arr.shape[0]-w+1, w #Expected shape of view (7,3)
strides = arr.strides[0], arr.strides[0] #Strides (8,8) bytes
rolling = np.lib.stride_tricks.as_strided(arr, shape=shape, strides=strides)
rolling_sum = np.sum(rolling, axis=1)
rolling_sum
array([2.3, 2.7, 1.7, 0.5, 0.1, 0.6, 1.6])
You could clip , roll and sum :您可以剪辑、滚动和求和:
import numpy as np
def rolling_window(a, window):
"""Recipe from https://stackoverflow.com/q/6811183/4001592"""
shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
strides = a.strides + (a.strides[-1],)
return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
a = np.array([0.1, 1, 1.2, 0.5, -0.3, -0.2, 0.1, 0.5, 1])
res = rolling_window(np.clip(a, 0, a.max()), 3).sum(axis=1)
print(res)
Output Output
[2.3 2.7 1.7 0.5 0.1 0.6 1.6]
You may use np.correlate
to sweep an array of 3 ones
over the clipped of arr
to get desired output您可以使用
np.correlate
在arr
的剪辑上扫描 3 ones
数组以获得所需的 output
In [20]: np.correlate(arr.clip(0), np.ones(3), mode='valid')
Out[20]: array([2.3, 2.7, 1.7, 0.5, 0.1, 0.6, 1.6])
arr = np.array([0.1, 1, 1.2, 0.5, -0.3, -0.2, 0.1, 0.5, 1])
def sum_3(x):
collector = []
for i in range(len(arr)-2):
collector.append(sum(arr[i:i+3][arr[i:i+3]>0]))
return collector
#output
[2.3, 2.7, 1.7, 0.5, 0.1, 0.6, 1.6]
Easiest and most comprehensible way.最简单和最容易理解的方式。 The collector will append the sum of the 3 consecutive numbers if their indices are
True
otherwise, they are all turned to 0
s.收集器将 append 三个连续数字的总和,如果它们的索引是
True
否则,它们都变成0
s。
The method is not general, it is for 3 consecutives but you can adapt it.该方法不通用,连续3次,但您可以调整它。
def sum_any(x,n):
collector = []
for i in range(len(arr)-(n-1)):
collector.append(sum(arr[i:i+n][arr[i:i+n]>0]))
return collector
Masked arrays and view_as_windows (which uses numpy strides under the hood) are built for this purpose:蒙面的 arrays 和 view_as_windows(在引擎盖下使用 numpy 跨步)是为此目的而构建的:
from skimage.util import view_as_windows
arr = view_as_windows(arr, 3)
arr2 = np.ma.masked_array(arr, arr<0).sum(-1)
output: output:
[2.3 2.7 1.7 0.5 0.1 0.6 1.6]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.