2014-04-19 94 views
2

我从以特定方式格式化的仪器获取一些数据。我需要将数据加载到MATLAB中,操纵一些数值,然后用相同的格式保存回仪器软件以供进一步分析...在MATLAB中将混合数据单元阵列保存为ascii文件

我遇到的问题是数据是混合值类型,他们都是那种地方。

该文件制表符分隔的,我加箭头例如-->以示出突片的位置(例如:写字板++一样)

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哪里可以得到需要的值,然后将它们保存在这个格式中可以很好地工作。该文件必须保存为.asc,否则仪器将拒绝它。

帮助是极大的赞赏。

谢谢

+0

*他们是那种地方*,你的意思是文本''Linspace“'可能在文件中的几个地方?如果是这样,我们是否需要将所有这些合并到一个变量中用于MATLAB? – Divakar

+0

@Divakar嗨,没有数据会完全一样。只是在实际的文件中,它会有比0.01,0.02,0.03更多的点数......我的意思是它如何从文本跳转到数字。不仅仅是字符串标题,还有数字数组都在下面。谢谢 –

回答

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”有123分别添加到它的元素。
  • “Logspace”已将120300分别添加到它的元素中。

结果

前 -

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"类似。

+0

嗨Divakar,非常感谢你的巨大努力。它看起来可以工作,但有一个问题,箭头,' - >'实际上是由我添加来显示标签的位置。所以他们不在实际的文件中。当我使用我的代码导入数据时,它将放入1x3单元格中,并将其放入临时文件中。我在原始文章中添加了一张图片以显示加载的文件。 –

+0

@SteveHatcher我可以问,你是如何获得工作区变量数据中显示的单元格数组“temp”的? – Divakar

+0

上面运行我的导入代码时,数据最初出现在1乘3的单元格阵列中。我只是通过'temp(:,1)= dataArray {1,1}','temp(:,2)= dataArray {1,2}'将第一列和第二列提取到可以放弃的位置。谢谢 –

1

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

首先,你已经把你的数据分成块,所以这很好。根据您的评论判断,数据似乎是从文件到文件格式一致,但在每个文件中格式不一致。没关系。

你需要做的是遍历dataArray,并找到每个唯一的标签(如“Linspace”)并跟踪该标签索引。你最终得到的是一个索引向量,它可以精确地告诉你这些标签出现在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

+0

嗨,谢谢你的回应。几周前,当我编写如何将数据导入MATLAB时,这个答案对我来说非常有用。我最终得到了几乎完全相同的解决方案,所以+1。我遇到的问题实际上是一旦它在MATLAB中以完全相同的格式将其保存回.asc文件。例如,在我的示例文本中,我可以将它加载到MATLAB中,我只是不能将它从MATLAB写回到一个完全相同的.asc文件中。 –

+0

Steve抱歉,并不完全理解问题的症结所在。现在看起来很清楚。我的错。事实上,在我的项目中,我也必须这样做。看起来@Divakar在下面有正确的答案。如果那不适合你,我会采取一些措施。 –