在实际需求中,往往会遇到根据度量值进行条件判断,从而决定计算范围的场景。由于python语法层面的限制,deepcube SDK无法直接使用源生if else语法实现此类需求,但是用户可以使用when then otherwise语法来满足过滤计算范围的场景。
使用时,在when()中传入判断条件,如果条件判定为true则执行then()中的计算,否则执行otherwise()中的计算,或继续下一个when判断。
when(条件A).then(计算1).otherwise(计算2)
执行逻辑等同
if 条件A:
计算1
else:
计算2
when(条件A).then(计算1).when(条件B).then(计算2).otherwise(计算3)
执行逻辑等同
if 条件A:
计算1
elif 条件B:
计算2
else:
计算3
并且when, then,otherwise支持嵌套:
when(条件A).then(when(条件B).then(计算1).otherwise(计算2)).otherwise(计算3)
执行逻辑等同
if 条件A:
if 条件B:
计算1
else:
计算2
else:
计算3
在计算处理时,它表示的语义是对待计算的目标集做条件过滤,满足when条件的数据做then语句中的计算,并赋值到目标集。
但是与普通的条件过滤不同,when语句中的条件可以跨维度做判断,比如用科目A的度量值做判断,影响科目B的计算范围。跨维度时,与loc计算的原则一样,只能一对一或多对一,不能一对多或多对多。例如:
# 可以一对一
cube1.loc[entity['East'].Base(), account['B']] = when(
cube1.loc[account['A']].col('decimal_val')>100).then(...)
# 可以多对一
cube1.loc[entity['East'].Base(), account['B']] = when(
cube1.loc[entity['NoEntity']].col('decimal_val')>100).then(...)
# 可以跨多个维度
cube1.loc[entity['East'].Base(), account['B']] = when(
cube1.loc[entity['NoEntity'],account['A']].col('decimal_val')>100).then(...)
# 不能一对多,下例为错误示例
cube1.loc[entity['East'].Base(), account['B']] = when(
cube1.loc[account['A1','A2']].col('decimal_val')>100).then(...)
# 不能多对多,下例为错误示例
cube1.loc[entity['East'].Base(), account['B']] = when(
cube1.loc[entity['West'].Base()].col('decimal_val')>100).then(...)
如果判断条件是组合条件,可以将每个独立条件使用小括号()括起来,用&,|,~符号代进行逻辑连接。&,|,~分别对应与或非逻辑。
# 如果科目A大于100,并且小于200,则。。。
cube1.loc[entity['East'].Base(), account['B']] = when(
(cube1.loc[account['A']].col('decimal_val')>100) &
(cube1.loc[account['A']].col('decimal_val')<200)).then(...)
# 如果科目A大于100,或科目B大于100,则。。。
cube1.loc[entity['East'].Base(), account['C']] = when(
(cube1.loc[account['A']].col('decimal_val')>100) |
(cube1.loc[account['B']].col('decimal_val')>100)).then(...)
# 如果不是科目A大于100,则。。。
cube1.loc[entity['East'].Base(), account['C']] = when(
~(cube1.loc[account['A']].col('decimal_val')>100)).then(...)
实际案例:
例如我们有如下动态表,行上配置的是12家entity,列上配置的是account,其中flag科目是文本类型,科目A-E则是数值类型:
比如我们的需求是,
上述数据块中,每行数据如果flag中保存的是“规则1”,则计算科目A=B*C;
如果是“规则2”,则计算科目A=D*2;;
如果是“规则3”,则计算科目A=E。
对应代码如下:
from deepcube.cube.cube import deepcube
from deepcube import when
def main(p1, p2):
# 实例cube1对象
cube1 = deepcube('cube1')
year = cube1.year
period = cube1.period
scenario = cube1.scenario
version = cube1.version
account = cube1.account
category = cube1.category
entity = cube1.entity
cube1.init_data(
[year['2022'],
period['1'],
scenario['Actual'],
category['NoCategory'],
version['Working'],
entity['Total'].Base(),
account['A', 'B', 'C', 'D', 'E', 'flag']])
cube1.scope(year['2022'], period['1'], scenario['Actual'], category['NoCategory'], version['Working'])
# 如果flag中保存的是“规则1”,则计算科目A=B*C;如果是“规则2”,则计算科目A=D*2;如果是“规则3”,则计算科目A=E
cube1.loc[account['A']] = when(cube1.loc[account['flag']].col('string_val') == '规则1').then(
cube1.loc[account['B']] * cube1.loc[account['C']]).when(
cube1.loc[account['flag']].col('string_val') == '规则2').then(
cube1.loc[account['D']] * 2).when(
cube1.loc[account['flag']].col('string_val') == '规则3').then(
cube1.loc[account['E']])
# 将计算结果写入Cube
cube1.submit_calc()
并且判断条件中支持多组联合条件。多个条件之间如果是且的关系,则用&符号连接,如果是或的关系,用 | 符号连接,如果要对条件取反,用~符号。多个条件时每个独立条件需要用小括号()做分隔。
如果判断条件是in一个列表,可以用isin()函数。
比如我们的需求是,
如果flag是“规则1”并且C=2时,计算科目A=B*D;
如果flag是“规则1”并且C是3,4,5,6中的任一个时,计算科目A=B*E;
如果flag是“规则2”或“规则3”,则计算科目A=E。
对应代码如下:
from deepcube.cube.cube import deepcube
from deepcube import when
def main(p1, p2):
# 实例cube1对象
cube1 = deepcube('cube1')
year = cube1.year
period = cube1.period
scenario = cube1.scenario
version = cube1.version
account = cube1.account
category = cube1.category
entity = cube1.entity
cube1.init_data(
[year['2022'],
period['1'],
scenario['Actual'],
category['NoCategory'],
version['Working'],
entity['Total'].Base(),
account['A', 'B', 'C', 'D', 'E', 'flag']])
cube1.scope(year['2022'], period['1'], scenario['Actual'], category['NoCategory'], version['Working'])
# 如果flag是“规则1”并且C=2时,计算科目A=B*D,如果flag是“规则1”并且C=3时,计算科目A=B*E;如果flag是“规则2”,则计算科目A=E;如果flag既不是“规则1”也不是“规则2”,则计算科目A=0
cube1.loc[account['A']] = when((cube1.loc[account['flag']].col('string_val') == '规则1') & (
cube1.loc[account['C']].col('decimal_val') == 2)).then(
cube1.loc[account['B']] * cube1.loc[account['D']]).when(
(cube1.loc[account['flag']].col('string_val') == '规则1') & (
cube1.loc[account['C']].col('decimal_val').isin([3,4,5,6]))).then(
cube1.loc[account['B']] * cube1.loc[account['E']]).when(
(cube1.loc[account['flag']].col('string_val') == '规则2') |
cube1.loc[account['flag']].col('string_val') == '规则3').then(
cube1.loc[account['E']])
# 将计算结果写入Cube
cube1.submit_calc()
有些特殊场景,我们需求可能是如果一个维度成员有数据,则计算另一个成员。此类需求可以使用exists函数来判定。
比如我们的需求是,
如果B不为空,计算科目A=B+1
from deepcube.cube.cube import deepcube
from deepcube import when
def main(p1, p2):
# 实例cube1对象
cube1 = deepcube('cube1')
year = cube1.year
period = cube1.period
scenario = cube1.scenario
version = cube1.version
account = cube1.account
category = cube1.category
entity = cube1.entity
cube1.init_data(
[year['2022'],
period['1'],
scenario['Actual'],
category['NoCategory'],
version['Working'],
entity['Total'].Base(),
account['A', 'B', 'C', 'D', 'E', 'flag']])
cube1.scope(year['2022'], period['1'], scenario['Actual'], category['NoCategory'], version['Working'])
# 如果B不为空,计算科目A=B+1
cube1.loc[account['A']] = when(cube1.loc[account['B']].col('decimal_val').exists()).then(
cube1.loc[account['B']] + 1)
# 将计算结果写入Cube
cube1.submit_calc()
回到顶部
咨询热线