将混合数据单元阵列保存到MATLAB中的ascii文件中

时间:2014-04-19 13:18:05

标签: arrays matlab file-io save ascii

我从以特定方式格式化的乐器中获取一些数据。我需要将数据加载到MATLAB中,操作一些值,然后用相同的格式将其保存回仪器软件中进行进一步分析......

我遇到的问题是数据属于混合值类型,并且它们遍布各处。

文件是制表符分隔的,我添加了箭头,例如-->以显示标签的位置(就像记事本++那样)

Scan-42/01
Temperature [K] :-->   295.00
Time [s]        :-->     60

"Linspace"
0.01-->   0.96
0.02-->   0.95
0.03-->   0.95

"Logspace"
0.01-->   0.96
0.02-->   0.95
0.04-->   0.94

数据一直在下降,但我在3行后将其剪掉了。

我需要操作的数据是Temperature,以及LinspaceLogspace下的一些值。

我目前正在导入这样的数据:

filename = 'test.asc';
delimiter = '\t';
formatSpec = '%s%s%[^\n\r]';
fileID = fopen(filename,'r');
dataArray = textscan(fileID, formatSpec, 'Delimiter', delimiter, 'ReturnOnError', false);

MATLAB中的数据如下所示:

.asc file loaded into MATLAB

即使我可以在MATLAB中设置某种模板,在那里我可以得到值nesessary,然后将它们保存在这个格式中就可以正常工作了。该文件必须保存为.asc,否则仪器将拒绝该文件。

非常感谢帮助。

由于

2 个答案:

答案 0 :(得分:2)

希望这对你有用。

<强>代码

%%// Note: file1 is your input .asc filename and file2 is the output .asc.
%%// Please specify their names before running this.

%%// **** Read in file data  **** 
fid = fopen(file1,'r');
A = importdata(file1,'\n')

%%// Delimiters (mind these assumptions)
linlog_delim1 = '-->   ';
temperature_delim1 = 'Temperature [K] :-->   ';

sep1 = cellfun(@(x) isequal(x,''),A)
sep1 = [sep1 ;1]
sep_ind = find(sep1)
full_data = regexp(A,linlog_delim1,'split')

%%// Temperature value
temp_ind = find(~cellfun(@isempty,strfind(A,'Temperature [K] :-->')))
temp_val = str2num(cell2mat(full_data{temp_ind,:}(1,2)))

%%// Linspace values
sep_linspace = cellfun(@(x) isequal(x,'"Linspace"'),A)
lin_start_ind = find(sep_linspace)+1
lin_stop_ind = sep_ind(find(sep_ind>lin_start_ind,1,'first'))-1

linspace_data = vertcat(full_data{lin_start_ind:lin_stop_ind})
linspace_valid_ind = cellfun(@str2num,linspace_data(:,1))
linspace_valid_val = cellfun(@str2num,linspace_data(:,2))

%%// Logspace values
sep_linspace = cellfun(@(x) isequal(x,'"Logspace"'),A)
log_start_ind = find(sep_linspace)+1
log_stop_ind = sep_ind(find(sep_ind>log_start_ind,1,'first'))-1

logpace_data = vertcat(full_data{log_start_ind:log_stop_ind})
logspace_valid_ind = cellfun(@str2num,logpace_data(:,1))
logspace_valid_val = cellfun(@str2num,logpace_data(:,2))

%%// ****  Let us modify some data ****
temp_val = temp_val + 10;
linspace_valid_val_mod1 = linspace_valid_val+[1 2 3]'; %%//'
logspace_valid_val_mod1 = logspace_valid_val+[1 20 300]'; %%//'

%%// **** Write back file data  ****

%%// Write back temperature data
A(temp_ind) = {[temperature_delim1,num2str(temp_val)]}

%%// Write back linspace data
mod_lin_val = cellfun(@strtrim,cellstr(num2str(linspace_valid_val_mod1)),'uni',0)
mod_lin_ind = cellstr(num2str(linspace_valid_ind))
sep_lin = repmat({linlog_delim1},numel(mod_lin_val),1)
A(lin_start_ind:lin_stop_ind)=cellfun(@horzcat,mod_lin_ind,sep_lin,mod_lin_val,'uni',0)

%%// Write back logspace data
mod_log_val = cellfun(@strtrim,cellstr(num2str(logspace_valid_val_mod1)),'uni',0)
mod_log_ind = cellstr(num2str(logspace_valid_ind))
sep_log = repmat({linlog_delim1},numel(mod_log_val),1)
A(log_start_ind:log_stop_ind)=cellfun(@horzcat,mod_log_ind,sep_log,mod_log_val,'uni',0)

%%// Remove leading whitespaces
A = strtrim(A)

%%// Write the modified data 
fid2 = fopen(file2,'w');
for row = 1:numel(A)
    fprintf(fid2,'%s\n',A{row,:});
end

fclose(fid);
fclose(fid2);

演示的更改:

  • 温度已添加10
  • “Linspace”分别为1 23添加了元素。
  • “Logspace”分别为1 20300添加了元素。

<强>结果

之前 -

Scan-42/01
Temperature [K] :-->   295.00
Time [s]        :-->     60

"Linspace"
0.01-->   0.96
0.02-->   0.95
0.103-->   0.95

"Logspace"
0.01-->   0.96
0.02-->   0.95
0.04-->   0.94

之后 -

Scan-42/01
Temperature [K] :-->   305
Time [s]        :-->     60

"Linspace"
0.01-->   1.96
0.02-->   2.95
0.103-->   3.95

"Logspace"
0.01-->   1.96
0.02-->   20.95
0.04-->   300.94

修改1:

<强>代码

%%// I-O filenames
input_filename = 'gistfile1.txt';
output_file = 'gistfile1_out.txt';

%%// Get data from input filename
delimiter = '\t';
formatSpec = '%s%s%[^\n\r]';
fid = fopen(input_filename,'r');
dataArray = textscan(fid, formatSpec, 'Delimiter', delimiter, 'ReturnOnError', false);

%%// Get data into A
A(:,1) = dataArray{1,1}
A(:,2) = dataArray{1,2}

%%// Find separator indices
ind1 = find([cellfun(@(x) isequal(x,''),A(:,2));1])
temperature_ind = find(~cellfun(@isempty,strfind(A,'Temperature')))
temperature_val = str2num(cell2mat(A(temperature_ind,2)))

%%// Linspace values
sep_linspace = cellfun(@(x) isequal(x,'"Linspace"'),A(:,1))
lin_start_ind = find(sep_linspace)+1
lin_stop_ind = ind1(find(ind1>lin_start_ind,1,'first'))-1

linspace_valid_ind = cellfun(@str2num,A(lin_start_ind:lin_stop_ind,1))
linspace_valid_val = cellfun(@str2num,A(lin_start_ind:lin_stop_ind,2))

%%// Logspace values
sep_logspace = cellfun(@(x) isequal(x,'"Logspace"'),A(:,1))
log_start_ind = find(sep_logspace)+1
log_stop_ind = ind1(find(ind1>log_start_ind,1,'first'))-1

logspace_valid_ind = cellfun(@str2num,A(log_start_ind:log_stop_ind,1))
logspace_valid_val = cellfun(@str2num,A(log_start_ind:log_stop_ind,2))

%%// ****  Let us modify some data ****
temp_val_mod1 = temperature_val + 10;
linspace_valid_val_mod1 = linspace_valid_val+[1:numel(linspace_valid_val)]';
logspace_valid_val_mod1 = logspace_valid_val+10.*[1:numel(logspace_valid_val)]';

%%// **** Write back file data into A  ****
A(temperature_ind,2) = cellstr(num2str(temp_val_mod1))
A(lin_start_ind:lin_stop_ind,2) = cellstr(num2str(linspace_valid_val_mod1))
A(log_start_ind:log_stop_ind,2) = cellstr(num2str(logspace_valid_val_mod1))

%%// Write the modified data 
fid2 = fopen(output_file,'w');
for row = 1:size(A,1)
    fprintf(fid2,'%s\t%s\n',A{row,1},A{row,2});
end

%%// Close files
fclose(fid);
fclose(fid2);

<强>结果

之前 -

Scan-42/01
Temperature [K] :   295.00
Time [s]        :   60

"Linspace"
0.01    0.96
0.02    0.95
0.03    0.95

"Logspace"
0.01    0.96
0.02    0.95
0.04    0.94

之后 -

Scan-42/01  
Temperature [K] :   305
Time [s]        :   60
"Linspace"  
0.01    1.96
0.02    2.95
0.03    3.95
"Logspace"  
0.01    10.96
0.02    20.95
0.04    30.94

请注意,输入和输出文件之间唯一的格式差异是输出文件中"Linspace"和前一行之间没有空格行,就像输入文件中那样。 "Logspace"也可以看到这一点。

答案 1 :(得分:1)

我曾经解决过一个几乎相同的问题。解决方案是这样的:

首先,您已经将数据拆分成块,这样做很好。根据您的评论判断,似乎数据在文件之间始终格式化,但在每个单独的文件中格式不一致。没关系。

您需要做的是遍历dataArray,找到每个唯一标签(例如&#34; Linspace&#34;)并跟踪标签索引。您最终得到的是一个索引向量,它们可以准确地告诉您这些标签在dataArray中的位置。获得所有标签索引后,需要查看dataArray,并查看每个标签之间的数据是如何格式化的。然后,您将编写一些代码将dataArray分解为子数组。您需要为每种格式编写不同的子数组解析器。

我知道这有点抽象,所以让我试着举个例子。

 timeIndex      = find(strcmp(dataArray, 'Time'), 1);
 linespaceIndex = find(strcmp(dataArray, '"linSpace"'), 1);
 logespaceIndex = find(strcmp(dataArray, '"logSpace"'), 1);

 linSpaceData = dataArray(linspaceIndex+3:logspaceIndex-1);   % This is the "sub-array" I was refering to. It's a little piece of dataArray that contains only the linspace data values.

这只是一个例子,可能不会即插即用,它只是一个思想挑战者。注意+3和-1,这些只是猜测。你必须根据经验确定每个范围的那些,因为像标签,冒号和空格这样的元素可能会妨碍你。这应该足以让你开始解决你的问题。如果您需要澄清,或者这对您没有帮助,请告诉我。祝你好运!

-Fletch