Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从文本文件将数据读入MATLAB_Matlab_File Io_Text Files - Fatal编程技术网

从文本文件将数据读入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