numpy数组中的向后计数
Posted
技术标签:
【中文标题】numpy数组中的向后计数【英文标题】:backward count in a numpy array 【发布时间】:2019-10-13 05:01:19 【问题描述】:假设我有一系列像这样排列在一个 numpy 数组中的整数值。
nan = np.nan
arr = np.array([3, nan, nan, nan, 5, nan, nan, nan, nan, nan])
nan
值应该用从第一个非空值到零的反向计数填充。
[3, 2, 1, 0, 5, 4, 3, 2, 1, 0]
【问题讨论】:
熊猫也有用吗? 没错 【参考方案1】:IMO,最简单的 pandas 方法是使用 groupby
和 cumcount
和 ascending=False
:
s = pd.Series(np.cumsum(~np.isnan(arr)))
s.groupby(s).cumcount(ascending=False)
0 3
1 2
2 1
3 0
4 5
5 4
6 3
7 2
8 1
9 0
dtype: int64
【讨论】:
@QuangHoang 抱歉,我不确定我是否关注。它用(递减的)计数标记每个组中的行。 对不起,我一定是在做白日梦。 +1【参考方案2】:这是一个带有 NumPy 的矢量化 -
def backward_count(a):
m = ~np.isnan(a)
idx = np.flatnonzero(m)
p = np.full(len(a), -1, dtype=a.dtype)
p[idx[0]] = a[idx[0]]+idx[0]
d = np.diff(idx)
p[idx[1:]] = np.diff(a[m]) + d - 1
out = p.cumsum()
out[:idx[0]] = np.nan
return out
使用更通用的案例运行示例 -
In [238]: a
Out[238]: array([nan, 3., nan, 5., nan, 10., nan, nan, 4., nan, nan])
In [239]: backward_count(a)
Out[239]: array([nan, 3., 2., 5., 4., 10., 9., 8., 4., 3., 2.])
基准测试
通过10,000x
放大给定样本的设置-
In [240]: arr = np.array([3, nan, nan, nan, 5, nan, nan, nan, nan, nan])
In [241]: arr = np.tile(arr,10000)
# Pandas based one by @cs95
In [243]: %%timeit
...: s = pd.Series(np.cumsum(~np.isnan(arr)))
...: s.groupby(s).cumcount(ascending=False)
35.9 ms ± 258 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [245]: %timeit backward_count(arr)
3.04 ms ± 4.35 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
【讨论】:
【参考方案3】:import pandas as pd
import numpy as np
import math
arr = pd.Series([3,np.nan,np.nan,np.nan,5,np.nan,np.nan,np.nan,np.nan,np.nan])
for i in range(len(arr)):
# Check if each element is "NaN"
if math.isnan(arr[i]):
# If NaN then take the previous element and subtract 1
arr[i] = arr[i-1]-1
# print the final array
print(arr)
结果:
0 3.0
1 2.0
2 1.0
3 0.0
4 5.0
5 4.0
6 3.0
7 2.0
8 1.0
9 0.0
dtype: float64
【讨论】:
1) 你没有解释你的代码(是的,这对我来说很明显,但对每个阅读它的人来说都不是),2) 在 numpy 中使用循环是禁忌。 我自己是 numpy 新手,为什么循环不好? NumPy 操作被实现为比循环更快、更具可扩展性。该过程称为"vectorisation",在性能方面比循环高出几步。以上是关于numpy数组中的向后计数的主要内容,如果未能解决你的问题,请参考以下文章