2017-02-14 4 views
0

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 ума h соответствующую строку формата, а затем использует datestr с нужной строкой формата. Datetime не смог автоматически определить формат входной строки.

Как вы можете себе представить, это ужасно медленно для больших столов (около 50000 строк).

Есть ли более быстрое решение?

Заранее спасибо.

ответ

0

Я попытался векторизовать код. Хитрость заключается в том, чтобы

  1. преобразования таблиц> ячейки> голец-массив, то
  2. манипулировать полукокса строк, а затем
  3. преобразовать обратно из полукокса массива> клетка> таблица

Кроме того, является важным битом для заполнения всех ячеек, имеющих более короткие буквы с нулевым символом в векторном виде. Без этого невозможно будет преобразовать из 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); 
+0

Это работает намного быстрее, чем мой код. Большое спасибо. – user2760995

+0

Тем не менее, мне пришлось внести некоторые корректировки, чтобы соответствовать им. Тем не менее, мне пришлось внести некоторые корректировки в соответствии с моими потребностями: Найти формат даты и времени месяца и месяца usDates = ddd (:, 3) == '/ «; ddd (usdates, [1 2 4 5]) = ddd (usDates, [4 5 1 2]); Я должен был установить nmax на 10 и 8 соответственно. Предлагаемый расчет не удался, когда присутствовали только двузначные годы или только элементы, не отображаемые во втором. Я удалил вызовы, чтобы найти, потому что логическое индексирование немного быстрее. Объединение двух массивов символов в одном: tttt = mat2cell (tttt, ones (1, size (raw, 1)), nmaxTimes + nmaxDates + 1); – user2760995

+0

Да, его можно настроить. Из приведенного вами примера я просто показал, как преобразовывать данные из таблицы в структуру массива (что более легко векторизовать). – Abhinav

0

Если вы вызываете два столбца ячейки массива c1 и c2, то что-то, как это должно работать:

c = detestr(datenum(strcat(c1,{' '},c2)), 'dd.mm.yyyy HH:MM:SS') 

Затем вам нужно будет отбросить старые колонки и поставить это один c на их место. Однако внутри, datenum должно делать что-то похожее на то, что вы делаете, поэтому я не уверен, что это будет быстрее. Я подозреваю, что это потому, что (мы можем надеяться) стандартные функции оптимизированы.

Если ваша таблица не представляет их как массивы ячеек, вам может потребоваться выполнить предварительную обработку для формирования массивов ячеек для strcat.

+0

К сожалению, кэш-память не смогла отличить разные форматы дат: -/ – user2760995

+0

Возможно, вам не понадобится звонок 'datenum' в середине - может быть достаточно позвонить' detestr' на строку, но я сомневаюсь, что это будет лучше для различая. Сколько форматов даты у вас есть? Те, что были в вашем примере, были достаточно узнаваемы. В примере, похоже, что входящие даты являются «американским стилем» с месяцем предшествующего дня, а результат явно «европейского стиля» с днем ​​предыдущего месяца. Это вообще правда? Возможно, попробуйте преобразовать все входные данные '.' на '/'? Точечный формат не является стандартным в США и, похоже, по-видимому, он может иметь меньшую поддержку в Matlab. @ user2760995 – Brick