如何将文件中的数据导入变量数组? (Matlab)
How to import data from file into variable arrays? (Matlab)
我使用 matlab 创建了 .txt 文件,这些文件有不同的 3 列,由制表符(字符串、浮点、浮点)和不同的行数分隔。
我正在尝试将这 3 列数据中的每一列读入 3 个不同的变量。这是我的代码:
fileId = fopen('file.txt');
% Storing columns from txt file into appropriate compartment data arrays
compartment_name = textscan(fileId,'%s%*f%*f','Delimiter','\t'); % column of strings
compartment_length = textscan(fileId,'%*s%f%*f','Delimiter','\t'); % column of doubles
compartment_diameter = textscan(fileId,'%*s%*f%f','Delimiter','\t'); % column of doubles
fclose('file.txt');
我收到 compartment_name 的正确数据(1x1 单元格包含 106x1 单元格(每个单元格都是一个字符串)),但是 compartment_length 和 compartment_diameter return 包含 0x1 双倍的空 1x1 单元格。
有什么想法吗?
还有 - 有什么简单的方法可以将 1x1 单元格转换为数组吗?即对于 compartment_name,它将是一个 1x106 字符串数组 ?
正如@jgrant 指出的那样,问题是如果您想重新读取文件的某些部分,您必须将文件位置指示器重置为文件的开头。
我真的不明白你为什么要尝试调用 textscan
三次,textscan
的输出是一个单元格的原因正是你可以调用一次它,然后分隔输出列:
tmpcell = textscan(fileId,'%s%f%f','Delimiter','\t'); % column of strings
compartment_name = tmpcell{1};
compartment_length = tmpcell{2};
compartment_diameter = tmpcell{3};
% or if you want to be fancy about it:
%[compartment_name, compartment_length, compartment_diameter] = tmpcell{:};
我写这个答案的原因是你的最后注释:
Also - is there any easy way for me to convert the 1x1 cells into an array? ie for compartment_name, it would be an array of 1x106 strings ?
这暗示您对 MATLAB 中的字符串感到困惑。在 MATLAB 中,字符串本质上是 整数数组 。您可以通过对字符串执行任何类型的算术运算来亲眼看到这一点:
>> tmpstring = 'asdf'
tmpstring =
asdf
>> tmpstring*1
ans =
97 115 100 102
您看到的数字是字符串中字符的 ASCII 表示形式。这也适用于其他方式:您可以通过将整数放入数组来构建字符串。事实上,就所有意图和目的而言,字符串 是 整数数组:
>> isequal([97 115 100 102],'asdf')
ans =
1
这也暗示了 MATLAB 中字符串的一些限制。你的问题是你不能简单地创建一个字符串数组。那就是字符串连接:如果 string1
和 string2
都只是整数数组,那么 [string1, string2]
就是两个字符串的连接。
然后您可以考虑使用 [string1; string2]
水平堆叠字符串。现在,这与它对两个整数数组的作用完全一样:如果字符串的长度相等(我现在的长度是指size(string1,2)
),你只能这样做。所以在一般情况下,您只能将字符串一起存储在一个非均匀容器中,即 MATLAB 中的单元格。拥有单元格后,您的元素可以具有任何类型和形状,因此您可以轻松地将任意长度的字符串推在一起,垂直或水平堆叠,但您喜欢它们。
所以考虑 textscan
。您需要实现此函数,该函数将从文件中读取 return 数据。数据可以是数字或字符串。你做什么工作? textscan
正在做的事情:return 数字列作为数组(因为每一行都有一个标量数据),return 字符串作为单元格(因为每一行包含一个字符串,即向量在自身!)。您 可以 水平堆叠字符串,但这仅在给定列中的每一行包含相同数量的字符时才有效,这显然不应假设,也不应规定。您 可以 仍然将字符串填充到最长的元素和 return 堆叠字符数组,但这会在大多数实际应用程序中引入不必要的开销。 (旁注:textscan
return 是一个单元格行向量作为其输出,每个单元格元素包含给定列中的完整数据。对于数字列,此 "full data" 是数组列向量,对于字符串列,它是一个单元格列向量。)
因此 textscan
return 将其字符串列作为单元格是合理的。如果愿意,您自己仍然可以将字符串堆叠到二维字符串数组中,但在大多数情况下这并不实用。这真的取决于您的应用程序。
一个最小的例子:考虑 tmp.inp
包含
asf 3 4
asdg 2 3
asd 1 4
现在
>> fid=fopen('tmp.inp','r'); outcell=textscan(fid,'%s%f%f'), fclose(fid);
outcell =
{3x1 cell} [3x1 double] [3x1 double]
这表明 outcell
的输出是一个单元格行向量,每个元素对应于从文件中读入的列。第 2 列和第 3 列周围的方括号表示这些单元格元素(即 outcell{2}
和 outcell{3}
,不要与 outcell(2)
和 outcell(3)
混淆)是数值数组。但是,第一个元素是单元格列向量:
>> outcell{1}
ans =
'asf'
'asdg'
'asd'
输出在每行上都带有引号,这表明这些是单元格中包含的单独字符串,但您也可以从
中看出这一点
>> whos ans
Name Size Bytes Class Attributes
ans 3x1 356 cell
现在,正如我所说,您可以决定将您的列堆叠在一起,您只需要在您的单元格上调用 char()
:
>> char(outcell{1})
ans =
asf
asdg
asd
>> whos ans
Name Size Bytes Class Attributes
ans 3x4 24 char
注意自动输出中缺少引号,以及输出本身的 class/size。 3x4
大小是通过将所有行填充到最长字符串的大小(即 4)来实现的。因此,输出的第一行和第三行以 space 结尾(这就是我们的意思字符串得到 padded).
如果您不执行此填充,您可以简单地引用读入的字符串作为它们的单元格元素:
>> outcell{1}{3}
ans =
asd
或者,按照您最初的意愿存储变量:
>> compartment_name=outcell{1}
compartment_name =
'asf'
'asdg'
'asd'
>> compartment_name{3}
ans =
asd
我使用 matlab 创建了 .txt 文件,这些文件有不同的 3 列,由制表符(字符串、浮点、浮点)和不同的行数分隔。
我正在尝试将这 3 列数据中的每一列读入 3 个不同的变量。这是我的代码:
fileId = fopen('file.txt');
% Storing columns from txt file into appropriate compartment data arrays
compartment_name = textscan(fileId,'%s%*f%*f','Delimiter','\t'); % column of strings
compartment_length = textscan(fileId,'%*s%f%*f','Delimiter','\t'); % column of doubles
compartment_diameter = textscan(fileId,'%*s%*f%f','Delimiter','\t'); % column of doubles
fclose('file.txt');
我收到 compartment_name 的正确数据(1x1 单元格包含 106x1 单元格(每个单元格都是一个字符串)),但是 compartment_length 和 compartment_diameter return 包含 0x1 双倍的空 1x1 单元格。
有什么想法吗?
还有 - 有什么简单的方法可以将 1x1 单元格转换为数组吗?即对于 compartment_name,它将是一个 1x106 字符串数组 ?
正如@jgrant 指出的那样
我真的不明白你为什么要尝试调用 textscan
三次,textscan
的输出是一个单元格的原因正是你可以调用一次它,然后分隔输出列:
tmpcell = textscan(fileId,'%s%f%f','Delimiter','\t'); % column of strings
compartment_name = tmpcell{1};
compartment_length = tmpcell{2};
compartment_diameter = tmpcell{3};
% or if you want to be fancy about it:
%[compartment_name, compartment_length, compartment_diameter] = tmpcell{:};
我写这个答案的原因是你的最后注释:
Also - is there any easy way for me to convert the 1x1 cells into an array? ie for compartment_name, it would be an array of 1x106 strings ?
这暗示您对 MATLAB 中的字符串感到困惑。在 MATLAB 中,字符串本质上是 整数数组 。您可以通过对字符串执行任何类型的算术运算来亲眼看到这一点:
>> tmpstring = 'asdf'
tmpstring =
asdf
>> tmpstring*1
ans =
97 115 100 102
您看到的数字是字符串中字符的 ASCII 表示形式。这也适用于其他方式:您可以通过将整数放入数组来构建字符串。事实上,就所有意图和目的而言,字符串 是 整数数组:
>> isequal([97 115 100 102],'asdf')
ans =
1
这也暗示了 MATLAB 中字符串的一些限制。你的问题是你不能简单地创建一个字符串数组。那就是字符串连接:如果 string1
和 string2
都只是整数数组,那么 [string1, string2]
就是两个字符串的连接。
然后您可以考虑使用 [string1; string2]
水平堆叠字符串。现在,这与它对两个整数数组的作用完全一样:如果字符串的长度相等(我现在的长度是指size(string1,2)
),你只能这样做。所以在一般情况下,您只能将字符串一起存储在一个非均匀容器中,即 MATLAB 中的单元格。拥有单元格后,您的元素可以具有任何类型和形状,因此您可以轻松地将任意长度的字符串推在一起,垂直或水平堆叠,但您喜欢它们。
所以考虑 textscan
。您需要实现此函数,该函数将从文件中读取 return 数据。数据可以是数字或字符串。你做什么工作? textscan
正在做的事情:return 数字列作为数组(因为每一行都有一个标量数据),return 字符串作为单元格(因为每一行包含一个字符串,即向量在自身!)。您 可以 水平堆叠字符串,但这仅在给定列中的每一行包含相同数量的字符时才有效,这显然不应假设,也不应规定。您 可以 仍然将字符串填充到最长的元素和 return 堆叠字符数组,但这会在大多数实际应用程序中引入不必要的开销。 (旁注:textscan
return 是一个单元格行向量作为其输出,每个单元格元素包含给定列中的完整数据。对于数字列,此 "full data" 是数组列向量,对于字符串列,它是一个单元格列向量。)
因此 textscan
return 将其字符串列作为单元格是合理的。如果愿意,您自己仍然可以将字符串堆叠到二维字符串数组中,但在大多数情况下这并不实用。这真的取决于您的应用程序。
一个最小的例子:考虑 tmp.inp
包含
asf 3 4
asdg 2 3
asd 1 4
现在
>> fid=fopen('tmp.inp','r'); outcell=textscan(fid,'%s%f%f'), fclose(fid);
outcell =
{3x1 cell} [3x1 double] [3x1 double]
这表明 outcell
的输出是一个单元格行向量,每个元素对应于从文件中读入的列。第 2 列和第 3 列周围的方括号表示这些单元格元素(即 outcell{2}
和 outcell{3}
,不要与 outcell(2)
和 outcell(3)
混淆)是数值数组。但是,第一个元素是单元格列向量:
>> outcell{1}
ans =
'asf'
'asdg'
'asd'
输出在每行上都带有引号,这表明这些是单元格中包含的单独字符串,但您也可以从
中看出这一点>> whos ans
Name Size Bytes Class Attributes
ans 3x1 356 cell
现在,正如我所说,您可以决定将您的列堆叠在一起,您只需要在您的单元格上调用 char()
:
>> char(outcell{1})
ans =
asf
asdg
asd
>> whos ans
Name Size Bytes Class Attributes
ans 3x4 24 char
注意自动输出中缺少引号,以及输出本身的 class/size。 3x4
大小是通过将所有行填充到最长字符串的大小(即 4)来实现的。因此,输出的第一行和第三行以 space 结尾(这就是我们的意思字符串得到 padded).
如果您不执行此填充,您可以简单地引用读入的字符串作为它们的单元格元素:
>> outcell{1}{3}
ans =
asd
或者,按照您最初的意愿存储变量:
>> compartment_name=outcell{1}
compartment_name =
'asf'
'asdg'
'asd'
>> compartment_name{3}
ans =
asd