我只是想知道是否有办法比较许多时间戳,看看是否有任何遗失。 目前我正在观看一年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('')
然后尝试比较它,并在不遵循趋势时抛出错误并返回先前的值。但我不确定。
任何帮助将不胜感激!
答案 0 :(得分:4)
您可以使用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
如何工作,给定数组中的i th 元素,给定输入值y_i
的{{1}}处的向量输出为:
x_i
因此,这将返回一个长度比原始长度小1的向量。我们基本上从你日期的第二个元素开始考虑元素。因此,对此单元格数组中的每个元素应用y_i = x_{i+1} - x_i
到diff
,我们得到:
datenum
前7位有效数字左右重要。其余的数字是由于一些精确的差异,但我们现在搁置它。因此,您需要检查差异中的每个元素是否都是format long
diffs = diff(datenum(C))
diffs =
0.020833333255723
0.020833333372138
0.020833333372138
0.020833333255723
。如果不是,那么你错过了一个间隔。让我们尝试捏几下:
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.0208
之间的跳跃,因此关于0.0416
的差异。因此,我们需要在此数组中找到大于0.02
的位置。为安全起见,我们将其设置为0.0416
。因此,如果您想以编程方式执行此操作,则可以执行此操作:
0.03
find
计算满足特定布尔条件的矩阵/数组中的位置。在这种情况下,我们希望找到差异为diffs = diff(datenum(C));
locs = find(diffs > 0.03) + 1;
的位置。我们也偏移> 0.03
,因为我们正在研究像之前谈到的第二个元素。通过修改后的1
数组执行此操作,我们得到:
C
这告诉我们在修改日期数组(locs =
2
3
5
)的位置2,3和5处,我们在半小时标记处缺少测量结果。
要仔细检查我们的第一个例子,如果我们在没有跳过的第一个例子中应用了这个,我们按预期得到空数组:
C
作为一点奖励,我们可以显示缺少间隔的位置。具体做法是:
locs =
[]
对于我们的捏造时间示例,我们得到:
missingTimes = C(locs)
在评论中我们的谈话中,一旦你有一个没有时间和日期的约会,这就会搞砸。具体来说,当您在单元格数组中至少调用其中一个missingTimes =
'1/01/2011 1:30 AM'
'1/01/2011 2:30 AM'
'1/01/2011 4:30 AM'
时,我们将不再获得浮点精度。我们只会得到整数(出于某种奇怪的原因......我无法弄清楚原因。我应该在这篇文章中写一篇StackOverflow文章)。换句话说,如果我们这样做:
datenum
如果我们这样做了:
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
我使用arrayfun
并指定了一个输入数组,该数组从2到format long;
diffs = arrayfun(@(x) datenum(C{x}) - datenum(C{x-1}), (2:numel(C)).');
中的元素数量。对于输出中的每个元素,我们采用C
元素的datenum
表示,并从i+1
元素中减去它。这基本上是手动实现i
操作,当你包含一个没有时间的日期时,它会逃避轻微的错误。老实说,我不知道为什么整个数字之后的所有小数点都被删除了....但是现在这个有效。
无论如何,我们得到:
diff
看起来你仍然遇到麻烦。我要做的另一个建议是找到那些缺少 diffs =
0.020833333372138
0.041666666627862
0.041666666627862
0.020833333372138
0.062500000000000
时间戳的时间。然后我们会找到这些条目并手动放置12:00 AM
时间戳。因此,我们可以使用正则表达式通过regexp
来执行此操作。正则表达式尝试查找字符串中出现模式的位置。因此,我们要做的就是找到那些不最终包含时间戳的模式,然后使用一些额外的代码来插入此时间戳。让&# 39;考虑一个玩具的例子:
12:00 AM
这里我们有各种日期和时间,有些人遗漏了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
#/##/#### ##:## xx
OR
##/##/#### ##:## xx
表示一个数字,#
表示一个字符。我们将搜索遵循此完全格式的所有日期。任何不遵循此格式的日期我们都会标记,这意味着它们缺少时间戳。看一下这句话:
x
这就是说,对于字符串regexp(x,'[0-9]{1,2}\/[0-9]{2}\/[0-9]{4} [0-9]{1,2}:[0-9]{2} [AaPp][Mm]')
,我们将查找以1或2个数字开头的字符串,后跟x
,后跟正好2个数字,然后是通过/
,后跟4个数字,后跟一个空格,然后我们将查找1或2个数字,然后是/
,然后是2个数字,后跟一个空格,然后:
或AM
,不区分大小写。这意味着PM
或AM
可以是大写或小写。
从PM
返回的内容是字符串中找到此字符串的位置。在我们的情况下,它会返回regexp
,意味着我们在开始处找到了这个字符串,或者为空,这意味着我们还没有找到这样的字符串一个字符串。如果1
返回空,则此日期缺少时间戳。这就是我用isempty
打包此调用以检查regexp
是否返回空的原因。然后我使用cellfun
包装此调用,以便我们可以遍历日期单元格数组中的所有元素。输出(存储在regexp
中)将包含一个布尔数组,其中missingTimeStampsLocs
表示缺少时间戳,1
表示它不会丢失。
下一行代码然后从原始单元格数据中提取那些缺少日期的日期。然后我再次运行0
来迭代这些单元格,然后我们在这个提取的单元格数组中连接每个字符串末尾的cellfun
时间戳。请注意,我还指定了两个附加参数(12:00 AM
和'uni'
),因为输出不再是单个值,而是字符串。这些字符串将被放置在单元格数组中,这是完美的,因为无论如何它们都是从单元格数组中提取的。我们没有必要在第一个0
调用中指定此项,因为输出是单个值 - 在这种情况下,它是布尔值cellfun
或0
。完成后,我们将那些缺少时间戳的日期替换为我们刚填入1
时间戳的日期。这会被覆盖到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)
我真的希望这是我最后一次解决这个问题(LOL),因为我非常确定我已经涵盖了所有意外情况。我还假设您的日期是以特定方式格式化的,我希望这可以解决您的问题。我们也不需要使用我们编写的自定义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'
函数,因为我现在正在完成日期以获得diff
时间戳。