图表数据源¶
前言¶
对图表组件来说,在当前的数据分析场景中,有较多情况是目前基于财务模型、业务模型作为数据源是无法满足的:
当分析的数据需要基于模型中原始数据进行计算的情况下,如计算 A列+B列,该类计算能力从产品框架划分来看,应该是由计算层提供,但短期内可能无法上线以满足需求场景
当分析图表希望从多个数据模型中取数据时,如:展示A模型中的销售数据、B模型中的成本数据等,此类为多个数据模型作为数据源的需求
上述场景中,可能仅数据输入部分无法满足需求,在图表分析要素设置上完全可以使用标准组件能力来实现,如果能将Python的结果作为数据源输入到图表组件中,将极大的减少需要自定义开发的功能数量,提高项目实施效率。
简单示例¶
一个可以作为图表数据源的脚本,由如下部分组成
字段信息,即元数据信息
在
main
函数中返回符合元数据信息的 Pandas DataFrame
定义字段信息¶
例如需要定义如下数据的元数据信息:
describe |
date |
cost |
active |
clazz |
---|---|---|---|---|
for A |
2021-07-12 |
100.00 |
true |
class1 |
B |
2021-02-01 |
200.00 |
true |
class2 |
for C |
2021-06-29 |
500.00 |
false |
class3 |
for D |
2021-12-31 |
700.00 |
true |
class4 |
其中,active的数据来源为值列表active
clazz的数据来源为维度class
则可如下定义元数据结构
[1]:
from deepfos.lib.deepchart import *
class Data(Struct):
desc = Text(name='describe', description='描述')
date = Date(description='日期')
cost = Number(description='开销')
active = SmartList(element_name='active', path='/deepchart', value_field=['true', 'false'])
clazz = Dimension(element_name='class', path='/deepchart', description='级别')
在如上定义中,比较特殊的是对于值列表元素字段active
和维度元素字段class
的定义,由于来自元素,需要提供元素信息(元素名,如元素名不唯一,需提供path和folder_id二选一)
针对值列表,支持提供参数 value_field 用以指定生效的值成员信息。
在定义了如上元数据后,以此作为as_datasource
的 struct 参数装饰至main
函数
完整脚本(仅包含元数据信息)
以此脚本作为数据源后初始化的图表编辑界面如下
其中的active
值列表的成员信息也已按照元数据设置被限制在true, false间
组织数据¶
在main
函数中返回符合元数据信息的 Pandas DataFrame,此处的 Pandas DataFrame 可以以任何方式组织,只需保证在main
函数 return时,为 Pandas DataFrame 数据即可。
示例完整脚本
此时该脚本就是一个可以提供元信息,并可以在使用时提供实际数据的数据源了
使用效果¶
现有图表界面的筛选配置可经过 ChartEngine 被解析理解,达到对结果数据的筛选聚合处理效果。
例如图表编辑界面设置如下
POV的详细配置
类别轴的详细配置
图形属性的详细配置(只有describe字段有过滤规则)
图表从编辑界面切换至使用界面
可见,在使用时,筛去了describe不以’for ’开头且不在’A,B,C’中和active
不为true的记录的数据,与图表设置一致
从中进一步选择class1的数据后点击查询
得到的结果为POV和筛选条件的交集
元数据¶
元数据,即图表编辑时所需的字段信息,包括字段的名称、描述、类型及其他必要信息,在选取Python元素作为图表数据源时,需提供。
在deepfos.lib.deepchart
中,包装了作为图表数据源已支持的字段类型,只需将其进行初始化后作为 Struct 子类的类成员即可。
字段类型¶
Python类名 |
图表中的字段类型 |
备注 |
---|---|---|
Text |
文本 |
|
Date |
日期 |
* deepfos>=1.0.44 增加精度配置项 precision ,默认为年月日,在比较时会以该配置项的精度为准 |
Number |
数字 |
|
SmartList |
值列表 |
|
Dimension |
维度 |
|
Person |
用户 |
* 图表组件需在版本2.0.10.11及以上,deepfos版本在1.0.44及以上 |
类型参数¶
Python类名 |
name - 字段名 |
description - 字段描述 |
element_name - 元素名 |
folder_id - 元素folder_id |
path - 元素path |
value_field - 成员列表 |
precision - 精度 |
---|---|---|---|---|---|---|---|
Text |
Y |
Y |
|||||
Date |
Y |
Y |
Y |
||||
Number |
Y |
Y |
|||||
SmartList |
Y |
Y |
Y |
Y |
Y |
Y |
|
Dimension |
Y |
Y |
Y |
Y |
Y |
||
Person |
Y |
Y |
注:
在
name
未提供时,默认以字段在Struct子类中成员名为字段名在
description
未提供时,默认以name
为字段描述Date 类型的精度默认为年月日,可选项为
year
/month
/quarter
/day
,使用deepfos.lib.filterparser
的 TimeType 提供
class TimeType(IntEnum):
year = 1
quarter = 2
month = 3
day = 4
日期精度与格式对照¶
精度 |
日期格式 |
---|---|
年月日 |
YYYY-MM-DD |
年月 |
YYYY-MM |
年期间 |
YYYY-Qn |
年 |
YYYY |
数据处理¶
在定义了元数据后,将元数据结构赋值至as_datasource
的 struct 字段,并装饰main
函数
此时,main函数预期返回 Pandas DataFrame ,SDK将依据as_datasource
的 engine 和 before_return 参数和入参的业务参数将main
函数返回的 Pandas DataFrame 进行筛选聚合,最终变为图表组件可用于显示数据的格式。
参数说明¶
as_datasource
方法签名如下
def as_datasource(
func=None,
struct: Type[Struct] = None,
engine: Optional[Type[ChartEngine]] = ChartEngine,
before_return: Optional[Callable[[pd.DataFrame, Dict], pd.DataFrame]] = None,
date_round: bool = False
):
func: 即main函数,可为异步
struct: 元数据信息,即字段及其字段类型的类,不可为空
engine: 用于数据处理的引擎,默认为ChartEngine;如用户需自定义,应继承自ChartEngine;为None时,不对main函数的结果DataFrame作处理
before_return:用户自定义的同步方法,作为ChartEngine处理的后置逻辑,该方法应接受处理后的DataFrame和来自图表组件的原始参数为入参
date_round: 是否允许低精度日期值与筛选条件内高精度日期值进行比较,默认不允许。允许后则精度缺失* 时,除了相等以外,统一判定为不符合条件
注: 精度缺失:例如2012与2012-10,缺失了月份部分,而2011与2012-10本身在年份可比,不属于精度缺失
定制后置处理¶
在简单示例的基础上增加后置处理,例如在代码层面保证只出一条结果数据记录,则可编辑后置方法如下
[2]:
def limit_to_one(df, param):
return df.iloc[[0]]
完整脚本
图表查询结果(查询级别:class1, class2, class3)
可见即使符合条件的会有两条数据,经过了后置函数的处理后,也只有一条数据被返回
定制Engine¶
在简单示例的基础上使用自定义的引擎来进行数据处理,例如强制结果数据固定为空
[3]:
import pandas as pd
class CustomEngine(ChartEngine):
def _main(self, df: pd.DataFrame):
return pd.DataFrame()
在使用了 CustomEngine 后,使用界面将一直为无数据
完整脚本