【问题标题】:using np.where with indices使用带有索引的 np.where
【发布时间】:2019-05-17 09:33:09
【问题描述】:

我有一个零数组 (17520,5),我想用两个值填充:0 和 0.05。我有两个条件,我正在使用函数 np.where,但是,我只需要在数组的特定索引处应用第二个条件。我使用的代码如下:

independent = np.zeros([17520,5])
w1 = np.where(independent == 0)
independent[w1] = np.random.choice([0.0, 0.05], size=len(w1[0]))

这部分代码工作正常,并用所需的值填充零数组(独立):0 和 0.05 具有相同的比例 (50/50)。另一方面,第二个条件只需要在特定索引处实现,如下所示:

for n in range(0, 365):
    start = 24 + n*48
    end = 46 + n*48
    w2 = np.where(independent == 0.05)
    independent[w2][start:end,0:5]=np.random.choice([0.0, 0.05], (22,5),size=len(w2[0]))

其中 [start:end,0:5] 表示我要实现条件 w2 的索引。

非常感谢您的帮助,指出使用带有索引的函数 np.where 的正确方法,因为目前我遇到以下错误

 SyntaxError: invalid syntax

【问题讨论】:

  • 问题出在np.random.choice()(22,5)len(w2[0]) 都是同一变量 size 的输入。
  • 我只留下 (22,5) 并且出现以下错误 IndexError: too many indices for array
  • 现在问题出在independent[w2][start:end,0:5]。您提供的索引过多,在第二个方括号中,应该只有 start:end0:5 之间的一个。或者你必须删除第一个方括号。
  • independent[w2] 是副本,不是视图

标签: python performance numpy


【解决方案1】:

请注意,np.where 也可以采用两个 array_like 参数,根据 条件 从中进行选择。以下是在您的情况下使用 np.where 的方法:

for n in range(0, 365):
    start = 24 + n*48
    end = 46 + n*48
    independent[start:end,0:5] = (np.where(independent== 0.05, 
                                          np.random.choice([0.0, 0.05], 
                                                    size=independent.shape), 
                                          independent)[start:end,0:5])

这有点棘手,但上面可以矢量化。关键是获取我们希望更新independent 的范围列表。为此,我们可以使用链接答案中的n_ranges,它可用于获取一个平面数组,其中包含对应的startend 的所有范围:

start = 24 + np.arange(0, 365)*48
end = 46 + np.arange(0, 365)*48
ranges = n_ranges(start, end)
independent[ranges,0:5] = (np.where(independent== 0.05, 
                                   np.random.choice([0.0, 0.05], 
                                                    size=independent.shape), 
                                   independent)[ranges,0:5])

检查时间,我们可以看到,使用第二种方法,我们获得了 260x 加速!

def vect_approach(a):
    start = 24 + np.arange(0, 365)*48
    end = 46 + np.arange(0, 365)*48
    ranges = n_ranges(start, end)
    a[ranges,0:5] = (np.where(a== 0.05, 
                             np.random.choice([0.0, 0.05], size=a.shape ),
                             a)[ranges,0:5])

def loopy_approach(x):
    for n in range(0, 365):
        start = 24 + n*48
        end = 46 + n*48
        independent[start:end,0:5] = (np.where(independent== 0.05, 
                                              np.random.choice([0.0, 0.05], 
                                                        size=independent.shape), 
                                              independent)[start:end,0:5])

independent = np.zeros([17520,5])

%timeit loopy_approach(independent)
# 475 ms ± 19.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit vect_approach(independent)
# 1.87 ms ± 95.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

【讨论】:

  • 感谢您的回答,第一个解决方案有效,但是,当我尝试使用第二个解决方案时,出现以下错误 NameError: name 'n_ranges' is not defined
  • 是的@JonathanBudez 转到我附加的链接,n_ranges 是我在其他帖子中的回答。使用该功能。它会加速你的实施:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-08
  • 2020-04-29
  • 1970-01-01
  • 2022-12-02
相关资源
最近更新 更多