我有一个具有以下结构的文本文件:
1999-01-04
1,100.00
1,060.00
1,092.50
0
6,225
1,336,605
37
1999-01-05
1,122.50
1,087.50
1,122.50
0
3,250
712,175
14
...
该文件包含重复的八个值集合(一个日期后面跟着七个数字,每个都在各自的行上)。
我想把它读入MATLAB并将值放到不同的向量中。我试图用几种不同的方法来实现这一点,但没有一种方法有效 - 都输出了某种错误。
如果它很重要,我在Mac上这样做。
答案 0 :(得分:9)
编辑:这是我之前在答案中的代码的简短版本......
如果您想直接读取数据文件,而不必先将其预处理为dstibbe suggested,则以下内容应该有效:
fid = fopen('datafile.txt','rt');
data = textscan(fid,'%s %s %s %s %s %s %s %s','Delimiter','\n');
fclose(fid);
data = [datenum(data{1}) cellfun(@str2double,[data{2:end}])]';
上面的代码将每组8个值放入8×N矩阵中,N是数据文件中8个线组的数量。日期将转换为序列日期编号,以便它可以包含在矩阵中的其他双精度值中。以下函数(在上面的代码中使用)可能很有用:TEXTSCAN,DATENUM,CELLFUN,STR2DOUBLE。
答案 1 :(得分:4)
我提出另一个解决方案。这是MATLAB代码中最短的一个。首先使用 sed ,我们将文件格式化为CSV文件(逗号分隔,每行记录在一行):
cat a.dat | sed -e 's/,//g ; s/[ \t]*$/,/g' -e '0~8 s/^\(.*\),$/\1\n/' |
sed -e :a -e '/,$/N; s/,\n/,/; ta' -e '/^$/d' > file.csv
解释:首先我们删除了数千个逗号分隔符,并在每行末尾修剪空格添加逗号。但是我们删除每个第8行的结尾逗号。最后,我们加入这些行并删除空行。
输出将如下所示:
1999-01-04,1100.00,1060.00,1092.50,0,6225,1336605,37
1999-01-05,1122.50,1087.50,1122.50,0,3250,712175,14
接下来在MATLAB中,我们只需使用 textscan 来读取每一行,第一个字段为字符串(转换为num),其余为数字:
fid = fopen('file.csv', 'rt');
a = textscan(fid, '%s %f %f %f %f %f %f %f', 'Delimiter',',', 'CollectOutput',1);
fclose(fid);
M = [datenum(a{1}) a{2}]
,得到的矩阵M为:
730124 1100 1060 1092.5 0 6225 1336605 37
730125 1122.5 1087.5 1122.5 0 3250 712175 14
答案 2 :(得分:3)
使用脚本将文本文件修改为Matlab可以读取的内容。
例如。把它变成一个矩阵:
M = [
1999-01-04
1,100.00
1,060.00
1,092.50
0
6,225
1,336,605; <-- notice the ';'
37
1999-01-05
1,122.50
1,087.50
1,122.50
0
3,250; <-- notice the ';'
712,175
14
...
]
将其导入matlab并从矩阵中读取各种向量。
注意:我的matlab有点生疏。可能包含错误。
答案 3 :(得分:2)
一旦您阅读完数据,您希望数据的形式并不完全清楚。下面的代码将它全部放在一个矩阵中,每行代表文本文件中的一组8行。您可能希望对不同的列使用不同的变量,或者(如果您可以访问统计工具箱),请使用数据集数组。
% Read file as text
text = fileread('c:/data.txt');
% Split by line
x = regexp(text, '\n', 'split');
% Remove commas from numbers
x = regexprep(x, ',', '')
% Number of items per object
n = 8;
% Get dates
index = 1:length(x);
dates = datenum(x(rem(index, n) == 1));
% Get other numbers
nums = str2double(x(rem(index, n) ~= 1));
nums = reshape(nums, (n-1), length(nums)/(n-1))';
% Combine dates and numbers
thedata = [dates nums];
您还可以查看函数textscan
以了解解决问题的其他方法。
答案 4 :(得分:0)
与Richie相似。使用str2double将文件字符串转换为双精度数。此实现逐行处理,而不是使用正则表达式打破文件。输出是各个向量的单元格数组。
function vectors = readdata(filename)
fid=fopen(filename);
tline = fgetl(fid);
counter = 0;
vectors = cell(7,1);
while ischar(tline)
disp(tline)
if counter > 0
vectors{counter} = [vectors{counter} str2double(tline)];
end
counter = counter + 1
if counter > 7
counter = 0;
end
tline = fgetl(fid);
end
fclose(fid);
答案 5 :(得分:0)
这有正则表达式检查,以确保您的数据格式良好。
fid = fopen('data.txt','rt'); %these will be your 8 value arrays val1 = []; val2 = []; val3 = []; val4 = []; val5 = []; val6 = []; val7 = []; val8 = []; linenum = 0; % line number in file valnum = 0; % number of value (1-8) while 1 line = fgetl(fid); linenum = linenum+1; if valnum == 8 valnum = 1; else valnum = valnum+1; end %-- if reached end of file, end if isempty(line) | line == -1 fclose(fid); break; end switch valnum case 1 pat = '(?\d{4})-(?\d{2})-(?\d{2})'; % val1 (e.g. 1999-01-04) case 2 pat = '(?\d*[,]*\d*[,]*\d*[.]\d{2})'; % val2 (e.g. 1,100.00) [valid up to 1billion-1] case 3 pat = '(?\d*[,]*\d*[,]*\d*[.]\d{2})'; % val3 (e.g. 1,060.00) [valid up to 1billion-1] case 4 pat = '(?\d*[,]*\d*[,]*\d*[.]\d{2})'; % val4 (e.g. 1,092.50) [valid up to 1billion-1] case 5 pat = '(?\d+)'; % val5 (e.g. 0) case 6 pat = '(?\d*[,]*\d*[,]*\d+)'; % val6 (e.g. 6,225) [valid up to 1billion-1] case 7 pat = '(?\d*[,]*\d*[,]*\d+)'; % val7 (e.g. 1,336,605) [valid up to 1billion-1] case 8 pat = '(?\d+)'; % val8 (e.g. 37) otherwise error('bad linenum') end l = regexp(line,pat,'names'); % l is for line if length(l) == 1 % match if valnum == 1 serialtime = datenum(str2num(l.yr),str2num(l.mo),str2num(l.dy)); % convert to matlab serial date val1 = [val1;serialtime]; else this_val = strrep(l.val,',',''); % strip out comma and convert to number eval(['val',num2str(valnum),' = [val',num2str(valnum),';',this_val,'];']) % save this value into appropriate array end else warning(['line number ',num2str(linenum),' skipped! [didnt pass regexp]: ',line]); end end