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

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

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

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

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

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 ]

0 голосов
/ 09 октября 2018

На самом деле это можно сделать одной строкой кода.Предполагая, что ваше значение 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)];
0 голосов
/ 09 октября 2018

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

% 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
...