采样函数
等数量分桶降采样函数
本函数对输入序列进行等数量分桶采样,即根据用户给定的降采样比例和降采样方法将输入序列按固定点数等分为若干桶。在每个桶内通过给定的采样方法进行采样。
等数量分桶随机采样
函数简介
对等数量分桶后,桶内进行随机采样。
| 函数名 | 可接收的输入序列类型 | 必要的属性参数 | 输出序列类型 | 功能类型 |
|---|---|---|---|---|
| EQUAL_SIZE_BUCKET_RANDOM_SAMPLE | INT32 / INT64 / FLOAT / DOUBLE | 降采样比例 proportion,取值范围为(0, 1],默认为0.1 |
INT32 / INT64 / FLOAT / DOUBLE | 返回符合采样比例的等分桶随机采样 |
使用示例
输入序列:root.ln.wf01.wt01.temperature从0.0-99.0共100条数据。
1. IoTDB> select temperature from root.ln.wf01.wt01;
2. +-----------------------------+-----------------------------+
3. | Time|root.ln.wf01.wt01.temperature|
4. +-----------------------------+-----------------------------+
5. |1970-01-01T08:00:00.000+08:00| 0.0|
6. |1970-01-01T08:00:00.001+08:00| 1.0|
7. |1970-01-01T08:00:00.002+08:00| 2.0|
8. |1970-01-01T08:00:00.003+08:00| 3.0|
9. |1970-01-01T08:00:00.004+08:00| 4.0|
10. |1970-01-01T08:00:00.005+08:00| 5.0|
11. |1970-01-01T08:00:00.006+08:00| 6.0|
12. |1970-01-01T08:00:00.007+08:00| 7.0|
13. |1970-01-01T08:00:00.008+08:00| 8.0|
14. |1970-01-01T08:00:00.009+08:00| 9.0|
15. |1970-01-01T08:00:00.010+08:00| 10.0|
16. |1970-01-01T08:00:00.011+08:00| 11.0|
17. |1970-01-01T08:00:00.012+08:00| 12.0|
18. |.............................|.............................|
19. |1970-01-01T08:00:00.089+08:00| 89.0|
20. |1970-01-01T08:00:00.090+08:00| 90.0|
21. |1970-01-01T08:00:00.091+08:00| 91.0|
22. |1970-01-01T08:00:00.092+08:00| 92.0|
23. |1970-01-01T08:00:00.093+08:00| 93.0|
24. |1970-01-01T08:00:00.094+08:00| 94.0|
25. |1970-01-01T08:00:00.095+08:00| 95.0|
26. |1970-01-01T08:00:00.096+08:00| 96.0|
27. |1970-01-01T08:00:00.097+08:00| 97.0|
28. |1970-01-01T08:00:00.098+08:00| 98.0|
29. |1970-01-01T08:00:00.099+08:00| 99.0|
30. +-----------------------------+-----------------------------+
sql:
1. select equal_size_bucket_random_sample(temperature,'proportion'='0.1') as random_sample from root.ln.wf01.wt01;
结果:
1. +-----------------------------+-------------+
2. | Time|random_sample|
3. +-----------------------------+-------------+
4. |1970-01-01T08:00:00.007+08:00| 7.0|
5. |1970-01-01T08:00:00.014+08:00| 14.0|
6. |1970-01-01T08:00:00.020+08:00| 20.0|
7. |1970-01-01T08:00:00.035+08:00| 35.0|
8. |1970-01-01T08:00:00.047+08:00| 47.0|
9. |1970-01-01T08:00:00.059+08:00| 59.0|
10. |1970-01-01T08:00:00.063+08:00| 63.0|
11. |1970-01-01T08:00:00.079+08:00| 79.0|
12. |1970-01-01T08:00:00.086+08:00| 86.0|
13. |1970-01-01T08:00:00.096+08:00| 96.0|
14. +-----------------------------+-------------+
15. Total line number = 10
16. It costs 0.024s
等数量分桶聚合采样
函数简介
采用聚合采样法对输入序列进行采样,用户需要另外提供一个聚合函数参数即
type:聚合类型,取值为avg或max或min或sum或extreme或variance。在缺省情况下,采用avg。其中extreme表示等分桶中,绝对值最大的值。variance表示采样等分桶中的方差。
每个桶采样输出的时间戳为这个桶第一个点的时间戳
| 函数名 | 可接收的输入序列类型 | 必要的属性参数 | 输出序列类型 | 功能类型 |
|---|---|---|---|---|
| EQUAL_SIZE_BUCKET_AGG_SAMPLE | INT32 / INT64 / FLOAT / DOUBLE | proportion取值范围为(0, 1],默认为0.1 type:取值类型有avg, max, min, sum, extreme, variance, 默认为avg |
INT32 / INT64 / FLOAT / DOUBLE | 返回符合采样比例的等分桶聚合采样 |
使用示例
输入序列:root.ln.wf01.wt01.temperature从0.0-99.0共100条有序数据,同等分桶随机采样的测试数据。
sql:
1. select equal_size_bucket_agg_sample(temperature, 'type'='avg','proportion'='0.1') as agg_avg, equal_size_bucket_agg_sample(temperature, 'type'='max','proportion'='0.1') as agg_max, equal_size_bucket_agg_sample(temperature,'type'='min','proportion'='0.1') as agg_min, equal_size_bucket_agg_sample(temperature, 'type'='sum','proportion'='0.1') as agg_sum, equal_size_bucket_agg_sample(temperature, 'type'='extreme','proportion'='0.1') as agg_extreme, equal_size_bucket_agg_sample(temperature, 'type'='variance','proportion'='0.1') as agg_variance from root.ln.wf01.wt01;
结果:
1. +-----------------------------+-----------------+-------+-------+-------+-----------+------------+
2. | Time| agg_avg|agg_max|agg_min|agg_sum|agg_extreme|agg_variance|
3. +-----------------------------+-----------------+-------+-------+-------+-----------+------------+
4. |1970-01-01T08:00:00.000+08:00| 4.5| 9.0| 0.0| 45.0| 9.0| 8.25|
5. |1970-01-01T08:00:00.010+08:00| 14.5| 19.0| 10.0| 145.0| 19.0| 8.25|
6. |1970-01-01T08:00:00.020+08:00| 24.5| 29.0| 20.0| 245.0| 29.0| 8.25|
7. |1970-01-01T08:00:00.030+08:00| 34.5| 39.0| 30.0| 345.0| 39.0| 8.25|
8. |1970-01-01T08:00:00.040+08:00| 44.5| 49.0| 40.0| 445.0| 49.0| 8.25|
9. |1970-01-01T08:00:00.050+08:00| 54.5| 59.0| 50.0| 545.0| 59.0| 8.25|
10. |1970-01-01T08:00:00.060+08:00| 64.5| 69.0| 60.0| 645.0| 69.0| 8.25|
11. |1970-01-01T08:00:00.070+08:00|74.50000000000001| 79.0| 70.0| 745.0| 79.0| 8.25|
12. |1970-01-01T08:00:00.080+08:00| 84.5| 89.0| 80.0| 845.0| 89.0| 8.25|
13. |1970-01-01T08:00:00.090+08:00| 94.5| 99.0| 90.0| 945.0| 99.0| 8.25|
14. +-----------------------------+-----------------+-------+-------+-------+-----------+------------+
15. Total line number = 10
16. It costs 0.044s
等数量分桶 M4 采样
函数简介
采用M4采样法对输入序列进行采样。即对于每个桶采样首、尾、最小和最大值。
| 函数名 | 可接收的输入序列类型 | 必要的属性参数 | 输出序列类型 | 功能类型 |
|---|---|---|---|---|
| EQUAL_SIZE_BUCKET_M4_SAMPLE | INT32 / INT64 / FLOAT / DOUBLE | proportion取值范围为(0, 1],默认为0.1 |
INT32 / INT64 / FLOAT / DOUBLE | 返回符合采样比例的等分桶M4采样 |
使用示例
输入序列:root.ln.wf01.wt01.temperature从0.0-99.0共100条有序数据,同等分桶随机采样的测试数据。
sql:
1. select equal_size_bucket_m4_sample(temperature, 'proportion'='0.1') as M4_sample from root.ln.wf01.wt01;
结果:
1. +-----------------------------+---------+
2. | Time|M4_sample|
3. +-----------------------------+---------+
4. |1970-01-01T08:00:00.000+08:00| 0.0|
5. |1970-01-01T08:00:00.001+08:00| 1.0|
6. |1970-01-01T08:00:00.038+08:00| 38.0|
7. |1970-01-01T08:00:00.039+08:00| 39.0|
8. |1970-01-01T08:00:00.040+08:00| 40.0|
9. |1970-01-01T08:00:00.041+08:00| 41.0|
10. |1970-01-01T08:00:00.078+08:00| 78.0|
11. |1970-01-01T08:00:00.079+08:00| 79.0|
12. |1970-01-01T08:00:00.080+08:00| 80.0|
13. |1970-01-01T08:00:00.081+08:00| 81.0|
14. |1970-01-01T08:00:00.098+08:00| 98.0|
15. |1970-01-01T08:00:00.099+08:00| 99.0|
16. +-----------------------------+---------+
17. Total line number = 12
18. It costs 0.065s
等数量分桶离群值采样
函数简介
本函数对输入序列进行等数量分桶离群值采样,即根据用户给定的降采样比例和桶内采样个数将输入序列按固定点数等分为若干桶,在每个桶内通过给定的离群值采样方法进行采样。
| 函数名 | 可接收的输入序列类型 | 必要的属性参数 | 输出序列类型 | 功能类型 |
|---|---|---|---|---|
| EQUAL_SIZE_BUCKET_OUTLIER_SAMPLE | INT32 / INT64 / FLOAT / DOUBLE | proportion取值范围为(0, 1],默认为0.1 type取值为avg或stendis或cos或prenextdis,默认为avg number取值应大于0,默认3 |
INT32 / INT64 / FLOAT / DOUBLE | 返回符合采样比例和桶内采样个数的等分桶离群值采样 |
参数说明
proportion: 采样比例number: 每个桶内的采样个数,默认3type: 离群值采样方法,取值为avg: 取桶内数据点的平均值,并根据采样比例,找到距离均值最远的top number个stendis: 取桶内每一个数据点距离桶的首末数据点连成直线的垂直距离,并根据采样比例,找到距离最大的top number个cos: 设桶内一个数据点为b,b左边的数据点为a,b右边的数据点为c,则取ab与bc向量的夹角的余弦值,值越小,说明形成的角度越大,越可能是异常值。找到cos值最小的top number个prenextdis: 设桶内一个数据点为b,b左边的数据点为a,b右边的数据点为c,则取ab与bc的长度之和作为衡量标准,和越大越可能是异常值,找到最大的top number个
使用示例
测试数据:root.ln.wf01.wt01.temperature从0.0-99.0共100条数据,其中为了加入离群值,我们使得个位数为5的值自增100。
1. IoTDB> select temperature from root.ln.wf01.wt01;
2. +-----------------------------+-----------------------------+
3. | Time|root.ln.wf01.wt01.temperature|
4. +-----------------------------+-----------------------------+
5. |1970-01-01T08:00:00.000+08:00| 0.0|
6. |1970-01-01T08:00:00.001+08:00| 1.0|
7. |1970-01-01T08:00:00.002+08:00| 2.0|
8. |1970-01-01T08:00:00.003+08:00| 3.0|
9. |1970-01-01T08:00:00.004+08:00| 4.0|
10. |1970-01-01T08:00:00.005+08:00| 105.0|
11. |1970-01-01T08:00:00.006+08:00| 6.0|
12. |1970-01-01T08:00:00.007+08:00| 7.0|
13. |1970-01-01T08:00:00.008+08:00| 8.0|
14. |1970-01-01T08:00:00.009+08:00| 9.0|
15. |1970-01-01T08:00:00.010+08:00| 10.0|
16. |1970-01-01T08:00:00.011+08:00| 11.0|
17. |1970-01-01T08:00:00.012+08:00| 12.0|
18. |1970-01-01T08:00:00.013+08:00| 13.0|
19. |1970-01-01T08:00:00.014+08:00| 14.0|
20. |1970-01-01T08:00:00.015+08:00| 115.0|
21. |1970-01-01T08:00:00.016+08:00| 16.0|
22. |.............................|.............................|
23. |1970-01-01T08:00:00.092+08:00| 92.0|
24. |1970-01-01T08:00:00.093+08:00| 93.0|
25. |1970-01-01T08:00:00.094+08:00| 94.0|
26. |1970-01-01T08:00:00.095+08:00| 195.0|
27. |1970-01-01T08:00:00.096+08:00| 96.0|
28. |1970-01-01T08:00:00.097+08:00| 97.0|
29. |1970-01-01T08:00:00.098+08:00| 98.0|
30. |1970-01-01T08:00:00.099+08:00| 99.0|
31. +-----------------------------+-----------------------------+
sql:
1. select equal_size_bucket_outlier_sample(temperature, 'proportion'='0.1', 'type'='avg', 'number'='2') as outlier_avg_sample, equal_size_bucket_outlier_sample(temperature, 'proportion'='0.1', 'type'='stendis', 'number'='2') as outlier_stendis_sample, equal_size_bucket_outlier_sample(temperature, 'proportion'='0.1', 'type'='cos', 'number'='2') as outlier_cos_sample, equal_size_bucket_outlier_sample(temperature, 'proportion'='0.1', 'type'='prenextdis', 'number'='2') as outlier_prenextdis_sample from root.ln.wf01.wt01;
结果:
1. +-----------------------------+------------------+----------------------+------------------+-------------------------+
2. | Time|outlier_avg_sample|outlier_stendis_sample|outlier_cos_sample|outlier_prenextdis_sample|
3. +-----------------------------+------------------+----------------------+------------------+-------------------------+
4. |1970-01-01T08:00:00.005+08:00| 105.0| 105.0| 105.0| 105.0|
5. |1970-01-01T08:00:00.015+08:00| 115.0| 115.0| 115.0| 115.0|
6. |1970-01-01T08:00:00.025+08:00| 125.0| 125.0| 125.0| 125.0|
7. |1970-01-01T08:00:00.035+08:00| 135.0| 135.0| 135.0| 135.0|
8. |1970-01-01T08:00:00.045+08:00| 145.0| 145.0| 145.0| 145.0|
9. |1970-01-01T08:00:00.055+08:00| 155.0| 155.0| 155.0| 155.0|
10. |1970-01-01T08:00:00.065+08:00| 165.0| 165.0| 165.0| 165.0|
11. |1970-01-01T08:00:00.075+08:00| 175.0| 175.0| 175.0| 175.0|
12. |1970-01-01T08:00:00.085+08:00| 185.0| 185.0| 185.0| 185.0|
13. |1970-01-01T08:00:00.095+08:00| 195.0| 195.0| 195.0| 195.0|
14. +-----------------------------+------------------+----------------------+------------------+-------------------------+
15. Total line number = 10
16. It costs 0.041s
M4函数
函数简介
M4用于在窗口内采样第一个点(first)、最后一个点(last)、最小值点(bottom)、最大值点(top):
- 第一个点是拥有这个窗口内最小时间戳的点;
- 最后一个点是拥有这个窗口内最大时间戳的点;
- 最小值点是拥有这个窗口内最小值的点(如果有多个这样的点,M4只返回其中一个);
- 最大值点是拥有这个窗口内最大值的点(如果有多个这样的点,M4只返回其中一个)。

| 函数名 | 可接收的输入序列类型 | 属性参数 | 输出序列类型 | 功能类型 |
|---|---|---|---|---|
| M4 | INT32 / INT64 / FLOAT / DOUBLE | 包含固定点数的窗口和滑动时间窗口使用不同的属性参数。包含固定点数的窗口使用属性windowSize和slidingStep。滑动时间窗口使用属性timeInterval、slidingStep、displayWindowBegin和displayWindowEnd。更多细节见下文。 |
INT32 / INT64 / FLOAT / DOUBLE | 返回每个窗口内的第一个点(first)、最后一个点(last)、最小值点(bottom)、最大值点(top)。在一个窗口内的聚合点输出之前,M4会将它们按照时间戳递增排序并且去重。 |
属性参数
(1) 包含固定点数的窗口(SlidingSizeWindowAccessStrategy)使用的属性参数:
windowSize: 一个窗口内的点数。Int数据类型。必需的属性参数。slidingStep: 按照设定的点数来滑动窗口。Int数据类型。可选的属性参数;如果没有设置,默认取值和windowSize一样。

(2) 滑动时间窗口(SlidingTimeWindowAccessStrategy)使用的属性参数:
timeInterval: 一个窗口的时间长度。Long数据类型。必需的属性参数。slidingStep: 按照设定的时长来滑动窗口。Long数据类型。可选的属性参数;如果没有设置,默认取值和timeInterval一样。displayWindowBegin: 窗口滑动的起始时间戳位置(包含在内)。Long数据类型。可选的属性参数;如果没有设置,默认取值为Long.MIN_VALUE,意为使用输入的时间序列的第一个点的时间戳作为窗口滑动的起始时间戳位置。displayWindowEnd: 结束时间限制(不包含在内;本质上和WHERE time < displayWindowEnd起的效果是一样的)。Long数据类型。可选的属性参数;如果没有设置,默认取值为Long.MAX_VALUE,意为除了输入的时间序列自身数据读取完毕之外没有增加额外的结束时间过滤条件限制。

使用示例
输入的时间序列:
1. +-----------------------------+------------------+
2. | Time|root.vehicle.d1.s1|
3. +-----------------------------+------------------+
4. |1970-01-01T08:00:00.001+08:00| 5.0|
5. |1970-01-01T08:00:00.002+08:00| 15.0|
6. |1970-01-01T08:00:00.005+08:00| 10.0|
7. |1970-01-01T08:00:00.008+08:00| 8.0|
8. |1970-01-01T08:00:00.010+08:00| 30.0|
9. |1970-01-01T08:00:00.020+08:00| 20.0|
10. |1970-01-01T08:00:00.025+08:00| 8.0|
11. |1970-01-01T08:00:00.027+08:00| 20.0|
12. |1970-01-01T08:00:00.030+08:00| 40.0|
13. |1970-01-01T08:00:00.033+08:00| 9.0|
14. |1970-01-01T08:00:00.035+08:00| 10.0|
15. |1970-01-01T08:00:00.040+08:00| 20.0|
16. |1970-01-01T08:00:00.045+08:00| 30.0|
17. |1970-01-01T08:00:00.052+08:00| 8.0|
18. |1970-01-01T08:00:00.054+08:00| 18.0|
19. +-----------------------------+------------------+
查询语句1:
1. select M4(s1,'timeInterval'='25','displayWindowBegin'='0','displayWindowEnd'='100') from root.vehicle.d1
输出结果1:
1. +-----------------------------+-----------------------------------------------------------------------------------------------+
2. | Time|M4(root.vehicle.d1.s1, "timeInterval"="25", "displayWindowBegin"="0", "displayWindowEnd"="100")|
3. +-----------------------------+-----------------------------------------------------------------------------------------------+
4. |1970-01-01T08:00:00.001+08:00| 5.0|
5. |1970-01-01T08:00:00.010+08:00| 30.0|
6. |1970-01-01T08:00:00.020+08:00| 20.0|
7. |1970-01-01T08:00:00.025+08:00| 8.0|
8. |1970-01-01T08:00:00.030+08:00| 40.0|
9. |1970-01-01T08:00:00.045+08:00| 30.0|
10. |1970-01-01T08:00:00.052+08:00| 8.0|
11. |1970-01-01T08:00:00.054+08:00| 18.0|
12. +-----------------------------+-----------------------------------------------------------------------------------------------+
13. Total line number = 8
查询语句2:
1. select M4(s1,'windowSize'='10') from root.vehicle.d1
输出结果2:
1. +-----------------------------+-----------------------------------------+
2. | Time|M4(root.vehicle.d1.s1, "windowSize"="10")|
3. +-----------------------------+-----------------------------------------+
4. |1970-01-01T08:00:00.001+08:00| 5.0|
5. |1970-01-01T08:00:00.030+08:00| 40.0|
6. |1970-01-01T08:00:00.033+08:00| 9.0|
7. |1970-01-01T08:00:00.035+08:00| 10.0|
8. |1970-01-01T08:00:00.045+08:00| 30.0|
9. |1970-01-01T08:00:00.052+08:00| 8.0|
10. |1970-01-01T08:00:00.054+08:00| 18.0|
11. +-----------------------------+-----------------------------------------+
12. Total line number = 7
推荐的使用场景
(1) 使用场景:保留极端点的降采样
由于M4为每个窗口聚合其第一个点(first)、最后一个点(last)、最小值点(bottom)、最大值点(top),因此M4通常保留了极值点,因此比其他下采样方法(如分段聚合近似 (PAA))能更好地保留模式。如果你想对时间序列进行下采样并且希望保留极值点,你可以试试 M4。
(2) 使用场景:基于数据缩约的大规模时间序列的零误差双色折线图可视化
参考论文: “M4: A Visualization-Oriented Time Series Data Aggregation”
open in new window.
假设屏幕画布的像素宽乘高是w*h,假设时间序列root.vehicle.d1.s1要可视化的时间范围是[tqs,tqe)(在这个使用场景里面,需要请你自行将tqe自适应调整使得(tqe-tqs)是w的整数倍),那么落在第i个时间跨度Ii=[tqs+(tqe-tqs)/w*(i-1),tqs+(tqe-tqs)/w*i) 内的点将会被画在第i个像素列中,i=1,2,…,w。
于是从可视化驱动的角度出发,使用查询语句:"select M4(s1,'timeInterval'='(tqe-tqs)/w','displayWindowBegin'='tqs','displayWindowEnd'='tqe') from root.vehicle.d1",来采集每个时间跨度内的第一个点(first)、最后一个点(last)、最小值点(bottom)、最大值点(top)。最终结果点数不会超过4*w个,使用这些聚合点画出来的折线图与使用原始数据画出来的图在像素级别上是完全一致的。
和其它SQL的功能比较
| SQL | 是否支持M4聚合 | 滑动窗口类型 | 示例 | 相关文档 |
|---|---|---|---|---|
| 1. 带有Group By子句的内置聚合函数 | 不支持,缺少BOTTOM_TIME和TOP_TIME,即缺少最小值点和最大值点的时间戳。 |
Time Window | select count(status), max_value(temperature) from root.ln.wf01.wt01 group by ([2017-11-01 00:00:00, 2017-11-07 23:00:00), 3h, 1d) |
https://iotdb.apache.org/UserGuide/Master/Query-Data/Aggregate-Query.html#built-in-aggregate-functions采样函数 - 图7open in new window https://iotdb.apache.org/UserGuide/Master/Query-Data/Aggregate-Query.html#downsampling-aggregate-query采样函数 - 图8open in new window |
| 2. EQUAL_SIZE_BUCKET_M4_SAMPLE (内置UDF) | 支持 | Size Window. windowSize = 4(int)(1/proportion) |
select equal_size_bucket_m4_sample(temperature, ‘proportion’=’0.1’) as M4_sample from root.ln.wf01.wt01 |
https://iotdb.apache.org/UserGuide/Master/Query-Data/Select-Expression.html#time-series-generating-functions采样函数 - 图9open in new window |
| 3. M4 (内置UDF) | 支持* | Size Window, Time Window | (1) Size Window: select M4(s1,’windowSize’=’10’) from root.vehicle.d1 (2) Time Window: select M4(s1,’timeInterval’=’25’,’displayWindowBegin’=’0’,’displayWindowEnd’=’100’) from root.vehicle.d1 |
本文档 |
| 4. 扩展带有Group By子句的内置聚合函数来支持M4聚合 | 未实施 | 未实施 | 未实施 | 未实施 |
进一步比较EQUAL_SIZE_BUCKET_M4_SAMPLE和M4:
(1) 不同的M4聚合函数定义:
在每个窗口内,EQUAL_SIZE_BUCKET_M4_SAMPLE从排除了第一个点和最后一个点之后剩余的点中提取最小值点和最大值点。
而M4则是从窗口内所有点中(包括第一个点和最后一个点)提取最小值点和最大值点,这个定义与元数据中保存的max_value和min_value的语义更加一致。
值得注意的是,在一个窗口内的聚合点输出之前,EQUAL_SIZE_BUCKET_M4_SAMPLE和M4都会将它们按照时间戳递增排序并且去重。
(2) 不同的滑动窗口:
EQUAL_SIZE_BUCKET_M4_SAMPLE使用SlidingSizeWindowAccessStrategy,并且通过采样比例(proportion)来间接控制窗口点数(windowSize),转换公式是windowSize = 4*(int)(1/proportion)。
M4支持两种滑动窗口:SlidingSizeWindowAccessStrategy和SlidingTimeWindowAccessStrategy,并且M4通过相应的参数直接控制窗口的点数或者时长。
