从文本文件将数据读入MATLAB
我有一个具有以下结构的文本文件:从文本文件将数据读入MATLAB,matlab,file-io,text-files,Matlab,File Io,Text Files,我有一个具有以下结构的文本文件: 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,然后把值转换成不同的向量。我曾尝试用几种不同的方法来实现这一点,但都没有成功——都会输出某种错误 如果这很重要,我将在Ma
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上执行此操作。使用脚本将文本文件修改为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
...
]
M=[
1999-01-04
1,100.00
1,060.00
1,092.50
0
6,225
1336605;阅读数据后,不完全清楚您希望数据采用何种形式。下面的代码将其全部放在一个矩阵中,每一行表示文本文件中一组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
,以找到解决此问题的其他方法。与Richie的类似。使用str2double将文件字符串转换为double。此实现逐行处理文件,而不是使用正则表达式分解文件。输出是单个向量的单元格数组。
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);
编辑:这是我以前在回答中使用的代码的较短版本
如果您希望直接读取数据文件,而无需先对其进行预处理,则以下操作应可行:
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行集的数量。该日期转换为一个序列日期号,以便可以与矩阵中的其他双精度值一起包含。以下函数(在上述代码中使用)可能会有兴趣:
解释:首先,我们去掉了数千个逗号分隔符,并在每行末尾的空格中添加一个逗号。然后,我们删除了每第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
这有正则表达式检查,以确保数据格式正确
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
fid=fopen('data.txt','rt');
%这些将是您的8值数组
val1=[];
val2=[];
val3=[];
val4=[];
val5=[];
val6=[];
val7=[];
val8=[];
linenum=0;%文件中的行号
valnum=0;值的百分比(1-8)
而1
直线=fgetl(fid);
linenum=linenum+1;
如果valnum==8
valnum=1;
其他的
valnum=valnum+1;
结束
%--如果到达文件末尾,则结束
如果为空(直线)|直线==-1
fclose(fid);
打破
结束
开关valnum
案例1
pat='(?\d{4})-(?\d{2})-(?\d{2});%val1(例如1999-01-04)
案例2
pat='(?\d*[,]*\d*[,]*\d*[.]\d{2});%val2(例如1100.00)[有效期高达10亿-1]
案例3
pat='(?\d*[,]*\d*[,]*\d*[.]\d{2});%val3(例如1060.00)[有效期高达10亿-1]
案例4
pat='(?\d*[,]*\d*[,]*\d*[.]\d{2});%val4(例如1092.50)[有效期高达10亿-1]
案例5
pat='(?\d+);%val5(例如0)
案例6
pat='(?\d*[,]*\d*[,]*\d+);%val6(例如6225)[有效期高达10亿-1]
案例7
pat='(?\d*[,]*\d*[,]*\d+);%val7(例如1336605)[有效期高达10亿-1]
案例8
pat='(?\d+);%val8(例如37)
否则
错误('bad linenum')
结束
l=regexp(line,pat,'names');%l表示line
如果长度(l)==1%匹配
如果valnum==1
serialtime=datenum(str2num(l.yr)、str2num(l.mo)、str2num(l.dy));%转换为matlab序列日期
val1=[val1;serialtime];
其他的
这个值=strep(l.val,,,,,,;%去掉逗号并转换为数字
eval(['val',num2str(valnum),'=[val',num2str(valnum),';',this_val',];'))%将此值保存到适当的数组中
结束
其他的
警告(['line number',num2str(linenum),'skipped![not pass regexp]:',line]);
结束
结束
还有一点不清楚,val 1
是否表示第一组8行,val 2
第二组8行,等等?等一下……我刚刚意识到每行上可能只有一个数字,而不是逗号分隔的值集。我猜712175
表示”“七十一万二千,一百七十五"对不起。每个周期应该有8个值。谢谢!谢谢,我用这种方法解决了。用python创建了一个脚本,让我按照你建议的方式生成矩阵!这正是我想要做的!非常感谢。但是-为什么在matlab中读取数据这么麻烦?…谢谢again@Fifth当前位置使您的案例变得困难的是在中使用逗号数字的格式。通常,逗号用于分隔数字,而不是表示数字中的千和百万之间的分隔。从Amro的例子中可以看出,对于格式更好的数字来说,MATLAB代码是微不足道的。@Fifth:实际上,我能想出一个更短的cod版本E,与AMRO的紧凑答案相比较,不需要任何数据文件的预处理。@第五:应该注意到C语言SCANF和C++ IOFROW都在示例文件中逗号上阻塞。您也必须在这些语言中进行两遍操作。C处理逗号,我不了解Java。这确实较短:)顺便说一句,您可以在textscan上使用“CollectOutput”选项,因此可以避免调用cellf
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