Использование MatLab для получения строк, чьи третьи столбцы имеют определенную строку

У меня есть текстовый файл с разделителями табуляции.

Это выглядит как

3   5    2011-05-30.01:22:02.558151+00
1   3    2014-01-10.16:25:20.992213+00    

3-й столбец - столбец даты. Я хочу получить строки с датами 2011-05-30, 2011-05-31, 2011-06-01 или 2011-06-02.

Я начинаю код с

fid = fopen('input.txt');
input = textscan(fid, '%f %f %*s','delimiter','\t','HeaderLines',0);

Что я пробовал

  1. Я думаю, что мне нужно использовать findstr. Но я мог закодировать это только тогда, когда использую оператор if. Так что код был слишком медленным.

  2. Вместо этого, используя python, я просто заменил «-» ничем, а затем удалил вещи после «даты».

Например, я изменил

2011-05-17.01:22:02.558151+00

to

20110517

Тогда input.txt целиком состоит только из числа, а не из строки.

Таким образом, в MatLab становится легко манипулировать.

Поэтому я импортировал этот измененный файл input.txt в MatLab.

Затем я выбрал строку с третьим столбцом 20110517 или 20110518.

Но это решение утомительно.

Я попробовал следующее решение, но оно не сработало.

%// Read in the text file
textArray = textread('input.txt', '%s', 'delimiter', '\n');

%// Space split
spacesGone = cellfun(@(x) regexp(x, ' ', 'split'), textArray, 'uni', false);

%// Extract only the dates
thirdColumn = cellfun(@(x) x{3}, spacesGone);

%// Get only the date now, not the time
splitDates = cellfun(@(x) regexp(x, ' ', 'split'), thirdColumn, 'uni', false);
datesFinal = cellfun(@(x) x{1}, splitDates, 'uni', false);

%// Convert to datenum format
dateNums = datenum(datesFinal);

%// Filter
validDates = dateNums >= 734653 & dateNums <= 734656;

%// Get final dates
finalDates = textArray(validDates);

person user3123767    schedule 22.07.2014    source источник
comment
mathworks.com/help/matlab/date-and-time- Operations.html   -  person Cory Kramer    schedule 22.07.2014
comment
Вы пробовали использовать регулярные выражения или даже использовать datenum или datevec? Покажите нам, что вы пробовали до сих пор   -  person rayryeng    schedule 22.07.2014
comment
Я изменил код, чтобы он работал. Я не использовал regexp должным образом. Проверьте это.   -  person rayryeng    schedule 24.07.2014


Ответы (1)


Хорошо, я дам вам решение. Что вы можете сделать, так это использовать textread для чтения вашего текстового файла. Что мы будем делать, так это читать в тексте, и каждая строка будет помещена в одну ячейку. Для каждой ячейки разделяем строку пробелами. Как только мы это сделаем, мы увидим, что каждые 3 элемента в тексте — это то, что вам нужно.

Таким образом, мы также создадим подмножество массива ячеек, чтобы сэмплировать каждые 3 элемента. Как только мы это сделаем, мы разделим строку на основе ., чтобы удалить только саму дату. Затем мы используем datenum для преобразования даты в число. При использовании datenum 2011-05-30 или 2011-05-31 или 2011-06-01 или 2011-06-02 соответствуют числам с 734653 по 734656. Следовательно, мы конвертируем каждую из дат в эти числа, а затем выясняем, какие даты попасть в этот диапазон. Затем мы можем подмножить исходный массив текстовых ячеек и продолжить. Другими словами, если ваш текстовый файл называется text.txt, выполните:

%// Read in the text file
textArray = textread('text.txt', '%s', 'delimiter', '\n');

%// Space split
spacesGone = cellfun(@(x) strsplit(x), textArray, 'uni', false);

%// Extract only the dates
thirdColumn = cellfun(@(x) x{3}, spacesGone, 'uni', false);

%// Get only the date now, not the time
splitDates = cellfun(@(x) strsplit(x, '.'), thirdColumn, 'uni', false);
datesFinal = cellfun(@(x) x{1}, splitDates, 'uni', false);

%// Convert to datenum format
dateNums = datenum(datesFinal);

%// Filter
validDates = dateNums >= 734653 & dateNums <= 734656;

%// Get final dates
finalDates = textArray(validDates);

Используя ваш пример выше, мы получаем:

finalDates = 

  '3    2    2011-05-30.01:22:02.558151+00'

Незначительное примечание

strsplit работает только для MATLAB R2013a и выше. Если у вас его нет, попробуйте вместо него использовать regexp. Таким образом, замените strsplit на regexp. Таким образом, вот как будет выглядеть ваш код:

%// Read in the text file
textArray = textread('text.txt', '%s', 'delimiter', '\n');

%// Space split
spacesGone = cellfun(@(x) regexp(x, ' +', 'split'), textArray, 'uni', false);

%// Extract only the dates
thirdColumn = cellfun(@(x) x{3}, spacesGone, 'uni', false);

%// Get only the date now, not the time
splitDates = cellfun(@(x) regexp(x, '\.', 'split'), thirdColumn, 'uni', false);
datesFinal = cellfun(@(x) x{1}, splitDates, 'uni', false);

%// Convert to datenum format
dateNums = datenum(datesFinal);

%// Filter
validDates = dateNums >= 734653 & dateNums <= 734656;

%// Get final dates
finalDates = textArray(validDates);

Некоторые заметки для вас:

  1. В первый раз, когда я вызываю regexp (сохраняя в spacesGone), мы ищем все экземпляры, в которых они разделены по крайней мере одним пробелом, и разделяем их на основе этого. Вот почему существует оператор +, так как мы ищем хотя бы один пробел.

  2. Второй вызов regexp (сохранение в splitDates), чтобы указать поиск точки, нам нужно сделать \., так как . обозначает подстановочный знак, а это не то, что нам нужно.

person rayryeng    schedule 22.07.2014
comment
Вы написали textread('text.txt', '%s', 'разделитель', '\n'); Но поскольку первые 2 столбца являются цифрами, разве это не должно быть textread('text.txt', '&f %f %s', 'delimiter', '\n'); ?? - person user3123767; 23.07.2014
comment
@ user3123767 - Нет. Я читаю всю строку как строку, и флаг 'delimiter' для '\n' ждет, пока мы не найдем новую строку, поэтому он берет строку до этой точки и помещает ее в новую ячейку. Вы сами пробовали код? Почему бы вам не попробовать мой код, прежде чем комментировать, как и почему он не работает. Кстати, я никогда не помещал нерабочий код в StackOverflow. Я всегда проверяю, работает ли это, прежде чем что-либо публиковать. - person rayryeng; 23.07.2014
comment
Я запустил его, но я терплю неудачу. Индекс превышает размерность матрицы. Я переписал свой вопрос, чтобы показать вам, как я редактировал его для регулярного выражения. - person user3123767; 24.07.2014
comment
Я использовал этот ввод drive.google.com/file/d/ 0B1sEqo7wNB1-YmxNbmZiYUhxRlU/ - person user3123767; 24.07.2014
comment
@user3123767 user3123767 - В данных, которые вы мне дали, есть период между датой и временем. В ваших данных есть пробел. Очевидно, что мой метод не будет работать с вашим вводом, и его необходимо изменить. Я использовал ваш вклад на основе вашего поста. Если ты собираешься изменить отношение ко мне, тебе придется лучше донести это до меня. Пожалуйста, выясните, какой формат вы хотите, чтобы ваш текст соответствовал (тот, что в вашем посте, или тот, что на вашем Google Диске), а затем вернитесь ко мне. - person rayryeng; 24.07.2014
comment
Я пробовал и точку, и пространство. Например, если во входных данных есть точка, я написал регулярное выражение (x, '.', 'split'). Когда во входных данных есть пробел, я написал регулярное выражение (x, ' ', 'split'). В обоих случаях код не т работать. Думаю, я не знаю, как правильно заменить strsplit на регулярное выражение. - person user3123767; 24.07.2014
comment
@ user3123767 - Мои извинения. Вам нужно немного больше поработать с regexp. Я изменю свой пост. - person rayryeng; 24.07.2014
comment
@ user3123767 - я изменил его. Приношу свои извинения за мою оплошность с regexp. Я должен был сделать немного больше работы. Теперь код должен работать. Возьмите свои данные, которые вы разместили в своем сообщении (с точками для дат), и теперь это должно работать, как ожидалось. - person rayryeng; 24.07.2014
comment
Я получил это сообщение: Индекс превышает размеры матрицы. Ошибка в @(x)x{3} Ошибка в импортере (строка 8) ThirdColumn = cellfun(@(x) x{3}, spaceGone, 'uni', false); - person user3123767; 24.07.2014
comment
@ user3123767 Вы используете исходные данные или данные с Google Диска? Я использовал ваши данные, размещенные в вашем посте, и это работает. Это в основном работает с вашей первоначальной датой, поэтому я перестану вам помогать. Удачи. - person rayryeng; 24.07.2014
comment
Да я вижу. Я думаю, вы очень помогли. Спасибо. И я попробовал с моими данными на моем посте. Та же ошибка сохраняется. Возможно, код не учел тот факт, что ввод разделен табуляцией? или это из-за другой версии MatLab? - person user3123767; 24.07.2014
comment
@user3123767 user3123767 - Это интересно... дайте мне разобраться. - person rayryeng; 24.07.2014
comment
@user3123767 user3123767 - Я только что попробовал ваши данные и вкладку, разделяющую пробелы. Мой код все еще работает. - person rayryeng; 24.07.2014
comment
Вот как я вижу входной текстовый файл с помощью notepad++, показывая все вкладки и \r\n . Отличается ли это от того, что вы наблюдаете? drive.google.com/file/d/0B1sEqo7wNB1-TzV6cWl3clRvRlU/ Входной файл.txt — это drive.google.com. /file/d/0B1sEqo7wNB1-UXBOOTFKRVFjNDg/ - person user3123767; 24.07.2014
comment
@ user3123767 - Да, это не имеет значения. Для каждой строки вы гарантируете, что в конце есть символ новой строки? Это может быть то, где он терпит неудачу. - person rayryeng; 24.07.2014