【问题标题】:Saving mixed data cell array to ascii file in MATLAB在 MATLAB 中将混合数据元胞数组保存到 ascii 文件
【发布时间】:2014-06-03 22:23:12
【问题描述】:

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

我遇到的问题是数据是混合值类型,而且它们到处都是。

文件是制表符分隔的,我添加了箭头,例如--> 来显示制表符的位置(就像notepad++一样)

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 中的数据如下所示:

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

非常感谢您的帮助。

谢谢

【问题讨论】:

  • 它们到处都是,你的意思是像 "Linspace" 这样的文字可能在文件中的多个位置吗?如果是这样,我们是否需要将所有这些合并到一个 MATLAB 变量中?
  • @Divakar 嗨,数据不会与呈现的完全相同。仅在实际文件中,它的点数将远远超过 0.01、0.02、0.03... 我的意思是它如何从文本跳转到数字。不仅仅是字符串的标题,然后是数字数组。谢谢

标签: arrays matlab file-io save ascii


【解决方案1】:

希望这对你有用。

代码

%%// 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" 的情况类似。

【讨论】:

  • 您好 Divakar,非常感谢您付出的巨大努力。看起来它可以工作,但有一个问题,箭头 --> 实际上是我添加的,以显示选项卡的位置。所以它们不在实际文件中。当我使用我的代码导入数据时,它位于 1x3 单元格中,我将其放入临时文件中。我在原始帖子中添加了一张图片以显示加载的文件。
  • @SteveHatcher 请问,您是如何获得工作区变量数据中显示的元胞数组temp
  • 在上面运行我的导入代码时,数据最初以 1 x 3 单元格数组的形式出现。我刚刚通过temp(:,1) = dataArray{1,1}temp(:,2) = dataArray{1,2} 将第一列和第二列提取到临时变量中,谢谢
  • @SteveHatcher 您能否将包含 linspace 和 logspace 的三行的示例 asc 文件上传到某处并将其链接到此处?因为我没有在您的代码中获得两个单独的列。
  • @SteveHatcher 查看编辑 1。
【解决方案2】:

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

首先,您已经将数据分成多个块,这很好。从您的评论来看,似乎数据在文件之间的格式一致,但在每个文件中的格式不一致。没关系。

您需要做的是遍历 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,这些只是猜测。您必须凭经验确定每个范围的值,因为制表符、冒号和空格之类的字符串可能会妨碍您。这应该足以让您开始解决问题。如果您需要澄清,或者这没有帮助,请告诉我。祝你好运!

-弗莱奇

【讨论】:

  • 您好,感谢您的回复。几周前,当我编写如何将数据导入 MATLAB 时,这个答案对我非常有用。我最终得到了几乎完全相同的解决方案,所以+1。我遇到的问题实际上是在 MATLAB 中以完全相同的格式将其保存回 .asc 文件。例如,在我的示例文本中,我可以将其加载到 MATLAB 中,但我无法将其从 MATLAB 写回相同的 .asc 文件...
  • Steve,抱歉,之前不太明白问题的症结所在。现在似乎很清楚了。我的错。实际上,在我的项目中,我也必须这样做。看起来@Divakar 有正确的答案,如下所示。如果这不适合你,我会努力解决的。
猜你喜欢
  • 2014-01-29
  • 2013-10-03
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多