python - 具有上限的numpy数组的重新分配
问题描述
我目前正在努力编写遵循简单规则的高效函数。
让我们假设矩阵(它总是降序排序)。
| 7 4 3 2 | # sums up to 16
| 3 2 1 0 | # sums up to 6
我想将值剪裁到某个数字(让它为 5),但是剪裁中的“休息”应该传播到右侧的列中(这些列也应该被剪裁等等)。因此,在头脑中,结果矩阵应如下所示:
| 5 5 4 2 | # still sums up to 16, but values "moves" to the right
| 3 2 1 0 | # no value extends 5 do nothing happens
算法在用一个循环编写它时并不难(将剪裁的值保存到缓冲区,将其分发到下一列,等等),效果很好,但正如我所说,使用矢量化来实现这一点是理想的(并使用任何循环关闭)。我尝试了一些 cumsum + clip + diff 解决方案,但没有任何效果。现在我被困住了。
感谢您的任何帮助。
解决方案
如果你有很多行而不是太多列,你可以这样处理:
import numpy as np
def carry(sample,cap):
result = sample.copy()
for c in range(1,result.shape[1]):
result[:,c] += np.maximum(result[:,c-1]-cap,0)
result[:,:-1] = np.minimum(result[:,:-1],cap)
return result
输出:
sample = np.array([[7, 4, 2,0], [3, 2, 1, 0]])
cap = 5
carry(sample,cap)
# [[5, 5, 3, 0],
[3, 2, 1, 0]]
[编辑] 没有循环的解决方案
尽管这可能无法利用完全矢量化(并且运行速度较慢),但它可以在没有任何循环的情况下解决问题:
def carry(sample,cap):
fCarry = np.frompyfunc(lambda a,b:b+max(0,a-cap),2,1)
result = fCarry.accumulate(sample,dtype=np.object,axis=1)
return np.minimum(cap,result.astype(sample.dtype))
使用自定义 ufunc 累积将额外的金额(超过上限)带到下一个元素。然后所有元素在结束时被降低到指定的上限(它们的进位已经转移到下一个邻居)
推荐阅读
- php - Laravel 不生成代码覆盖率报告
- r - R - spatstat:计算新点的密度
- c# - ASP.NET Core 5.0 MVC 中的自定义字段验证错误
- react-native - 如何在 react native 中访问适用于 android 和 ios 的 cameraRoll/photos
- c# - 如何按子实体的属性分组并在linq中获取子实体的总和?
- ruby-on-rails - rbenv:乘客状态:找不到命令
- c - 检查文件是否为二进制可执行文件
- python - 在 Bokeh 中更新 ColorBar
- django - 如何测试基于类的 FormView 的 Django 消息?
- debugging - 我在使用 vscode 调试多个 C 文件时遇到问题。我现在的配置似乎只适用于 1 个 C 文件