如何通过匹配时间间隔连接 Matlab (2018) 中的表格?
How to join tables in Matlab (2018) by matching time intervals?
我有两个tableA和B,我想根据他们的有效时间间隔加入他们。
A有产品质量(不定时),B有生产期间每小时设置。我需要创建一个像 C 一样的 table,其中包含属于 B 的 ValidFrom ValidTo 时间范围内的所有 A 的 RefDates 的参数 p1 和 p2。
A
RefDate result
'11-Oct-2017 00:14:00' 17
'11-Oct-2017 00:14:00' 19
'11-Oct-2017 00:20:00' 5
'11-Oct-2017 01:30:00' 25
'11-Oct-2017 01:30:00' 18
'11-Oct-2017 03:03:00' 28
B
ValidFrom ValidTo p1 p2
'11-Oct-2017 00:13:00' '11-Oct-2017 01:12:59' 2 1
'11-Oct-2017 01:13:00' '11-Oct-2017 02:12:59' 3 1
'11-Oct-2017 02:13:00' '11-Oct-2017 03:12:59' 4 5
'11-Oct-2017 03:13:00' '11-Oct-2017 04:12:59' 6 1
'11-Oct-2017 04:13:00' '11-Oct-2017 05:12:59' 7 9
我需要这样的东西。
C
RefDate res p1 p2
'11-Oct-2017 00:14:00' 17 2 1
'11-Oct-2017 00:14:00' 19 2 1
'11-Oct-2017 00:20:00' 5 2 1
'11-Oct-2017 01:30:00' 25 3 1
'11-Oct-2017 01:30:00' 18 3 1
'11-Oct-2017 03:03:00' 28 4 5
我知道如何在 SQL 中执行此操作,而且我想我已经弄清楚如何在 MatLab 中逐行执行此操作,但这速度非常慢。数据集相当大。我只是假设一定有一种我找不到的更优雅的方式。
导致我的许多方法失败的原因是 RefDate 列不是唯一的。
编辑:
真正的 table 有数千行和数百个变量。
C (in reality)
RefDate res res2 ... res200 p1 p2 ... p1000
11-Oct-2017 00:14:00 17 2 1
11-Oct-2017 00:14:00 19 2 1
11-Oct-2017 00:20:00 5 2 1
11-Oct-2017 01:30:00 25 3 1
11-Oct-2017 01:30:00 18 3 1
11-Oct-2017 03:03:00 28 4 5
以下代码完全符合您的要求:
% convert to datetime
A.RefDate = datetime(A.RefDate);
B.ValidFrom = datetime(B.ValidFrom);
B.ValidTo = datetime(B.ValidTo);
% for each row in A, find the matching row in B
i = cellfun(@find, arrayfun(@(x) (x >= B.ValidFrom) & (x <= B.ValidTo), A.RefDate, 'UniformOutput', false), 'UniformOutput', false);
% find rows in A that where not matched
j = cellfun(@isempty, i, 'UniformOutput', false);
% build the result
C = [B(cell2mat(i),:) A(~cell2mat(j),:)];
% display output
C
这实际上可以在一行代码中完成。假设您的 ValidTo
值总是在下一行的 ValidFrom
之前结束(在您的示例中),您只需要使用 ValidFrom
值。首先,使用 datenum
. Then use the discretize
函数将这些值和您的 RefDate
值转换为序列日期数字,以使用 ValidFrom
值作为边缘对 RefDate
值进行分箱,这将为您提供行B
中的索引包含 A
中的每个时间。然后使用该索引提取 p1
和 p2
值并将它们附加到 A
:
>> C = [A B(discretize(datenum(A.RefDate), datenum(B.ValidFrom)), 3:end)]
C =
RefDate result p1 p2
______________________ ______ __ __
'11-Oct-2017 00:14:00' 17 2 1
'11-Oct-2017 00:14:00' 19 2 1
'11-Oct-2017 00:20:00' 5 2 1
'11-Oct-2017 01:30:00' 25 3 1
'11-Oct-2017 01:30:00' 18 3 1
'11-Oct-2017 03:03:00' 28 4 5
上述解决方案适用于 B
中任意数量的列 pN
。
如果 A
中有任何时间不在 B
中的任何范围内,则必须将解决方案分成多行,以便检查是否从 discretize
返回的索引包含 NaN
个值。假设您想从 C
中排除这些行,这将是新的解决方案:
index = discretize(datenum(A.RefDate), datenum(B.ValidFrom));
C = [A(~isnan(index), :) B(index(~isnan(index)), 3:end)];
我有两个tableA和B,我想根据他们的有效时间间隔加入他们。
A有产品质量(不定时),B有生产期间每小时设置。我需要创建一个像 C 一样的 table,其中包含属于 B 的 ValidFrom ValidTo 时间范围内的所有 A 的 RefDates 的参数 p1 和 p2。
A
RefDate result
'11-Oct-2017 00:14:00' 17
'11-Oct-2017 00:14:00' 19
'11-Oct-2017 00:20:00' 5
'11-Oct-2017 01:30:00' 25
'11-Oct-2017 01:30:00' 18
'11-Oct-2017 03:03:00' 28
B
ValidFrom ValidTo p1 p2
'11-Oct-2017 00:13:00' '11-Oct-2017 01:12:59' 2 1
'11-Oct-2017 01:13:00' '11-Oct-2017 02:12:59' 3 1
'11-Oct-2017 02:13:00' '11-Oct-2017 03:12:59' 4 5
'11-Oct-2017 03:13:00' '11-Oct-2017 04:12:59' 6 1
'11-Oct-2017 04:13:00' '11-Oct-2017 05:12:59' 7 9
我需要这样的东西。
C
RefDate res p1 p2
'11-Oct-2017 00:14:00' 17 2 1
'11-Oct-2017 00:14:00' 19 2 1
'11-Oct-2017 00:20:00' 5 2 1
'11-Oct-2017 01:30:00' 25 3 1
'11-Oct-2017 01:30:00' 18 3 1
'11-Oct-2017 03:03:00' 28 4 5
我知道如何在 SQL 中执行此操作,而且我想我已经弄清楚如何在 MatLab 中逐行执行此操作,但这速度非常慢。数据集相当大。我只是假设一定有一种我找不到的更优雅的方式。
导致我的许多方法失败的原因是 RefDate 列不是唯一的。
编辑: 真正的 table 有数千行和数百个变量。
C (in reality)
RefDate res res2 ... res200 p1 p2 ... p1000
11-Oct-2017 00:14:00 17 2 1
11-Oct-2017 00:14:00 19 2 1
11-Oct-2017 00:20:00 5 2 1
11-Oct-2017 01:30:00 25 3 1
11-Oct-2017 01:30:00 18 3 1
11-Oct-2017 03:03:00 28 4 5
以下代码完全符合您的要求:
% convert to datetime
A.RefDate = datetime(A.RefDate);
B.ValidFrom = datetime(B.ValidFrom);
B.ValidTo = datetime(B.ValidTo);
% for each row in A, find the matching row in B
i = cellfun(@find, arrayfun(@(x) (x >= B.ValidFrom) & (x <= B.ValidTo), A.RefDate, 'UniformOutput', false), 'UniformOutput', false);
% find rows in A that where not matched
j = cellfun(@isempty, i, 'UniformOutput', false);
% build the result
C = [B(cell2mat(i),:) A(~cell2mat(j),:)];
% display output
C
这实际上可以在一行代码中完成。假设您的 ValidTo
值总是在下一行的 ValidFrom
之前结束(在您的示例中),您只需要使用 ValidFrom
值。首先,使用 datenum
. Then use the discretize
函数将这些值和您的 RefDate
值转换为序列日期数字,以使用 ValidFrom
值作为边缘对 RefDate
值进行分箱,这将为您提供行B
中的索引包含 A
中的每个时间。然后使用该索引提取 p1
和 p2
值并将它们附加到 A
:
>> C = [A B(discretize(datenum(A.RefDate), datenum(B.ValidFrom)), 3:end)]
C =
RefDate result p1 p2
______________________ ______ __ __
'11-Oct-2017 00:14:00' 17 2 1
'11-Oct-2017 00:14:00' 19 2 1
'11-Oct-2017 00:20:00' 5 2 1
'11-Oct-2017 01:30:00' 25 3 1
'11-Oct-2017 01:30:00' 18 3 1
'11-Oct-2017 03:03:00' 28 4 5
上述解决方案适用于 B
中任意数量的列 pN
。
如果 A
中有任何时间不在 B
中的任何范围内,则必须将解决方案分成多行,以便检查是否从 discretize
返回的索引包含 NaN
个值。假设您想从 C
中排除这些行,这将是新的解决方案:
index = discretize(datenum(A.RefDate), datenum(B.ValidFrom));
C = [A(~isnan(index), :) B(index(~isnan(index)), 3:end)];