【问题标题】:Checking timestamp intervals in matlab在matlab中检查时间戳间隔
【发布时间】:2014-10-18 04:40:52
【问题描述】:

我只是想知道是否有一种方法可以比较许多时间戳以查看是否缺少任何时间戳。 目前,我正在查看一年中的 365 天,每天读取 48 个读数。 (在 excel 文档中)因此我有超过 17000 点要分析。 目前时间戳的格式为:

1/01/2011 12:30 AM
1/01/2011 1:00 AM
1/01/2011 1:30 AM
1/01/2011 2:00 AM
1/01/2011 2:30 AM

我需要每 30 分钟检查一次是否缺少任何值。我曾想过使用

datenum('')

然后尝试比较它,当它不跟随趋势时抛出错误并返回之前的值。但我不确定。

任何帮助将不胜感激!

【问题讨论】:

    标签: matlab timestamp


    【解决方案1】:

    您可以使用datenum 并输入您提供的示例中的确切日期格式字符串之一。如果您有半小时的时间间隔,那么连续的datenum 调用之间的差异应该产生相同的差异。例如,让我们将日期放入一个单元格数组中,如下所示:

    C = {'1/01/2011 12:30 AM',
    '1/01/2011 1:00 AM',
    '1/01/2011 1:30 AM',
    '1/01/2011 2:00 AM',
    '1/01/2011 2:30 AM'};
    

    我们可以使用diff 来计算连续元素之间的差异。 diff 是如何工作的,给定数组中的第 ith 个元素,在给定输入值 x_i 的情况下,y_i 处的向量的输出是:

    y_i = x_{i+1} - x_i
    

    因此,这将返回一个长度比原始向量小一的向量。我们基本上是在考虑从你们日期的第二个元素开始的元素。因此,将diff 应用于此元胞数组中的每个元素datenum,我们得到:

    format long
    diffs = diff(datenum(C))
    
    diffs =
    
       0.020833333255723
       0.020833333372138
       0.020833333372138
       0.020833333255723
    

    前 7 个有效数字左右很重要。其余的数字是由于一些精度差异造成的,但我们暂时搁置它。因此,您需要检查差异中的每个元素是否大约为0.0208333。如果不是,那么你错过了一个间隔。让我们试着捏造几次:

    C = {'1/01/2011 12:30 AM',
    '1/01/2011 1:30 AM',
    '1/01/2011 2:30 AM',
    '1/01/2011 3:00 AM',
    '1/01/2011 4:30 AM'};
    
    format long
    diffs = diff(datenum(C))
    
    diffs =
    
       0.041666666627862
       0.041666666627862
       0.020833333372138
       0.062500000000000
    

    因此,对于C 的第二个、第三个和最后一个元素,我们缺少半小时间隔的测量值。具体来说,我假设您的单位是半小时。因此,缺失测量值之间的最小可能跳跃是一个小时,这是0.02080.0416 之间的跳跃,所以这大约是0.02 的差异。因此,我们需要在这个数组中找到大于0.0416 的位置。为了安全起见,我们将其设置为0.03。因此,如果您想以编程方式执行此操作,您可以这样做:

    diffs = diff(datenum(C));
    locs = find(diffs > 0.03) + 1;
    

    find 找出满足特定布尔条件的矩阵/数组中的位置。在这种情况下,我们希望找到差异为> 0.03 的位置。我们还抵消了1,因为我们正在查看我们之前讨论过的第二个元素。通过使用我们修改后的C 数组,我们得到:

    locs =
    
         2
         3
         5
    

    这告诉我们,在我们修改后的日期数组 (C) 的位置 2、3 和 5 处,我们缺少半小时标记处的测量值。

    为了仔细检查我们的第一个示例,如果我们在没有跳过的情况下将其应用于第一个示例,我们会按预期得到空数组:

    locs = 
    
    []
    

    作为一个小奖励,我们可以显示在哪些位置缺少间隔。具体来说:

    missingTimes = C(locs)
    

    对于我们捏造的时间示例,我们得到:

    missingTimes = 
    
        '1/01/2011 1:30 AM'
        '1/01/2011 2:30 AM'
        '1/01/2011 4:30 AM'
    

    编辑

    从我们在 cmets 回来的谈话中,只要你有一个没有时间和只有日期的约会,这就搞砸了。具体来说,当您调用 datenum 并在单元格数组中至少包含其中一个时,我们将不再获得浮点精度。我们只会得到整数(出于某种奇怪的原因......我不知道为什么。我可能应该为此发表一篇 StackOverflow 帖子)。换句话说,如果我们这样做了:

    C = {'1/01/2011',
    '1/01/2011 12:30 AM',
    '1/01/2011 1:30 AM',
    '1/01/2011 2:30 AM',
    '1/01/2011 3:00 AM',
    '1/01/2011 4:30 AM'};
    

    如果我们这样做了:

    diff(datenum(C))
    

    我们得到:

    ans =
    
      0
      0
      0
      0
      0
    

    为了解决这个问题,我必须实现我自己的diff 版本,并单独访问日期数组中的元素。因此,改为这样做:

    format long;
    diffs = arrayfun(@(x) datenum(C{x}) - datenum(C{x-1}), (2:numel(C)).');
    

    我使用了arrayfun,并指定了一个输入数组,该数组的元素数从 2 到 C 中的元素数。对于我们输出中的每个元素,我们采用i+1th 元素的datenum 表示并从我们的ith 元素中减去它。这实质上是手动实现diff 操作,并在您包含一个没有时间的日期时避开这个小错误。老实说,我不知道为什么整数后的所有小数点都被删除了....但这暂时有效。

    无论如何,我们得到:

    diffs =
    
       0.020833333372138
       0.041666666627862
       0.041666666627862
       0.020833333372138
       0.062500000000000
    

    编辑#2

    看来你还是遇到了麻烦。我会提出的另一个建议是找到那些缺少12:00 AM 时间戳的时间。然后我们会找到这些条目并手动放置12:00 AM 时间戳。因此,我们可以通过regexp 使用正则表达式来做到这一点。正则表达式尝试查找模式在字符串中出现的位置。因此,我们要做的是找到那些在末尾包含时间戳的模式,然后使用一些额外的代码插入这个时间戳。让我们考虑一个玩具示例:

    C = {'1/01/2011',
    '1/01/2011 12:30 AM',
    '1/01/2011 1:30 AM',
    '1/01/2011 2:30 AM',
    '1/01/2011 3:00 AM',
    '1/01/2011 4:30 AM',
    '1/02/2011',
    '1/02/2011 12:30 AM',
    '1/02/2011 1:30 AM',
    '1/02/2011 2:30 AM',
    '1/02/2011 3:00 AM',
    '1/02/2011 4:30 AM',
    '1/03/2011',
    '1/03/2011 12:30 AM',
    '1/03/2011 1:30 AM',
    '1/03/2011 2:30 AM',
    '1/03/2011 3:00 AM',
    '1/03/2011 4:30 AM'};
    

    这里有不同的日期和时间,有些缺少12:00 AM 时间戳。因此,这就是我将如何插入时间戳:

    missingTimeStampsLocs = cellfun(@(x) isempty(regexp(x,'[0-9]{1,2}\/[0-9]{2}\/[0-9]{4} [0-9]{1,2}:[0-9]{2} [AaPp][Mm]')), C);
    missingTimeStamps = C(missingTimeStampsLocs);
    filledInTimeStamps = cellfun(@(x) [x ' 12:00 AM'], missingTimeStamps, 'uni', 0);
    C(missingTimeStampsLocs) = filledInTimeStamps;
    

    这看起来像是一段令人生畏的代码,但肯定可以解释。让我们从第一行代码开始。首先,我们调用regexp,它接收一个我们想要查看的字符串,然后第二个参数用于描述您正在寻找的pattern。我必须在这里做的是我要查找以下格式的所有日期:

     #/##/#### ##:## xx
           OR
    ##/##/#### ##:## xx
    

    # 表示数字,x 表示字符。我们将搜索所有遵循这种exact格式的日期。我们将标记任何不遵循这种格式的日期,这意味着它们缺少时间戳。看看这句话:

    regexp(x,'[0-9]{1,2}\/[0-9]{2}\/[0-9]{4} [0-9]{1,2}:[0-9]{2} [AaPp][Mm]')
    

    这就是说,对于一个字符串x,我们将寻找一个以1或2个数字开头的字符串,然后是/,然后正好是2个数字,然后是@987654382 @,后跟正好 4 个数字,后跟一个空格,然后我们将查找 1 个或 2 个数字,然后是 :,然后正好是 2 个数字,后跟一个空格,然后是 AMPM并且不区分大小写。这意味着AMPM 可以是大写或小写。

    regexp 将返回的是您的字符串中找到此字符串的位置。在我们的例子中,它要么返回1,表示我们在它的开始处找到了这个字符串,要么返回empty,表示我们没有找到这样的字符串.如果regexp 返回空,则此日期缺少时间戳。这就是为什么我用isempty 包装这个调用来检查regexp 是否返回空。然后我使用cellfun 包装这个调用,以便我们可以迭代我们的日期单元格数组中的所有元素。输出(存储在missingTimeStampsLocs)将包含一个布尔数组,其中1 表示缺少时间戳,0 表示没有丢失。

    下一行代码然后从原始元胞数组中提取那些缺少日期的日期。然后我再运行一次cellfun 来遍历这些单元格,然后我们将12:00 AM 时间戳连接到这个提取的单元格数组中每个字符串的末尾。请注意,我还指定了两个附加参数('uni'0),因为输出不再是单个值,而是一个字符串。这些字符串将被放置在一个元胞数组中,这是完美的,因为它们无论如何都是从一个元胞数组中提取的。我们不必在第一个 cellfun 调用中指定它,因为输出是单个值 - 在这种情况下,它是 01 的布尔值。完成后,我们将那些缺少时间戳的日期替换为我们刚刚用12:00 AM 时间戳填写的日期。这将被覆盖到C。因此,通过使用我们的C 运行上述代码,我们得到了:

    C =  
    
    '1/01/2011 12:00 AM'
    '1/01/2011 12:30 AM'
    '1/01/2011 1:30 AM'
    '1/01/2011 2:30 AM'
    '1/01/2011 3:00 AM'
    '1/01/2011 4:30 AM'
    '1/02/2011 12:00 AM'
    '1/02/2011 12:30 AM'
    '1/02/2011 1:30 AM'
    '1/02/2011 2:30 AM'
    '1/02/2011 3:00 AM'
    '1/02/2011 4:30 AM'
    '1/03/2011 12:00 AM'
    '1/03/2011 12:30 AM'
    '1/03/2011 1:30 AM'
    '1/03/2011 2:30 AM'
    '1/03/2011 3:00 AM'
    '1/03/2011 4:30 AM'
    

    然后我们可以通过我们的检测代码运行它,看看哪些日期跳跃了半小时。

    diffs = diff(datenum(C));
    locs = find(diffs > 0.03) + 1;
    missingTimes = C(locs)
    

    因此我们得到:

    missingTimes = 
    
    '1/01/2011 1:30 AM'
    '1/01/2011 2:30 AM'
    '1/01/2011 4:30 AM'
    '1/02/2011 12:00 AM'
    '1/02/2011 1:30 AM'
    '1/02/2011 2:30 AM'
    '1/02/2011 4:30 AM'
    '1/03/2011 12:00 AM'
    '1/03/2011 1:30 AM'
    '1/03/2011 2:30 AM'
    '1/03/2011 4:30 AM'
    

    我真的希望这是我最后一次解决这个问题 (LOL),因为我很确定我已经涵盖了所有意外情况。我还假设您的日期以特定方式格式化,我希望这能解决您的问题。我们也不需要使用我们编写的自定义 diff 函数,因为我现在正在完成您的日期以在其上添加 12:00 AM 时间戳。

    祝你好运!

    【讨论】:

    • sldn't the missingTime 是 '1/01/2011 1:00 AM', '1/01/2011 2:00 AM','1/01/2011 3:30 AM', “2011 年 1 月 1 日凌晨 4:00”?
    • @lakesh - 不。我只在C 数组中显示了where,发现缺少时间。这本身并没有找到实际的丢失时间。这将取决于 OP 来解决:)
    • 非常感谢您的精彩回复!似乎已经解决了我的大部分问题,我还有一个快速的问题。如果我的数据从 2011 年 1 月 1 日开始,然后照常继续... 1/01/2011 12:30 AM 1/01/2011 1:00 AM 1/01/2011 1:30 AM 差异value 似乎对所有这些都返回 0。
    • @user3575908 - 你确定?我刚刚做了datenum('1/01/2011 12:30 AM') - datenum('1/01/2011'),我得到了0.0208,正如预期的那样。如果省略时间,则假定为午夜。你能告诉我你的数据在开始时的样子吗?
    • 我也试过了,得到的答案和你一样。我的实际数据从“空白”午夜开始,例如: 日期/时间 1/01/2011 1/01/2011 12:30 AM 1/01/2011 1:00 AM 1/01/2011 1:30 AM 1 /01/2011 2:00 AM 1/01/2011 2:30 AM 1/01/2011 3:00 AM 然后继续。
    猜你喜欢
    • 2012-03-27
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 2022-12-02
    • 1970-01-01
    • 2014-07-12
    • 2015-02-09
    • 1970-01-01
    相关资源
    最近更新 更多