Как объединить таблицы в Matlab (2018), сопоставляя временные интервалы?

У меня есть две таблицы A и B. Я хочу присоединиться к ним на основании их временных интервалов.

A имеет качество продукции (нерегулярное время), а B имеет почасовые настройки в течение периода производства. Мне нужно создать таблицу типа C, которая включает параметры p1 и p2 для всех RefDates A, которые попадают во временной диапазон ValidFrom от ValidTo.

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 не уникален.

редактировать: реальные таблицы имеют тысячи строк и сотни переменных.

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

2 ответа

Решение

Это на самом деле может быть сделано в одной строке кода. Предполагая ваш ValidTo значение всегда заканчивается непосредственно перед ValidFrom в следующем ряду (что он делает в вашем примере), вам нужно только использовать ValidFrom ценности. Во-первых, конвертировать те и ваши RefDate значения к порядковым номерам дат, используя datenum, Затем используйте discretize функция для бин RefDate значения с использованием ValidFrom значения как ребра, которые дадут вам индекс строки в 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 

Вышеупомянутое решение должно работать для любого количества столбцов pN в B,

Если есть какие-либо времена в A которые не попадают ни в один из диапазонов B вам придется разбить решение на несколько строк, чтобы вы могли проверить, возвращен ли индекс из discretize содержит NaN ценности. Предполагая, что вы хотите исключить эти строки из C, это было бы новым решением:

index = discretize(datenum(A.RefDate), datenum(B.ValidFrom));
C = [A(~isnan(index), :) B(index(~isnan(index)), 3:end)];

Следующий код делает именно то, что вы просите:

% 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
Другие вопросы по тегам