全部文档
文档中心财务模型deepcubedeepcube语法loc计算按照度量值过滤计算范围

按照度量值过滤计算范围

在实际需求中,往往会遇到根据度量值进行条件判断,从而决定计算范围的场景。由于python语法层面的限制,deepcube SDK无法直接使用源生if else语法实现此类需求,但是用户可以使用when then otherwise语法来满足过滤计算范围的场景。

使用时,在when()中传入判断条件,如果条件判定为true则执行then()中的计算,否则执行otherwise()中的计算,或继续下一个when判断。

when(条件A).then(计算1).otherwise(计算2)

执行逻辑等同

if 条件A:

计算1

else:

Copy
计算2

when(条件A).then(计算1).when(条件B).then(计算2).otherwise(计算3)

执行逻辑等同

if 条件A:

计算1

elif 条件B:

计算2

else:

Copy
计算3

并且when, then,otherwise支持嵌套:

when(条件A).then(when(条件B).then(计算1).otherwise(计算2)).otherwise(计算3)

执行逻辑等同

if 条件A:

if 条件B:

计算1

else:

计算2

else:

Copy
计算3

在计算处理时,它表示的语义是对待计算的目标集做条件过滤,满足when条件的数据做then语句中的计算,并赋值到目标集。

但是与普通的条件过滤不同,when语句中的条件可以跨维度做判断,比如用科目A的度量值做判断,影响科目B的计算范围。跨维度时,与loc计算的原则一样,只能一对一或多对一,不能一对多或多对多。例如:

Copy
# 可以一对一
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(...)

如果判断条件是组合条件,可以将每个独立条件使用小括号()括起来,用&,|,~符号代进行逻辑连接。&,|,~分别对应与或非逻辑。

Copy
# 如果科目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。

对应代码如下:

Copy
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。

对应代码如下:

Copy
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

Copy
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()

回到顶部

咨询热线

400-821-9199

我们使用 ChatGPT,基于文档中心的内容以及对话上下文回答您的问题。

ctrl+Enter to send