使用向量从元胞数组中提取数据并转换为数组
Extract data from a Cell Array using a vector and converting into an array
我有一个单元格数组 [5x1],其中所有单元格都是列向量,例如:
exInt =
[46x1 double]
[54x1 double]
[40x1 double]
[51x1 double]
[ 9x1 double]
我需要一个向量 (vec),其中包含我需要提取的 extInt 中的单元格,然后我必须将它们转换为单列数组。如:
vec = [1,3];
Output = cell2mat(extInt{vec})
输出应该变成数组[86x1 double]。
我的编码方式是:
Error using cell2mat
Too many input arguments.
如果可能的话,我想要一个不使用循环的解决方案。
您的代码中有一个小错误
改变
Output = cell2mat(extInt{vec});
到
Output = cell2mat(extInt(vec));
对于单元格,方括号和圆括号都可以用来获取信息。您可以阅读更多相关内容 here,但总结一下:
- Use curly braces {} for setting or getting the contents of cell arrays.
- Use parentheses () for indexing into a cell array to collect a subset of cells together in another cell array.
在您的示例中,使用括号和索引向量 vec
将产生 2 个单独的输出(我在下面制作了 extInt
的较短版本)
extInt = {[1],[2 3],[4 5 6]};
extInt{vec}
ans =
1
ans =
4 5 6
由于这是 2 个独立的输出,因此它也将是函数 cell2mat
的 2 个独立输入。由于此函数仅需要一个输入,因此您会收到一个错误。
一种替代方案是您自己的解决方案。获取两个输出并将它们放在一个新的(未命名的)单元格中
{extInt{vec}}
ans =
[1] [1x3 double]
现在,这个(单个)结果毫无问题地进入 cell2mat
。
(请注意,您可能需要先转置结果,具体取决于单元格中是否有列向量或行向量。要组合的大小向量(或矩阵)需要 match/align。)
另一种使用括号的方法(如我上面的解决方案)。这里原始单元格的一个子集是 return。因此它直接进入 cell2mat
函数。
extInt(vec)
ans =
[1] [1x3 double]
我一直在胡思乱想,我通过将这个条目转换成一个新的元胞数组并转置它来使这个工作正常进行,这样维数对于连接过程来说仍然是相等的
Output = cell2mat({extInt{vec}}')
使用
Output = cell2mat(extInt(vec))
因为您要处理 extInt
中的单元格而不是单元格的内容
extInt(vec)
extInt{vec}
尝试一下看看发生了什么
此处最好的方法是使用由 {}
索引创建的 cat
along with a comma-separted list 来生成预期的列向量。我们将第一个维度指定为第一个参数,因为您拥有所有列向量并且我们希望输出也是一个列向量。
out = cat(1, extInt{vec})
根据您的输入,cell2mat
尝试沿着 第二维 进行连接,这对您的数据来说会失败,因为所有数据都具有不同的行数。这就是为什么(在您的示例中)您必须在调用 cell2mat
.
之前转置数据的原因
更新
这是比较 cat
和 cell2mat
方法执行时间的基准。
function benchit()
nRows = linspace(10, 1000, 100);
[times1, times2] = deal(zeros(size(nRows)));
for k = 1:numel(nRows)
rows = nRows(k);
data = arrayfun(@(x)rand(randi([10, 50], 1), 1), 1:rows, 'uni', 0);
vec = 1:2:numel(data);
times1(k) = timeit(@()cat_method(data, vec));
data = arrayfun(@(x)rand(randi([10, 50], 1), 1), 1:rows, 'uni', 0);
vec = 1:2:numel(data);
times2(k) = timeit(@()cell2mat_method(data, vec));
end
figure
hplot(1) = plot(nRows, times1 * 1000, 'DisplayName', 'cat');
hold on
hplot(2) = plot(nRows, times2 * 1000, 'DisplayName', 'cell2mat');
ylabel('Execution Times (ms)')
xlabel('# of Cell Array Elements')
legend(hplot)
end
function out = cat_method(data, vec)
out = cat(1, data{vec});
end
function out = cell2mat_method(data, vec)
out = cell2mat(data(vec)');
end
两者之间不断偏移的原因是 cell2mat
在内部调用 cat
但在其之上添加了一些额外的逻辑。如果您直接使用 cat
,就可以避免额外的开销。
我有一个单元格数组 [5x1],其中所有单元格都是列向量,例如:
exInt =
[46x1 double]
[54x1 double]
[40x1 double]
[51x1 double]
[ 9x1 double]
我需要一个向量 (vec),其中包含我需要提取的 extInt 中的单元格,然后我必须将它们转换为单列数组。如:
vec = [1,3];
Output = cell2mat(extInt{vec})
输出应该变成数组[86x1 double]。
我的编码方式是:
Error using cell2mat
Too many input arguments.
如果可能的话,我想要一个不使用循环的解决方案。
您的代码中有一个小错误
改变
Output = cell2mat(extInt{vec});
到
Output = cell2mat(extInt(vec));
对于单元格,方括号和圆括号都可以用来获取信息。您可以阅读更多相关内容 here,但总结一下:
- Use curly braces {} for setting or getting the contents of cell arrays.
- Use parentheses () for indexing into a cell array to collect a subset of cells together in another cell array.
在您的示例中,使用括号和索引向量 vec
将产生 2 个单独的输出(我在下面制作了 extInt
的较短版本)
extInt = {[1],[2 3],[4 5 6]};
extInt{vec}
ans =
1
ans =
4 5 6
由于这是 2 个独立的输出,因此它也将是函数 cell2mat
的 2 个独立输入。由于此函数仅需要一个输入,因此您会收到一个错误。
一种替代方案是您自己的解决方案。获取两个输出并将它们放在一个新的(未命名的)单元格中
{extInt{vec}}
ans =
[1] [1x3 double]
现在,这个(单个)结果毫无问题地进入 cell2mat
。
(请注意,您可能需要先转置结果,具体取决于单元格中是否有列向量或行向量。要组合的大小向量(或矩阵)需要 match/align。)
另一种使用括号的方法(如我上面的解决方案)。这里原始单元格的一个子集是 return。因此它直接进入 cell2mat
函数。
extInt(vec)
ans =
[1] [1x3 double]
我一直在胡思乱想,我通过将这个条目转换成一个新的元胞数组并转置它来使这个工作正常进行,这样维数对于连接过程来说仍然是相等的
Output = cell2mat({extInt{vec}}')
使用
Output = cell2mat(extInt(vec))
因为您要处理 extInt
中的单元格而不是单元格的内容
extInt(vec)
extInt{vec}
尝试一下看看发生了什么
此处最好的方法是使用由 {}
索引创建的 cat
along with a comma-separted list 来生成预期的列向量。我们将第一个维度指定为第一个参数,因为您拥有所有列向量并且我们希望输出也是一个列向量。
out = cat(1, extInt{vec})
根据您的输入,cell2mat
尝试沿着 第二维 进行连接,这对您的数据来说会失败,因为所有数据都具有不同的行数。这就是为什么(在您的示例中)您必须在调用 cell2mat
.
更新
这是比较 cat
和 cell2mat
方法执行时间的基准。
function benchit()
nRows = linspace(10, 1000, 100);
[times1, times2] = deal(zeros(size(nRows)));
for k = 1:numel(nRows)
rows = nRows(k);
data = arrayfun(@(x)rand(randi([10, 50], 1), 1), 1:rows, 'uni', 0);
vec = 1:2:numel(data);
times1(k) = timeit(@()cat_method(data, vec));
data = arrayfun(@(x)rand(randi([10, 50], 1), 1), 1:rows, 'uni', 0);
vec = 1:2:numel(data);
times2(k) = timeit(@()cell2mat_method(data, vec));
end
figure
hplot(1) = plot(nRows, times1 * 1000, 'DisplayName', 'cat');
hold on
hplot(2) = plot(nRows, times2 * 1000, 'DisplayName', 'cell2mat');
ylabel('Execution Times (ms)')
xlabel('# of Cell Array Elements')
legend(hplot)
end
function out = cat_method(data, vec)
out = cat(1, data{vec});
end
function out = cell2mat_method(data, vec)
out = cell2mat(data(vec)');
end
两者之间不断偏移的原因是 cell2mat
在内部调用 cat
但在其之上添加了一些额外的逻辑。如果您直接使用 cat
,就可以避免额外的开销。