Унифицировать метки времени как строки даты
MATLAB R2015b
У меня есть таблица, содержащая строку даты и строку времени в различных форматах в двух столбцах для каждой строки:
11.01.2016 | 00:00:00 | data
10/19/16 | 05:29:00 | data
12.02.16 | 06:40 | data
Я хочу преобразовать эти два столбца в один столбец с общим форматом:
31.12.2017 14:00:00
Мое текущее решение использует цикл над каждой строкой и объединяет столбцы в виде строк, проверяет различные форматы, чтобы использовать datetime с соответствующей строкой формата, а затем использует datestr с требуемой строкой формата. Datetime не смог автоматически определить формат входной строки.
Как вы можете себе представить, это ужасно медленно для больших таблиц (около 50000 строк).
Есть ли более быстрое решение?
Заранее спасибо.
2 ответа
Я дал попытку векторизовать код. Хитрость заключается в
- преобразовать таблицы> ячейка> массив символов, затем
- манипулировать символьными строками, затем
- преобразовать обратно из char-array > cell > table
Кроме того, есть важный бит для заполнения всех ячеек с более короткими длинами с нулевым символом векторизованным способом. Без этого будет невозможно конвертировать из cell > char-array. Вот код clc очистить все
%% create Table T
d={'11.01.2016';
'10/19/16';
'12.02.16'};
t={'00:00:00';
'05:29:00';
'06:40'};
dat=[123;
456;
789];
T = table(d,t,dat);
%% deal with dates in Table T
% separate date column and convert to cell
dd = table2cell(T(:,1));
% equalize the lengths of all elements of cell
% by padding 'null' in end of shorter dates
nmax=max(cellfun(@numel,dd));
func = @(x) [x,zeros(1,nmax-numel(x))];
temp1 = cellfun(func,dd,'UniformOutput',false);
% convert to array for vectorized manipulation of char strings
ddd=cell2mat(temp1);
% replace the separators in 3rd and 6th location with '.' (period)
ddd(:,[3 6]) = repmat(['.' '.'], length(dd),1);
% find indexes of shorter dates
short_year_idx = find(uint16(ddd(:,nmax)) == 0);
% find the year value for those short_year cases
yy = ddd(short_year_idx,[7 8]);
% replace null chars with '20XX' string in desirted place
ddd(short_year_idx,7:nmax) = ...
[repmat('20',size(short_year_idx,1),1) yy];
% convert char array back to cell and replace in table
dddd = mat2cell(ddd,ones(1,size(d,1)),nmax);
T(:,1) = table(dddd);
%% deal with times in Table T
% separate time column and convert to cell
tt = table2cell(T(:,2));
% equalize the lengths of all elements of cell
% by padding 'null' in end of shorter times
nmax=max(cellfun(@numel,tt));
func = @(x) [x,zeros(1,nmax-numel(x))];
temp1 = cellfun(func,tt,'UniformOutput',false);
% convert to array for vectorized manipulation of char strings
ttt=cell2mat(temp1);
% find indexes of shorter times (assuming only ':00' in end is missing
short_time_idx = find(uint16(ttt(:,nmax)) == 0);% dirty hack, as null=0 in ascii
% replace null chars with ':00' string
ttt(short_time_idx,[6 7 8]) = repmat(':00',size(short_time_idx,1),1);
% convert char array back to cell and replace in table
tttt = mat2cell(ttt,ones(1,size(t,1)),nmax);
T(:,2) = table(tttt);
Если вы называете два столбца ячейками c1
а также c2
, тогда что-то вроде этого должно работать:
c = detestr(datenum(strcat(c1,{' '},c2)), 'dd.mm.yyyy HH:MM:SS')
Тогда вам нужно будет отбросить старые столбцы и поставить этот c
на их месте. На внутренней, datenum
должно быть, что-то похожее на то, что вы делаете, однако, поэтому я не уверен, будет ли это быстрее. Я подозреваю, что это потому, что (мы можем надеяться) стандартные функции оптимизированы.
Если ваша таблица не представляет их как массивы ячеек, то вам может потребоваться выполнить предварительную обработку, чтобы сформировать массивы ячеек для strcat
,