accumulate
语法
accumulate(func, X, [init],
[assembleRule|consistent=false])
[init] <operator>:A X
或 func:A([init],
X)
表示不指定 assembleRule,使用默认值
[init] <operator>:AC X
或 func:AC([init], X)
表示指定 assembleRule,此例中指定为 C(Consistent)
参数
- func:函数。
-
当 func 是一元函数时,X 可以是非负整数、一元函数或空值。init 表示 func 的参数,必须指定。
-
func 是二元函数时,X 是向量、矩阵或表。init 表示初始值。
-
func 是三元函数时,X 必须是一个 Tuple,包含2个元素,分别表示 func 的后两个参数。
-
- assembleRule 可选参数,表示如何将子任务的结果合并为函数最终结果。接受一个整数或字符串作为输入,可选值如下:
-
0 (或 "D"):默认值,表示 DolphinDB 规则,即根据所有子任务的结果来决定最终输出的数据类型和形式。当所有子结果具有相同的数据类型和形式时,多个标量合并为一个向量、多个向量合并为一个矩阵、多个矩阵合并为一个元组、多个字典合并为一张表;否则将所有子结果合并为一个元组输出。
-
1(或 "C"):表示 Consistent 规则,即认为所有子结果的数据类型和形式都与第一个子结果相同,根据第一个子结果来选择最终结果的数据类型和形式。如果后续子任务返回的结果与第一个子任务的结果类型不一致,系统会尝试对后续结果进行类型转换。如果转换失败则抛出异常。因此,此规则只可在已知子结果的数据类型及形式一致时指定。此规则可使系统免于逐一缓存并检查每个子任务的计算结果,从而提升性能。
-
2(或 "U"):表示 Tuple 规则,系统不再对各子结果的类型和形式一致性进行检查,而是直接将子结果组装成一个元组输出。
-
3(或 "K"):表示 kdb+ 规则。与 DolphinDB 规则类似,都会根据所有子结果来决定最终结果形式。主要区别在于,kdb+ 规则下,只要有任一子任务返回向量,则最终结果必为一个元组;而在 DolphinDB 规则下,子任务结果若均为长度相同的向量,则最终结果为一个矩阵。其他情况下,kdb+ 规则的输出与 DolphinDB 规则相同。
注:- 自 2.00.15/3.00.3 版本起,新增了 assembleRule 参数。该参数不仅实现了原 consistent 参数的功能,还提供了更多的结果合并选项。consistent 是一个布尔值,默认值为 false,相当于 assembleRule="D";若为 true,则相当于 assembleRule="C"。为保持兼容性,用户仍可使用 consistent 参数。如果同时指定 assemble 和 consistent,将以 consistent 的值为准。
- assembleRule 也可在高阶函数对应的函数模式符号后指定,通过字符 D/C/U/K 表示。以
eachPre (:P)
为例,形如sub:PU(X)
。不指定则使用默认值 D。
-
其他相关的 cum 系列函数的参数说明和窗口计算规则请参考: 累计窗口系列(cum 系列)
详情
-
当 func 是一元函数时,accumulate 先输出 init,再应用 func 在 init 上,然后迭代地应用 func 到前一个结果上,直至满足 X 指定地迭代条件后输出结果。
-
X 为整数时,表示 func 进行迭代的次数,输出结果包含 X + 1 个元素。注意,X 为负数时,将按0处理。
-
X 为一元函数时,表示终止条件,返回结果必须为一个布尔标量。若 X 应用在前一个结果上的返回值为 true,func 继续迭代;否则,func 停止迭代。
-
X 没有设置或为 NULL,func 将进行迭代计算直至输出的结果与前一个结果相同时停止迭代。
-
-
当 func 是二元函数时,
accumulate
先应用函数 / 运算符在 init 和 X[0] 上,再迭代地应用函数 / 运算符在前一个结果和当前元素上。当 init 缺失时,accumulate
返回值的第一个元素是 X[0]。accumulate
等同于下面伪代码的执行过程:result[0]=iif(init==NULL,X[0],<function>(init,X[0])); for(i:1~size(X)-1){ result[i]=<function>(result[i-1], X[i]); } return result;
-
当 func 是三元函数时,其迭代规则等同于二元函数。
与 reduce 返回最后一个结果不同,
accumulate
输出所有中间结果。
例子
当func 是一元函数时:
通过以下方式定义一个一元函数:
def func1(x){
if(x<5){
return x*3
}
else{
return x+3
}
}
当 X 为整数时,输出结果长度为 X + 1:
accumulate(func1, 5, 1)
返回:[1,3,9,12,15,18]。
当 X 为一元函数 condition 时,第3次迭代时因 condition 返回 false,停止迭代并输出前 2 次的迭代结果。
def condition(x){
return x<9
}
accumulate(func1, condition, 1)
返回:[1,3,9]。
当 X 为 NULL(或不指定)时,自定义函数 func2 作为迭代的函数。由于第 4 次迭代结果和第 3 次相同,停止迭代并输出前 3 次迭代结果。
def func2(x){
if(x<5){
return x*3
}
else{
return 6
}
}
accumulate(func2,NULL,1)
返回:[1,3,9,6]。
func 是二元函数时,在一个向量上执行 accumulate:
x = 1 2 3;
accumulate(add, 1 2 3);
返回:[1,3,6]。这样的运算等同于 [1, 1+2, 3+3]。
1 +:A x;
返回:[2,4,7]。这样的运算等同于 [1+1, 2+2, 4+3]。
accumulate(-, x, 2);
返回:[1,-1,-4]。这样的运算等同于 [2-1, 1-2, -1-3]。
accumulate(mul, x);
返回:[1,2,6]。这样的运算等同于 [1, 1*2, 2*3]。
通过以下方式计算累积因式分解:
def facts(a) {return 1*:A 1..a;};
facts 5;
返回:[1,2,6,24,120]
通过以下方式计算 log(1) 到 log(i) 之间的累加和。其中,第一行的结果用作第二行 accumulate
的第一个参数值:
def f1(a,b): a+log(b);
accumulate(f1, 1..5, 0);
返回:[0,0.693147,1.791759,3.178054,4.787492]。这等同于:0+log(1)=0,
0+log(2)=0.693147, 0.693147+log(3)=1.791759, ......
在下面这个例子中,由于忽略了初始条件,输入向量的第一个元素的数据类型决定了返回值的数据类型。
accumulate(f1, 1..5);
返回:[1,1.693147,2.791759,4.178053,5.787491]。
对一个矩阵执行 accumulate
:
x=1..12$3:4;
x;
得到:
col1 | col2 | col3 | col4 |
---|---|---|---|
1 | 4 | 7 | 10 |
2 | 5 | 8 | 11 |
3 | 6 | 9 | 12 |
+ :A x;
得到:
col1 | col2 | col3 | col4 |
---|---|---|---|
1 | 5 | 12 | 22 |
2 | 7 | 15 | 26 |
3 | 9 | 18 | 30 |
func 是三元函数时:
def fun3(x,y,z){
return x+y+z
}
accumulate(fun3,[[1,2,3],[10,10,10]],5)
返回:[16,28,41]。