跳转至

观测云工具包 / 数据格式化函数

「数据格式化函数」是用于将常见数据格式转换为与 DQL 返回值结构一致的方便函数,可用于非时序数据在观测云中的展示。

1. 快速开始

导入guance_toolkit__data_formatter,并使用其中的from_xxx函数进行数据转换。

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import json
import guance_toolkit__data_formatter as data_formatter

def run():
    # 原始数据
    data = [
        { 'subject': 'math', 'name': 'Tom',   'score': 100 },
        { 'subject': 'math', 'name': 'Jerry', 'score': 80  },
        { 'subject': 'math', 'name': 'Pluto', 'score': 90  },
    ]

    # 提取字段
    field_map = {
        '科目': 'subject',
        '姓名': 'name',
        '得分': 'score',
    }

    # 转换后数据
    dql_res = data_formatter.from_table(data, field_map, measurement='学生成绩')

    # 输出
    print(json.dumps(dql_res, indent=2, ensure_ascii=False))

输出如下:

为缩短文档,JSON 输出缩减了部分换行

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[2023-03-08 15:22:22.433] [+0ms] {
  "content": [
    {
      "group_by": [],
      "series": [
        {
          "name": "学生成绩",
          "columns": [ "time", "科目", "姓名", "得分" ],
          "tags": {},
          "values": [
            [ 0, "math", "Tom", 100 ],
            [ 0, "math", "Jerry", 80 ],
            [ 0, "math", "Pluto", 90 ]
          ]
        }
      ]
    }
  ]
}

2. from_table 函数

from_table函数用于将表格类数据转换为 DQL 的输出格式。

参数列表:

参数 类型 必须/默认值 说明
data list 必须 原始数据
每行数据可以是 Key-Value 键值对,也可以是数组
field_map dict 必须 输出字段配置
Key 为输出字段名
Value 为原始字段名、索引或函数
measurement str "Table Data" 输出系列的名称
group_by list 分组方式
分组后会产生多个数据系列
time_field str / function 时间字段

data / field_map 参数

data参数用于接收原始数据,支持字典数组和二维数组,需要提取的字段则通过field_map指定。

根据原始数据格式不同,field_map需要做相应调整。

原始数据为字典数组

略,见上文「快速开始」示例

原始数据为二维数组

示例代码如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import json
import guance_toolkit__data_formatter as data_formatter

def run():
    # 原始数据为二维数组
    data = [
        [ 'math', 'Tom',   100 ],
        [ 'math', 'Jerry', 80  ],
        [ 'math', 'Pluto', 90  ],
    ]

    # 提取字段使用索引
    field_map = {
        '科目': 0,
        '姓名': 1,
        '得分': 2,
    }

    # 转换后数据
    dql_res = data_formatter.from_table(data, field_map)

    # 输出
    print(json.dumps(dql_res, indent=2, ensure_ascii=False))

输出如下:

为缩短文档,JSON 输出缩减了部分换行

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[2023-03-08 15:36:08.787] [+0ms] {
  "content": [
    {
      "group_by": [],
      "series": [
        {
          "name": "Table Data",
          "columns": [ "time", "科目", "姓名", "得分" ],
          "tags": {},
          "values": [
            [ 0, "math", "Tom", 100 ],
            [ 0, "math", "Jerry", 80 ],
            [ 0, "math", "Pluto", 90 ]
          ]
        }
      ]
    }
  ]
}

原始数据转换

field_map参数除了直接指定原始数据字段名外,也可以传入函数,对原始数据进行转换后提取。

不仅如此,还可以生成原始数据中不存在的字段。

示例如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import json
import guance_toolkit__data_formatter as data_formatter

def run():
    # 原始数据
    data = [
        { 'subject': 'math', 'name': 'Tom',   'score': 100 },
        { 'subject': 'math', 'name': 'Jerry', 'score': 80  },
        { 'subject': 'math', 'name': 'Pluto', 'score': 90  },
    ]

    # 分档字段函数
    def get_level(row):
        if row['score'] >= 90:
            return '优秀'
        elif row['score'] >= 80:
            return '良好'
        elif row['score'] >= 60:
            return '及格'
        else:
            return '不及格'

    # 提取字段
    field_map = {
        '科目': 'subject',
        '姓名': 'name',
        '得分': 'score',

        # 生成新字段
        '分档': get_level,
        '班级': lambda row: '普通班' if row['score'] < 90 else '尖子班'
    }

    # 转换后数据
    dql_res = data_formatter.from_table(data, field_map)

    # 输出
    print(json.dumps(dql_res, indent=2, ensure_ascii=False))

输出如下:

为缩短文档,JSON 输出缩减了部分换行

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[2023-03-08 15:46:32.883] [+0ms] {
  "content": [
    {
      "group_by": [],
      "series": [
        {
          "name": "Table Data",
          "columns": [ "time", "科目", "姓名", "得分", "分档", "班级" ],
          "tags": {},
          "values": [
            [ 0, "math", "Tom", 100, "优秀", "尖子班" ],
            [ 0, "math", "Jerry", 80, "良好", "普通班" ],
            [ 0, "math", "Pluto", 90, "优秀", "尖子班" ]
          ]
        }
      ]
    }
  ]
}

group_by 参数

group_by参数用于指定输出数据的分组(即分成多个系列)

示例如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import json
import guance_toolkit__data_formatter as data_formatter

def run():
    # 原始数据
    data = [
        { 'subject': 'math', 'name': 'Tom',   'score': 100 },
        { 'subject': 'math', 'name': 'Tom',   'score': 90 },
        { 'subject': 'math', 'name': 'Jerry', 'score': 80  },
        { 'subject': 'math', 'name': 'Jerry', 'score': 70  },
        { 'subject': 'math', 'name': 'Pluto', 'score': 90  },
        { 'subject': 'math', 'name': 'Pluto', 'score': 80  },
    ]

    # 提取字段
    field_map = {
        '得分': 'score',
    }

    # 按照「科目 + 姓名」进行分组
    group_by = [ 'subject', 'name' ]

    # 转换后数据
    dql_res = data_formatter.from_table(data, field_map, group_by=group_by)

    # 输出
    print(json.dumps(dql_res, indent=2, ensure_ascii=False))

输出如下:

为缩短文档,JSON 输出缩减了部分换行

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[2023-03-08 15:52:35.887] [+0ms] {
  "content": [
    {
      "group_by": [ "subject", "name" ],
      "series": [
        {
          "name": "Table Data",
          "columns": [ "time", "得分" ],
          "tags": {
            "subject": "math",
            "name": "Tom"
          },
          "values": [
            [ 0, 100 ],
            [ 0, 90 ]
          ]
        },
        {
          "name": "Table Data",
          "columns": [ "time", "得分" ],
          "tags": {
            "subject": "math",
            "name": "Jerry"
          },
          "values": [
            [ 0, 80 ],
            [ 0, 70 ]
          ]
        },
        {
          "name": "Table Data",
          "columns": [ "time", "得分" ],
          "tags": {
            "subject": "math",
            "name": "Pluto"
          },
          "values": [
            [ 0, 90 ],
            [ 0, 80 ]
          ]
        }
      ]
    }
  ]
}

支持按原始数据字段 / 输出字段进行分组

group_by中的字段可以是原始数据中的字段,也可以是输出数据中的字段,也可以是两者混合。

示例如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import json
import guance_toolkit__data_formatter as data_formatter

def run():
    # 原始数据
    data = [
        { 'subject': 'math', 'name': 'Tom',   'score': 100 },
        { 'subject': 'math', 'name': 'Tom',   'score': 90 },
        { 'subject': 'math', 'name': 'Jerry', 'score': 80  },
        { 'subject': 'math', 'name': 'Jerry', 'score': 70  },
        { 'subject': 'math', 'name': 'Pluto', 'score': 90  },
        { 'subject': 'math', 'name': 'Pluto', 'score': 80  },
    ]

    # 提取字段
    field_map = {
        '得分': 'score',
        '班级': lambda row: '普通班' if row['score'] < 90 else '尖子班'
    }

    # 按照「科目 + 姓名」进行分组
    group_by = [ 'subject', '班级' ]

    # 转换后数据
    dql_res = data_formatter.from_table(data, field_map, group_by=group_by)

    # 输出
    print(json.dumps(dql_res, indent=2, ensure_ascii=False))

输出如下:

为缩短文档,JSON 输出缩减了部分换行

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[2023-03-08 15:56:54.696] [+0ms] {
  "content": [
    {
      "group_by": [ "subject", "班级" ],
      "series": [
        {
          "name": "Table Data",
          "columns": [ "time", "得分", "班级" ],
          "tags": {
            "subject": "math",
            "班级": "尖子班"
          },
          "values": [
            [ 0, 100, "尖子班" ],
            [ 0, 90, "尖子班" ],
            [ 0, 90, "尖子班" ]
          ]
        },
        {
          "name": "Table Data",
          "columns": [ "time", "得分", "班级" ],
          "tags": {
            "subject": "math",
            "班级": "普通班"
          },
          "values": [
            [ 0, 80, "普通班" ],
            [ 0, 70, "普通班" ],
            [ 0, 80, "普通班" ]
          ]
        }
      ]
    }
  ]
}

time_field 参数

time_field参数用于从原始数据中提取时序数据所需的时间信息。

示例如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import json
import guance_toolkit__data_formatter as data_formatter

def run():
    # 原始数据
    data = [
        { 'subject': 'math', 'name': 'Tom', 'score': 100, 'time': '2023-01-01T00:00:00Z' },
        { 'subject': 'math', 'name': 'Tom', 'score': 80 , 'time': '2023-01-02T00:00:00Z' },
        { 'subject': 'math', 'name': 'Tom', 'score': 90 , 'time': '2023-01-03T00:00:00Z' },
    ]

    # 提取字段
    field_map = {
        '科目': 'subject',
        '姓名': 'name',
        '得分': 'score',
    }

    # 时间字段
    time_field = 'time'

    # 转换后数据
    dql_res = data_formatter.from_table(data, field_map, time_field=time_field)

    # 输出
    print(json.dumps(dql_res, indent=2, ensure_ascii=False))

输出如下:

为缩短文档,JSON 输出缩减了部分换行

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[2023-03-08 16:01:10.809] [+0ms] {
  "content": [
    {
      "group_by": [],
      "series": [
        {
          "name": "Table Data",
          "columns": [ "time", "科目", "姓名", "得分" ],
          "tags": {},
          "values": [
            [ 1672531200000, "math", "Tom", 100 ],
            [ 1672617600000, "math", "Tom", 80 ],
            [ 1672704000000, "math", "Tom", 90 ]
          ]
        }
      ]
    }
  ]
}

支持的时间格式

time_field指定的字段,最终都会由 Python Arrow 库进行解析。因此支持所有Arrow库支持的数据格式,如:

数据格式 示例 说明
字符串 "2023-01-01T00:00:00Z"
"2023-01-01T00:00:00+08:00"
ISO 8601 格式
整数 / 浮点数 1672502400
1672502400.123
UNIX 时间戳,单位为秒
Arrow 对象 arrow.now() 支持转换函数中直接返回 arrow 对象

如果时间为不包含时区的字符串(如:2023-01-01 00:00:00),请务必进行对其进行转换处理(见下文)

时间数据转换

time_field参数也可以传入一个函数,对时间进行转换。

示例如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import json
import guance_toolkit__data_formatter as data_formatter

def run():
    # 原始数据
    data = [
        { 'subject': 'math', 'name': 'Tom', 'score': 100, 'date': '01-01' },
        { 'subject': 'math', 'name': 'Tom', 'score': 80 , 'date': '01-02' },
        { 'subject': 'math', 'name': 'Tom', 'score': 90 , 'date': '01-03' },
    ]

    # 提取字段
    field_map = {
        '科目': 'subject',
        '姓名': 'name',
        '得分': 'score',
    }

    # 时间字段
    def time_field(row):
        return f"2023-{row['date']}T00:00:00+08:00"

    # 转换后数据
    dql_res = data_formatter.from_table(data, field_map, time_field=time_field)

    # 输出
    print(json.dumps(dql_res, indent=2, ensure_ascii=False))

输出如下:

为缩短文档,JSON 输出缩减了部分换行

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[2023-03-08 16:04:58.331] [+0ms] {
  "content": [
    {
      "group_by": [],
      "series": [
        {
          "name": "Table Data",
          "columns": [ "time", "科目", "姓名", "得分" ],
          "tags": {},
          "values": [
            [ 1672502400000, "math", "Tom", 100 ],
            [ 1672588800000, "math", "Tom", 80 ],
            [ 1672675200000, "math", "Tom", 90 ]
          ]
        }
      ]
    }
  ]
}