2015-08-03 7 views
1

У меня есть txt-файл, который я хочу прочитать в Matlab. Формат данных выглядит следующим образом:читает сложный формат .txt-файла в Matlab

term2 2015-07-31-15_58_25_612 [0.9934343, 0.3423043, 0.2343433, 0.2342323] 
term0 2015-07-31-15_58_25_620 [12] 
term3 2015-07-31-15_58_25_625 [2.3333, 3.4444, 4.5555] 
... 

Как я могу прочитать эти данные следующим образом?

name = [term2 term0 term3] or namenum = [2 0 3] 
time = [2015-07-31-15_58_25_612 2015-07-31-15_58_25_620 2015-07-31-15_58_25_625] 
data = {[0.9934343, 0.3423043, 0.2343433, 0.2342323], [12], [2.3333, 3.4444, 4.5555]} 

Я пытался использовать textscan таким образом 'term%d %s [%f, %f...]', но для последней части данных я не могу определить длину, потому что они разные. Тогда как я могу его прочитать? Моя версия Matlab - R2012b.

Большое спасибо, если кто-нибудь может помочь!

ответ

1

Возможно, это один из способов сделать это за один проход, но для меня эти проблемы проще сортировать с использованием подхода с 2-мя проходами.

  • Передача 1: Прочитайте все столбцы с постоянным форматом в соответствии с их типом (строка, целое число и т. Д.) И прочитайте не постоянную часть в отдельном столбце, который будет обрабатываться во втором проходе.
  • Пасс 2: Обработайте свою нерегулярную колонну в соответствии со своими особенностями.

В случае с данными выборки, это выглядит следующим образом:

%% // read file 
fid = fopen('Test.txt','r') ; 
M = textscan(fid , 'term%d %s %*c %[^]] %*[^\n]' ) ; 
fclose(fid) ; 

%% // dispatch data into variables 
name = M{1,1} ; 
time = M{1,2} ; 
data = cellfun(@(s) textscan(s,'%f',Inf,'Delimiter',',') , M{1,3}) ; 

Что случилось:
Первая textscan инструкция читает полный файл. В спецификатора формата:

  • term%d читать целое число после буквального выражения 'term'.
  • %s читать строка, представляющая дату.
  • %*c игнорировать один знак (для игнорирования персонажа '[').
  • %[^]] читать все (как строка), пока не найдет символ ']'.
  • %*[^\n] игнорировать все до следующей строки новой строки ('\n'). (Чтобы не захватить последнюю ']'.

После этого, первые 2 столбца легко посланы в их собственных переменный. 3-й столбце массива результата ячейки M содержит строки различной длины, содержащие различное число числа с плавающей точкой ,Мы используем cellfun в сочетании с другим textscan читать числа в каждой ячейке и возвращают массив ячеек, содержащий double:

textscan advanced


Бонус: Если вы хотите, чтобы ваше время, чтобы быть числовым значение, а (вместо строки), используйте следующее расширение кода:

%% // read file 
fid = fopen('Test.txt','r') ; 
M = textscan(fid , 'term%d %f-%f-%f-%f_%f_%f_%f %*c %[^]] %*[^\n]' ) ; 
fclose(fid) ; 

%% // dispatch data 
name = M{1,1} ; 
time_vec = cell2mat(M(1,2:7)) ; 
time_ms = M{1,8} ./ (24*3600*1000) ; %// take care of the millisecond separatly as they are not handled by "datenum" 
time = datenum(time_vec) + time_ms ; 
data = cellfun(@(s) textscan(s,'%f',Inf,'Delimiter',',') , M{1,end}) ; 

Это даст вам массив time с временным серийным Matlab число (часто проще в использовании, чем строки). Для того, чтобы показать вам серийный номер по-прежнему представляют собой правильное время:

>> datestr(time,'yyyy-mm-dd HH:MM:SS.FFF') 
ans = 
2015-07-31 15:58:25.612 
2015-07-31 15:58:25.620 
2015-07-31 15:58:25.625 
+0

Так полезно для меня! Большое спасибо за ваш очень подробный ответ! – Hongwei

0

Для осложнила строки синтаксического анализа ситуации, как, например, что лучше всего использовать regexp. В этом случае, предположив, что у вас есть данные в файле data.txt, следующий код должен делать то, что вы ищете:

txt = fileread('data.txt') 
tokens = regexp(txt,'term(\d+)\s(\S*)\s\[(.*)\]','tokens','dotexceptnewline') 

% Convert namenum to numeric type 
namenum = cellfun(@(x)str2double(x{1}),tokens) 

% Get time stamps from the second row of all the tokens 
time = cellfun(@(x)x{2},tokens,'UniformOutput',false); 

% Split the numbers in the third column 
data = cellfun(@(x)str2double(strsplit(x{3},',')),tokens,'UniformOutput',false) 
Смежные вопросы