【问题标题】:Cell array or matrix for different element's sizes per iteration每次迭代不同元素大小的元胞数组或矩阵
【发布时间】:2012-11-21 01:20:48
【问题描述】:

没有代码只是视觉上的:

Iteration i              result j1                  result j2
     1                   10 15 20 15 25                2 
     2                   5                             8
     .                   . . .                         .
     .                   . . . . . .                   .
     i           j1 with length(x), x=0:100        j2 with length == 1

编辑以获得更好的表现:

                [10 15 20 15 25]          [1]                (i=1)
                [5]                       [2]                (i=2)
Matrix(i) = [   [. . . . . . . ]          [3]          ]
                [..]                      [.]
                [j1 = size (x)]     [j2 size 1 * 1]          (i=100)

so Matrix dimension is: i (rows) * 2 (columns) 

(p.e for i = 1, j1 with size(x) column 1 on row 1, j1 size (1) column 2 on row 1)

我想将每个迭代结果保存到一个矩阵中,以便使用它们进行比较。 这可以用矩阵完成还是用单元格数组更好,请写一个例子供参考。

提前致谢。

【问题讨论】:

  • 对不起,我真的无法得到什么是随机的,什么不是,这里。您的迭代依赖是否相互依赖?如果您将它们称为迭代,则可能存在i-th 值对前一个值的确定性依赖性,因此您需要循环。否则,如果没有耦合并且一切都是随机的,那么在我看来这只是矩阵整形的问题。不是吗?
  • 矩阵整形是个问题,因为迭代是独立的。你能告诉我你的重塑方式吗?谢谢。
  • 请考虑我给你的答案。我在那里表达了我的观点。

标签: matlab matrix cell-array


【解决方案1】:

我会使用cell 数组来实现更简洁、更直观、约束更少的实现。

nIterations = 500;
J = cell(nIterations, 2);
for i=1:nIterations
    length_x = randi(100); % random size of J1
    J{i,1} = randi(100, length_x, 1); % J1
    J{i,2} = randi(i); % J2
end

此外,您还可以获得一些额外的好处,例如:

  • 访问元胞数组中的元素

    J{10, 1}; J{10, 2};

  • 在每个元素内追加/修改而不改变整体结构

    J{10, 1} = [J{10, 1}; 0]

  • 追加到数组(添加迭代),就像在普通数组中一样

    J{end+1, 1} = 1; J{end, 2} = 1

  • 在每个条目(向量)中应用函数,使用cellfun

    length_J = cellfun(@length, J); % 得到 J1 的数量/长度
    mean_J = cellfun(@mean, J); % 得到 J1 的平均值

【讨论】:

  • 我先走这条路。谢谢。
【解决方案2】:

编辑:滚动到分析进行比较。 (这使得单元实现获胜。)


您可以使用具有i 行和 101 列的矩阵(前 100 列中的 j1 的值,必要时用 NaNs (*) 填充,然后是 j2 的值), 因此,鉴于它是一个明确的表示,因此您可以进行简单的比较。也就是说,使用 101 列可以确保 j1 不以 NaN 结尾。

(*){NaN 或 0,取决于哪个更方便}

您也可以做 102 列,其中第一列给出 j1 的 长度,然后是 j1 的值,然后是 NaN,然后​​是 j2 的值。
j1=[3 1 10 5]j2=2,那么对应的行就是[4 3 1 10 5 NaN ... NaN 2]

这种矩阵方法的好处是

  • 它应该比单元格更快(在不太多的行上),因为 Matlab 非常擅长处理固定大小的矩阵。
  • 此外,基本操作(如比较)更易于编程。 (你只需要比较两个向量,你可以在同一行进行多次比较。)

矩阵方法的倒退是

  • 您不能轻易地追加到 j1(好吧,当您执行 102 列方法时会更容易一些),
  • j1 的大小有限制。 (在本例中为 100。)

总而言之,单元格通常速度较慢,编程时间可能更长,但更灵活。
我希望这能为您指明正确的方向。

编辑:

使用 2 个矩阵的第三种方法:

j1results = zeros( n_iterations, maxlen_j1 );
j2results = zeros( n_iterations, 1);

然后计算如下:

[j1results(k,:), j2results(k)] = compute(k);

其中的计算是一个返回两个不同值的函数。


分析:

function [J1,J2] = compute(k)
    J1 = zeros(1,100); %this is necessary
    % some dummy assignments
    len = randi(100,1);
    J1(1:len) = k*ones(1,len);
    J2 = k;
end

function res = compute_cell(k) % for the cell-solution
    res = cell(1,2);
    len = randi(100,1);
    res{1} = k*ones(1,len);
    res{2} = k;
end

n=100000;

tic;
J12 = cell(n,2);
for i=1:n
    J12{i}=temp_cell(i);
end
toc

tic;
J1 = zeros(n,100);
J2 = zeros(n,1);
for i=1:n
    [J1(i,:), J2(i)] = temp(i);
end
toc

结果:

Elapsed time is 2.437634 seconds.
Elapsed time is 2.741491 seconds.

(还使用UNI[50,100]len 分布进行了剖析,其中分配不必要的内存空间的矩阵实现的缺点将不那么显着,图片保持不变。)

底线:令人惊讶的是,分析表明单元实现在各个方面都优于矩阵实现

【讨论】:

  • 您的回答已被理解。您可以为每次迭代的不同 j1 的预定义零矩阵编写一个简单的代码吗? matrix =zeros(length(j1), 1) 就足够了吗?
  • 如果您只想从函数返回结果,您的 101 类型矩阵应该是 matrix = zeros(maxlen_of_j1+1, num_iterations)zeros(maxlen_of_j1+1, 1)。然后你可以在第 k 次迭代中分配matrix(k,:) = result(k)
  • 糟糕,我做错了,这是正确的版本:如果您只想从函数返回结果,您的 101 类型矩阵应该是 matrix = zeros(num_iterations, maxlen_of_j1+1)zeros(1, maxlen_of_j1+1)。然后你可以在第 k 次迭代中分配matrix(k,:) = result(k)
  • 我检查了你的答案,它返回:“索引不能产生多个结果”。你能澄清一下吗?
  • 这是我在矩阵定义上的错误。感谢您的教育帖子。
【解决方案3】:

从您的图形表示中可以看出您需要一个2xN_Rows 结构,它没有常规模式(确实有一种随机性 em> 在其中)因此您必须以支持这种不规则性的方式存储您的数据。因此,正如其他人所说,cells 是自然的解决方案。

据我所知,您需要在矩阵中插入的元素虽然是随机的,但彼此独立,因此您仍然可以富有成效地矢量化

您有2 相互独立的随机贡献:

  1. 结构第一列中的元素数量是随机的。

  2. 结构中的元素是随机的;

让我们分别考虑贡献:

  1. 您有N_Rows,其中包含可变数量的元素。假设在最坏的情况下有N_El(即N_El 是每行条目数量的上限)。让我们生成每行的元素数

     elem_N = randi(`N_El` , [N_Rows 1]);
    
  2. 您必须准确生成 sum(elem_N) 随机数(对于第 2 点),这些随机数将在根据 elem_N 分区后分布在各行中。

这是我建议的最终代码

N_ROW = 20;
N_EL = 10;    
MAX_int = 20; %maximum random integer in each row

elem_N = randi(N_EL,[N_ROW , 1]);         % elements per line stochasticity
elements = randi(MAX_int, [1 sum(elem)]); % elements value stochasticity

     %cutoff points of the vector "elements" among the rows of the structure
cutoffs = mat2cell(...
     [[1 ; cumsum(elem_N(1:end-1))] cumsum(elem_)]... 
     ,ones(N_ROW,1),[2]);



    %result:
res = [cellfun(@(idx) elements( idx(1):idx(2) ) , cutoffs , 'UniformOutput', false ) ,...
     num2cell( randi(MAX_int,[1 N_ROW])')];

结果

 res = 

[1x9  double]    [20]
[1x3  double]    [12]
[1x5  double]    [ 7]
[1x8  double]    [20]
[1x11 double]    [18]
[1x7  double]    [ 4]
[1x11 double]    [ 1]
[1x4  double]    [15]
[1x5  double]    [18]

在哪里

  res{1,1}

ans =

    15    13     2     3    20    10     1     2     3


res{2,1}

 ans =

 3    18    10

等等……

【讨论】:

  • 好吧,我现在明白了。好好的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-20
  • 2014-05-25
  • 2015-07-29
  • 1970-01-01
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
相关资源
最近更新 更多