Django/MySQL中的间隙检测

1 投票
3 回答
508 浏览
提问于 2025-04-16 11:49

我有一些时间序列数据存储在MySQL的InnoDB数据库里,我是通过Django的对象关系映射工具来访问这些数据的。

我想问的是:怎样才能最好地识别和找到这些时间序列数据中的空缺部分呢?

补充说明一下:虽然获取所有缺失数据点的列表比较简单,但这并不能完全解决我的问题。我只想知道空缺的开始和结束时间。连续时间段的开始和结束也可以。

再补充说明一下:下面是这个表的MySQL列。时间是标准的Django DateTimeField。相关数据每15分钟采样一次。

mysql> show columns from datalogging_datapoint;
+----------------------+------------+------+-----+---------+----------------+
| Field                | Type       | Null | Key | Default | Extra          |
+----------------------+------------+------+-----+---------+----------------+
| id                   | int(11)    | NO   | PRI | NULL    | auto_increment |
| new_since_parsing    | tinyint(1) | NO   |     | NULL    |                |
| non_public           | tinyint(1) | NO   |     | NULL    |                |
| time                 | datetime   | NO   |     | NULL    |                |
| value                | double     | NO   |     | NULL    |                |
| parent_timeseries_id | int(11)    | NO   | MUL | NULL    |                |
+----------------------+------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

3 个回答

0

可以看看Python的numpy和scipy这两个包,它们里面可能有一些时间序列分析的功能。接下来就是从数据库中提取数据,这个在Django和Python中是很常见的操作。

你想要的效果是这样的:

def gaps(seq):
  ...
  return gaps_found

也就是说,当输入[1,2,4,5,6,8,12]时,返回的结果是[3,7,9,10,11]?这个可以用集合来实现。

1

你需要提供一些示例数据,以及你希望如何处理这些数据。告诉我们你把数据存储在MySQL或者使用innodb并不是问题的关键(比如,ORM会处理这些事情)。我假设你能够把时间序列数据提取成一个整数列表,而你想要找出这个列表中缺口的开始和结束位置。

def gaps(seq):
    seq_set = set(seq) # e.g., set([0, 1, 2, 3, 7, 8, 9, 10, 16, 17, 18])
    full_set = set(range(seq[-1]+1)) # set([0,1,2,3,..., 17, 18])
    missing_pts = list(seq_set ^ full_set) # [4, 5, 6, 11, 12, 13, 14, 15]
    missing_pts.sort() # EDIT: originally didn't have this; 
                       # should have as sets are unordered.
    missing_pt_pairs = []
    first_pt = missing_pts[0]
    prev_pt = missing_pts[0]
    for pt in missing_pts:
        if pt - prev_pt > 1:
            missing_pt_pairs.append((first_pt, prev_pt))
            first_pt = pt
        prev_pt = pt
    missing_pt_pairs.append((first_pt, pt))
    return missing_pt_pairs

time_pts = [0,1,2,3,7,8,9,10,16,17,18]
gaps(time_pts) # returns [(4,6), (11,15)], 
# indicating that two gaps are present starting from [4,6] and [11,15]
0

谢谢大家的建议!我从你们那里学到了很多。

不过,我觉得我通过在脑海中重新整理问题,找到了一个理想的解决办法。基本的想法是这样的:

Count the values in a that year with Django's .count() .
If not complete:
    Count the values for each month in that year
    If not complete:
        Count the values for each day in that month

撰写回答