【问题标题】:Array formatting with argmax numpy Python使用 argmax numpy Python 进行数组格式化
【发布时间】:2021-05-19 20:34:47
【问题描述】:

我在使用Numbers[(Numbers<=0).argmax():] = 0 函数时遇到问题,如果满足条件,它应该将其后面的所有元素都变为零,但是如果不满足条件,它会将所有数组元素变为零。我该如何解决这个问题。如果不满足Numbers<=0 条件,则数组不应更改。

在-35.15610151处满足条件的数组:

Numbers = np.array([123.6,       123.6 ,       123.6,        110.3748,     111.6992976,
 102.3165566,   97.81462811 , 89.50038472 , 96.48141473 , 90.49956702,
  88.59907611 , 77.96718698,  61.51611052,  56.84088612,  55.36302309,
  54.69866681,  56.44902415 , 59.49727145,  42.12406819,  27.42276839,
  33.86711896,  32.10602877,  -35.15610151,  32.34361339 , 29.20628289])

Numbers[(Numbers<=0).argmax():] = 0

输出:

[123.6        123.6        123.6        110.3748     111.6992976
 102.3165566   97.81462811  89.50038472  96.48141473  90.49956702
  88.59907611  77.96718698  61.51611052  56.84088612  55.36302309
  54.69866681  56.44902415  59.49727145  42.12406819  27.42276839
  33.86711896  32.10602877   0.           0.           0.        ]

不满足条件的数组,将-35.15610151变成+35.15610151:

Numbers = np.array([123.6,       123.6 ,       123.6,        110.3748,     111.6992976,
 102.3165566,   97.81462811 , 89.50038472 , 96.48141473 , 90.49956702,
  88.59907611 , 77.96718698,  61.51611052,  56.84088612,  55.36302309,
  54.69866681,  56.44902415 , 59.49727145,  42.12406819,  27.42276839,
  33.86711896,  32.10602877,  35.15610151,  32.34361339 , 29.20628289])

Numbers[(Numbers<=0).argmax():] = 0

输出:

[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0.]

【问题讨论】:

  • 你自己检查过(Numbers&lt;=0).argmax()吗?如果这不正确,则更大的表达式也不正确。
  • np.ones(3, bool).argmax()为0,第一个True

标签: python arrays function numpy sorting


【解决方案1】:

试试这两种方法,一种是在原地分配给 NumPy 视图,另一种是创建一个新数组以分配给另一个变量 -

#Method 1 (Inplace assignment)
Numbers[(Numbers<=0).cumsum(dtype=bool)] = 0

或者,

#Method 2 (Not inplace)
np.where(~(Numbers<=0).cumsum(dtype=bool), Numbers, 0)

或者,

#As an excellent suggestion by Mad Physicist!
Numbers[np.logical_or.accumulate(Numbers >= 0)] = 0

解释-

  1. 返回[F, F, F, T, F, F, F]的bool数组可以看成1和0的数组。执行 cumsum 最终会将第一个 T 传播到后续元素。

  2. 因此,这会将数组转换为 [F, F, F, T, T, T, T],现在可以仅与 boolean indexing 一起使用,并将视图设置为 0 或 np.where 以获取原始元素或 0,基于使用 ~ 反转布尔值

  3. 这里的好处是,如果你的数组只是由 False 组成,意味着没有元素满足条件,它只会返回原始的Numbers 本身,而不是将它们设置为 0。


运行测试 -

  1. 具有满足条件的值
Numbers = np.array([123.6 , 123.6 ,  -123.6, 110.3748 ,  111.6992976, 102.3165566,  97.81462811])

Numbers[(Numbers<=0).cumsum(dtype=bool)] = 0

#array([123.6, 123.6,   0. ,   0. ,   0. ,   0. ,   0. ])
  1. 没有符合条件的值
Numbers = np.array([123.6 , 123.6 ,  123.6, 110.3748 ,  111.6992976, 102.3165566,  97.81462811])

Numbers[(Numbers<=0).cumsum(dtype=bool)] = 0

#array([123.6 , 123.6 , 123.6 , 110.3748 ,111.6992976 , 102.3165566 ,  97.81462811])

编辑:应要求的新场景

Numbers1 = np.array([1.1, 2.2, 3.3, 4.4, 5.5])
Numbers2 = np.array([1,2,-3,4,5])

Numbers2 = np.where(~(Numbers2<=0).cumsum().astype(bool), Numbers1, 0)
Numbers2
array([1.1, 2.2, 0. , 0. , 0. ])

【讨论】:

  • 效率更高,n[np.logical_or.accumulate(n &gt;= 0)] = 0
  • 谢谢你的作品。有没有一种方法可以实现它,以便它也扫描另一个数组,如np.where(~(Numbers2&lt;=0).cumsum().astype(bool), Numbers, 0),其中Numbers2 是另一个数组,如Numbers,具有相同的长度,但对于低于0的数字,它只是将Numbers元素修改为0。 `
  • 相同的代码是否也适用于此? np.where(~(Numbers2&lt;=0).cumsum().astype(bool), Numbers, 0)?
  • 为我工作。我已经编辑了我的答案做检查。
  • 谢谢,我犯了一个愚蠢的错误,谢谢它有效
【解决方案2】:

这个用if就行了,很好的表达了意图,也很容易理解:

smaller_equal_zero = Numbers <= 0
if smaller_equal_zero.any():
    Numbers[smaller_equal_zero.argmax():] = 0

在 Python 3.8+ 中,您可以在 if 中使用赋值表达式:

if (smaller_equal_zero := Numbers <= 0).any():
    Numbers[smaller_equal_zero.argmax():] = 0

【讨论】:

    猜你喜欢
    • 2021-12-22
    • 2021-04-30
    • 2021-12-02
    • 2021-05-17
    • 2021-06-02
    • 2021-06-30
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多