- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想计算数组中某个范围的总和(简单) - 但我不想这样做,但要计算 n 次,并且应该求和的范围来自第二个数组。
我有一个包含 0 和 1 的二维数组:
count = np.array(\
[[0,1,0,0,1,0,1],
[0,0,1,1,1,0,0]])
我有一个结构化的二维数组,它有一个字段,其中的范围是对计数数组求和的范围。
dtype=[..., ('ranges', 'u1', (2, 2)) , ...]
table['ranges']
如下所示:
[
[[1, 3], [0, 4]],
[[0, 0], [3, 4]],
[[0, 0], [2 4]],
[[0, 0], [3 4]],
[[3, 7], [1 5]]]
(通常在 20 到几百行之间)。
这个例子的结果应该是
[2, # = (1 +0) + (0 + 0 +1)
1, # = ( ) + (1)
2, # = ( ) + (1 + 1)
1, # = ( ) + (1)
5] # = (0 + 1 +0 +1 ) + (0 + 1 + 1 + 1)
首先我开始:
result = np.zeros(table.size, dtype=np.int)
for index, r in enumerate(table):
for index, range in enumerate(r['ranges']):
result[index] += np.sum(counts[index][range[0]:range[1]])
给出了正确的结果,但不是效率的例子。
我还尝试消除第二个循环并对其进行更多的 numpyfy:
result = np.zeros(table.size, dtype=np.int)
for index, (from1, to1, from2, to2) in \
enumerate(np.nditer(table['ranges'], flags=['external_loop'])):
counts[index] += np.sum(counts[0][from1:to1]) +\
np.sum(counts[1][from2:to2])
但是这些代码行仍然是应用程序花费大部分时间的地方。该应用程序比这要大得多,但根据分析器,这些行花费的时间大约减半。
所以基本上我正在寻找一种方法来摆脱循环并在 numpy 中完成这一切。我一直在寻找类似的东西
counts=np.sum(counts[1][table['ranges'][0][0]:table['ranges'][0][1])+np.sum(counts[2][table['ranges'][1][0]:table['ranges'][1][1])
但到目前为止还没有真正找到一个好的方法来做到这一点。
更新进行了一些时间比较:
import numpy as np
import timeit as ti
table = np.empty(5,
dtype=[('s1', np.int8),
('ranges', 'u1', (2, 2)),
('s2', np.int16)])
table["ranges"] = [((1, 3), (0, 4)),
((0, 0), (3, 4)),
((0, 0), (2, 4)),
((0, 0), (3, 4)),
((3, 7), (1, 5))]
results = np.zeros(table.size)
counts = np.array([[0, 1, 0, 0, 1, 0, 1],
[0, 0, 1, 1, 1, 0, 0]])
# version one
def rv1(table, counts, results):
for row_index, r in enumerate(table):
for index, crange in enumerate(r['ranges']):
results[row_index] += np.sum(counts[index][crange[0]:crange[1]])
# version two
def rv2(table, counts, results):
for rowindex, (f1, t1, f2, t2) in \
enumerate(np.nditer(table['ranges'], flags=['external_loop'])):
results[rowindex] += np.sum(counts[0][f1:t1]) +\
np.sum(counts[1][f2:t2])
# version 3 (TomNash)
def rvTN(table, counts, results):
ranges=table["ranges"]
result=[
sum(counts[0][slice(*ranges[i][0])]) + sum(counts[1][slice(*ranges[i][1])])
for i in range(len(ranges))]
results+=result
results = np.zeros(table.size)
rv1(table, counts, results)
print ("rv1 result" , results)
results = np.zeros(table.size)
rv2(table, counts, results)
print ("rv2 result", results)
results = np.zeros(table.size)
rvTN(table, counts, results)
print ("slice*(TN) result", results)
print ("double loop time " , ti.timeit(lambda : rv1(table, counts, results)))
print ("nditer time " , ti.timeit(lambda : rv2(table, counts, results)))
print ("slice* time " , ti.timeit(lambda : rv3(table, counts, results)))
我明白了
double loop result [3. 1. 2. 1. 5.]
nditer result [3. 1. 2. 1. 5.]
slice* result [3. 1. 2. 1. 5.]
double loop time 42.41987561201677
nditer time 36.45269059110433
slice* time 24.102186055853963
所以 TomNashs 版本快了大约 30%。不幸的是,这仍然有点慢。
最佳答案
遇到同样的问题后,我找到了两种编写完全矢量化版本的方法。
一种解决方案涉及使用 ufunc.reduceat numpy.add 上的方法,但由于 reduceat
行为的奇怪规范,这最终变得相当困惑和低效。关于 numpy issue #834 有一些讨论关于添加一个新的 ufunc 方法,可以使该任务成为一个高效的单行任务,但尚未实现任何内容。
我提出的第二个解决方案似乎更高效,也更容易理解,工作原理如下:
首先,使用numpy.cumsum获取沿 counts
长轴的累积总和 cumulative_counts
。
接下来,获取要求和的范围的所有起始索引 starts
和结束索引 ends
,这可以通过对数组进行切片轻松获得在tables['ranges']
中。
现在,您可以通过使用 starts
和 ends
索引到 cumulative_counts 来获取每个范围的开始和结束处的累积总和的数组
.
最后,要获得每个范围内的总和,只需从最终总和中减去所有起始总和即可。
有一个小问题,那就是为了使索引正常工作,cumulative_counts
需要在其第一个索引处为零,然后才是cumsum
> 结果。
首先将这个概念放在一维中,因为它稍微清晰一点:
for i in range(len(counts)):
cumulative_counts = np.empty(len(counts[i]) + 1, dtype=counts.dtype)
cumulative_counts[0] = 0
cumulative_counts[1:] = np.cumsum(counts[i])
starts, ends = table['ranges'][:,i,:].T
results += cumulative_counts[ends] - cumulative_counts[starts]
这已经更快了 - 循环仅在短轴上(计数
的 2 行),其余部分被矢量化。
但也可以消除外循环并对 2D 输入应用相同的方法,为您的示例提供完全矢量化的解决方案:
cumulative_counts = np.empty((counts.shape[0], counts.shape[1] + 1), dtype=counts.dtype)
cumulative_counts[:,0] = 0
cumulative_counts[:,1:] = np.cumsum(counts, axis=1)
starts, ends = table['ranges'].T.swapaxes(1, 2)
rows = np.arange(len(counts)).reshape(1,-1)
row_results = cumulative_counts[rows, ends] - cumulative_counts[rows, starts]
results += row_results.sum(axis=1)
将此版本添加到您的计时比较中,它在我的系统上比 TomNash 的切片方法快 30%。我预计对于更大的阵列,加速会得到放大。
rv1 result [3. 1. 2. 1. 5.]
rv2 result [3. 1. 2. 1. 5.]
slice*(TN) result [3. 1. 2. 1. 5.]
cumsum(ML) result [3. 1. 2. 1. 5.]
double loop time 118.32055400998797
nditer time 101.83165721700061
slice* time 50.249228183995
cumsum time 38.694901300012134
关于python - 如何对数组中的范围值求和,其中每行都有不同的范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57694003/
我正在尝试在 OCaml 中创建一个函数,该函数在数学中执行求和函数。 我试过这个: sum n m f = if n = 0 then 0 else if n > m then f
我正在尝试找到一个可以帮助我解决问题的公式。 这个公式应该对每个靠近(总是在左边)具有相同名称的单元格的单元格求和(或工作)。如下所示: 将每个大写字母视为 “食谱”并且每个小写字母为 “成分” .在
让它成为以下 python pandas DataFrame,其中每一行代表一个人在酒店的住宿。 | entry_date | exit_date | days | other_columns
我有显示客户来电的数据。我有客户号码、电话号码(1 个客户可以有多个)、每个语音调用的日期记录以及调用持续时间的列。表看起来如下示例。 CusID | PhoneNum | Date
让它成为以下 python pandas DataFrame,其中每一行代表一个人在酒店的住宿。 | entry_date | exit_date | days | other_columns
我得到了两列数据; 答: 2013年12月31日 2013年12月30日 2013年12月29日 2013年12月28日 2013年12月27日 2012年12月26日 B: 10 10 10 10
我对 double 格式的精度有疑问。 示例: double K=0, L=0, M=0; scanf("%lf %lf %lf", &K, &L, &M); if((K+L) 我的测试输入: K
我有以下数组: int[,] myArray1 = new int[2, 3] { { 1, 2, 3 }, { 4, 6, 8 } }; int[,] myArray2 = new int[2, 3
我需要有关报告查询的帮助。我在该方案的底部有一个发票表,需要一种方法来获取总计费金额,同时在此数据库方案中的较高点进行条件过滤。我需要加入其他表,这会导致 SUM 函数返回不需要的结果。 这是我正在使
我有一个使用innodb作为存储引擎的MySQL数据库,并且我有许多采用基本形式的查询: SELECT bd.billing, SUM(CASE WHEN tc.transaction_class
尝试创建一个查询来给出总胜、平和负。我有以下查询 SELECT CASE WHEN m.home_team = '192' AND m.home_full_time_score
我正在尝试生成一份报告,显示排名靠前的推荐人以及他们推荐的人产生了多少收入。 这是我的表格的缩写版本: Users Table ------------------ id referral_user_
我有以下查询,并得到了预期的结果: SELECT IF (a1>b1,'1','0') AS a1r, IF (a2>b2,'1','0') AS a2r,
我尝试了几种不同的解决方案,但都没有成功。我给出的表格是一个示例,其设计和功能与我实际使用的表格类似: PK | Color | Count -------------------
我正在尝试构建一个查询来检查我的库存。 SELECT COUNT(*) AS item_count, reseller_id, sum(sold) as sold_count, sum(refunde
我试图解决一个看起来像下面编写的代码的问题,但由于缺乏知识和阅读 sqlalchemy 文档,我还没有真正找到解决问题的方法。 目标: 如果 year_column 中的年份相同,则获取 sales_
我有一个包含一周中多天的表格。一周中的每一天都有独特的属性,例如冰淇淋是否在这一天成功送达: ID DAY_WEEK ICE_CREAM 1 Monday
首先,我有一个名为store_00的表 id | ref | item | qty | cost | sell 1 22 x1 5 10 15 2 22
我正在编写一个程序,计算每个数字的总和,直到 1000。例如,1+2+3+4+5....+100。首先,我将求和作业分配给 10 个处理器:处理器 0 得到 1-100,处理器 1 得到 101-20
我想在一个循环中一次对多个属性求和: class Some(object): def __init__(self, acounter, bcounter): self.acou
我是一名优秀的程序员,十分优秀!