Python 用最后一个非零值填充1d numpy数组的零值
假设我们有一个1d numpy数组,其中填充了一些Python 用最后一个非零值填充1d numpy数组的零值,python,numpy,Python,Numpy,假设我们有一个1d numpy数组,其中填充了一些int值。假设其中一些是0 是否有任何方法,使用numpy数组的幂,用最后找到的非零值填充所有0值 例如: arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2]) fill_zeros_with_last(arr) print arr [1 1 1 2 2 4 6 8 8 8 8 8 2] 一种方法是使用此功能: def fill_zeros_with_last(arr): la
int
值。假设其中一些是0
是否有任何方法,使用numpy
数组的幂,用最后找到的非零值填充所有0
值
例如:
arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2])
fill_zeros_with_last(arr)
print arr
[1 1 1 2 2 4 6 8 8 8 8 8 2]
一种方法是使用此功能:
def fill_zeros_with_last(arr):
last_val = None # I don't really care about the initial value
for i in range(arr.size):
if arr[i]:
last_val = arr[i]
elif last_val is not None:
arr[i] = last_val
但是,这是使用原始pythonfor
循环,而不是利用numpy
和scipy
的强大功能
如果我们知道一个合理数量的连续零是可能的,我们可以使用基于numpy.roll
的东西。问题是连续零的数量可能很大
有什么想法吗?或者我们应该直接去西顿吗
免责声明:
我想说很久以前,我在stackoverflow中发现了一个问题,问了一些类似的问题。我没能找到它-(
也许我错过了正确的搜索词,很抱歉重复了。也许这只是我的想象…这里有一个使用
np.max.accumulate的解决方案:
def fill_zeros_with_last(arr):
prev = np.arange(len(arr))
prev[arr == 0] = 0
prev = np.maximum.accumulate(prev)
return arr[prev]
我们构造了一个数组prev
,其长度与arr
相同,并且prev[i]
是arr
第i个条目之前最后一个非零条目的索引。例如,如果:
>>> arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2])
然后prev
看起来像:
array([ 0, 0, 0, 3, 3, 5, 6, 7, 7, 7, 7, 7, 12])
然后我们用prev
索引到arr
,我们得到了我们的结果。测试:
>>> arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2])
>>> fill_zeros_with_last(arr)
array([1, 1, 1, 2, 2, 4, 6, 8, 8, 8, 8, 8, 2])
注意:请注意,当数组的第一个条目为零时,这会发生什么:
>>> fill_zeros_with_last(np.array([0,0,1,0,0]))
array([0, 0, 1, 1, 1])
下面是一个使用np.maximum.accumulate
的解决方案:
def fill_zeros_with_last(arr):
prev = np.arange(len(arr))
prev[arr == 0] = 0
prev = np.maximum.accumulate(prev)
return arr[prev]
我们构造了一个数组prev
,其长度与arr
相同,并且prev[i]
是arr
第i个条目之前最后一个非零条目的索引。例如,如果:
>>> arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2])
然后prev
看起来像:
array([ 0, 0, 0, 3, 3, 5, 6, 7, 7, 7, 7, 7, 12])
然后我们用prev
索引到arr
,我们得到了我们的结果。测试:
>>> arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2])
>>> fill_zeros_with_last(arr)
array([1, 1, 1, 2, 2, 4, 6, 8, 8, 8, 8, 8, 2])
注意:请注意,当数组的第一个条目为零时,这会发生什么:
>>> fill_zeros_with_last(np.array([0,0,1,0,0]))
array([0, 0, 1, 1, 1])
如果0
s仅以1的字符串形式出现,则非零的使用可能会起作用:
In [266]: arr=np.array([1,0,2,3,0,4,0,5])
In [267]: I=np.nonzero(arr==0)[0]
In [268]: arr[I] = arr[I-1]
In [269]: arr
Out[269]: array([1, 1, 2, 3, 3, 4, 4, 5])
我可以通过反复应用此选项来处理您的arr
,直到I
为空
In [286]: arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2])
In [287]: while True:
.....: I=np.nonzero(arr==0)[0]
.....: if len(I)==0: break
.....: arr[I] = arr[I-1]
.....:
In [288]: arr
Out[288]: array([1, 1, 1, 2, 2, 4, 6, 8, 8, 8, 8, 8, 2])
如果0的字符串较长,则最好查找这些字符串并将其作为块处理。但如果大多数字符串较短,则此重复应用程序可能是最快的路径。如果0
s的字符串仅为1,则使用非零
可能有效:
In [266]: arr=np.array([1,0,2,3,0,4,0,5])
In [267]: I=np.nonzero(arr==0)[0]
In [268]: arr[I] = arr[I-1]
In [269]: arr
Out[269]: array([1, 1, 2, 3, 3, 4, 4, 5])
我可以通过反复应用此选项来处理您的arr
,直到I
为空
In [286]: arr = np.array([1, 0, 0, 2, 0, 4, 6, 8, 0, 0, 0, 0, 2])
In [287]: while True:
.....: I=np.nonzero(arr==0)[0]
.....: if len(I)==0: break
.....: arr[I] = arr[I-1]
.....:
In [288]: arr
Out[288]: array([1, 1, 1, 2, 2, 4, 6, 8, 8, 8, 8, 8, 2])
如果0的字符串很长,则最好查找这些字符串并将其作为块处理。但如果大多数字符串都很短,则此重复应用程序可能是最快的方法。受的启发,我提出了不同的numpy函数组合:
def fill_zeros_with_last(arr, initial=0):
ind = np.nonzero(arr)[0]
cnt = np.cumsum(np.array(arr, dtype=bool))
return np.where(cnt, arr[ind[cnt-1]], initial)
我认为它很简洁,也很有效,所以我把它发布在这里记录在案。不过,'s也很简洁,容易理解,而且似乎更快,所以我接受了它:-)受的启发,我在这里和(在链接的问题中)提出了一个不同的numpy函数组合:
def fill_zeros_with_last(arr, initial=0):
ind = np.nonzero(arr)[0]
cnt = np.cumsum(np.array(arr, dtype=bool))
return np.where(cnt, arr[ind[cnt-1]], initial)
我认为它很简洁,也很有效,所以我把它贴在这里记录在案。尽管如此,“s”还是简洁易懂,而且似乎速度更快,所以我接受它:-)如果您不介意使用pandas
,请看一下ffill
方法(或者查看fillna
了解完整的故事)。然而,numpy中没有内置“向前填充”类型的功能。正如@JoeKington所提到的,pandas中的fillna
可以做到这一点。Cython源是pad\u 2d\u inplace\u
函数,特别是底部的内环。代码正是您在示例中编写的。@JoeKington谢谢!功能不错!尽管如此,我还是希望避免依赖于pandas
。如果您不介意使用pandas
,请查看ffill
方法(或参阅fillna
了解完整的故事)。然而,numpy中没有内置“向前填充”类型的功能。正如@JoeKington所提到的,pandas中的fillna
可以做到这一点。Cython源是pad\u 2d\u inplace\u
函数,特别是底部的内环。代码正是您在示例中编写的。@JoeKington谢谢!功能不错!不过,我还是不想依靠熊猫来解决这个问题……你的答案可能比我的快——除非我的就地操作可能会节省时间。我自己也试过一个,但这一个还是一样好,而且更快的。:)谢谢你的答案可能比我的答案快——除非我的就地操作可能会节省时间。我自己尝试了一个,但这一个至少同样好而且快。:)谢谢不幸的是,我确实预期可能会有许多连续的0
。我想了些什么,但是for循环没有说服我…:-/不幸的是,我确实预期可能会有许多连续的0
。我想了些什么,但是for循环没有说服我…:-/很不错的。。。还有一个潜在的解决方案是使用np.repeat
,但要正确设置边界似乎有点困难。它可能也没有我们两个的快。非常好。。。还有一个潜在的解决方案是使用np.repeat
,但要正确设置边界似乎有点困难。它可能也没有我们两个的速度快。