从稀疏矩阵获取向量的最佳方法

发布于 2024-08-29 04:16:25 字数 407 浏览 7 评论 0原文

我有一个 mx n 矩阵,其中每行均由零组成,并且每行的值相同。

例如:

M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0]

在此示例中,第一列由 0-0.6 组成,第二列由 01.8 组成>、第三个-2.3等等。

在这种情况下,我想将 m 减少到 1(从给定矩阵获取向量),因此在本例中向量将是 [-0.6 1.8 -2.3 3.4 -3.8 -4.3]

有谁知道从这样的矩阵中获取向量的最佳方法是什么?

谢谢你!

I have a m x n matrix where each row consists of zeros and same values for each row.

an example would be:

M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0]

In this example the first column consists of 0s and -0.6, second 0 and 1.8, third -2.3 and so on.

In such case I would like to reduce m to 1 (get a vector from a given matrix) so in this example a vector would be [-0.6 1.8 -2.3 3.4 -3.8 -4.3]

Does anyone know what is the best way to get a vector from such matrix?

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

逆夏时光 2024-09-05 04:16:25

这是使用函数 SUM 的单行代码:

nonZeroColumnValues = sum(M)./sum(M ~= 0);

这将返回一个 1×n 向量,其中包含每列中重复的非零值。它通过对每列求和,然后将结果除以每列中非零值的数量来实现。如果列中没有非零值,则该列的结果将为 NaN

以下是在问题中使用示例矩阵 M 的示例:

>> M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0]

M =

   -0.6000    1.8000   -2.3000         0         0         0
         0         0         0    3.4000   -3.8000   -4.3000
   -0.6000         0         0    3.4000         0         0

>> nonZeroColumnValues = sum(M)./sum(M ~= 0)

nonZeroColumnValues =

   -0.6000    1.8000   -2.3000    3.4000   -3.8000   -4.3000

Here's a one-liner that uses the function SUM:

nonZeroColumnValues = sum(M)./sum(M ~= 0);

This will return a 1-by-n vector that contains the repeated non-zero value from each column. It does so by summing each column, then dividing the result by the number of non-zero values in each column. If there are no non-zero values in a column, the result for that column will be NaN.

Here's an example using the sample matrix M in the question:

>> M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0]

M =

   -0.6000    1.8000   -2.3000         0         0         0
         0         0         0    3.4000   -3.8000   -4.3000
   -0.6000         0         0    3.4000         0         0

>> nonZeroColumnValues = sum(M)./sum(M ~= 0)

nonZeroColumnValues =

   -0.6000    1.8000   -2.3000    3.4000   -3.8000   -4.3000
山色无中 2024-09-05 04:16:25

如果存在未知数量的非零和零,解决该问题的一种方法是首先用 NaN 替换零,然后使用 max 或 min 之类的东西来查找数据。

%# create an array
M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0];

%# replace zeros with NaN
M(M==0) = NaN;

%# get, for each column, the number
numbers = max(M,[],1)

numbers =

    -0.6000    1.8000   -2.3000    3.4000   -3.8000   -4.3000

编辑

这就是我对这个问题的理解:
“我希望,对于每一列,都知道非零条目的值。每列只有一个非零数字,但它可能会出现多次”

这是一种更类似于 Matlab(但更长)的方法得到解决方案:

%# create an array
    M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0];

%# find the non-zero entries
[r,c] = find(M);

%# only take one entry per column
[uniqueCols, sortIdx] = unique(c);

%# fix the rows correspondingly
uniqueRows = r(sortIdx);

%# convert to index
idx = sub2ind(size(M),uniqueRows,uniqueCols);

%# get the numbers per column (transpose as needed)
numbers = M(idx)

numbers =

   -0.6000
    1.8000
   -2.3000
    3.4000
   -3.8000
   -4.3000

If there's an unknown number of non-zeros and zeros, one way to fix the problem is to first replace the zeros with NaNs, and then use something like max or min to find the data.

%# create an array
M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0];

%# replace zeros with NaN
M(M==0) = NaN;

%# get, for each column, the number
numbers = max(M,[],1)

numbers =

    -0.6000    1.8000   -2.3000    3.4000   -3.8000   -4.3000

EDIT

This is how I understood the question:
"I want, for every column, to know the value of the non-zero entries. There is only one non-zero number per column, but it could occur multiple times"

Here is a more Matlab-like (but longer) way to get the solution:

%# create an array
    M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0];

%# find the non-zero entries
[r,c] = find(M);

%# only take one entry per column
[uniqueCols, sortIdx] = unique(c);

%# fix the rows correspondingly
uniqueRows = r(sortIdx);

%# convert to index
idx = sub2ind(size(M),uniqueRows,uniqueCols);

%# get the numbers per column (transpose as needed)
numbers = M(idx)

numbers =

   -0.6000
    1.8000
   -2.3000
    3.4000
   -3.8000
   -4.3000
烟雨凡馨 2024-09-05 04:16:25

这实际上不是一个稀疏矩阵。 MATLAB 中的稀疏矩阵就是这样定义的。如果您使用稀疏或 spdiags 函数来定义该矩阵,则不需要存储零元素,只需存储非零元素。当然,MATLAB 知道如何将这些真正的稀疏矩阵与其他标准双精度数组结合使用。

最后,真正的稀疏矩阵通常比这稀疏得多,或者你根本不会费心使用稀疏存储形式。

无论如何,如果您只需要 ANY 矩阵的非零元素,那么您可以这样做:

NZ = M(M ~= 0);

或者,

NZ = M(find(M));

Either 将按列串出非零元素,因为这就是 MATLAB 中数字在矩阵中的存储方式。

NZ = M(find(M))
NZ =
         -0.6
         -0.6
          1.8
         -2.3
          3.4
          3.4
         -3.8
         -4.3

在您的问题中,您询问如何按行执行此操作,提取第一行中的非零元素,然后提取第二行等。

这最简单的方法是首先转置数组。因此,我们可能会做一些类似的事情......

NZ = M.';
NZ = NZ(find(NZ))
NZ =
         -0.6
          1.8
         -2.3
          3.4
         -3.8
         -4.3
         -0.6
          3.4

看看我用过的。进行转置,以防万一任何元素很复杂。

This is NOT actually a sparse matrix. A sparse matrix in MATLAB is defined as such. If you use the sparse or spdiags functions to define that matrix, then the zero elements will not need to be stored, only the non-zeros. Of course, MATLAB knows how to work with these true sparse matrices in conjunction with other standard double arrays.

Finally, true sparse matrices are usually much more sparse than this, or you would not bother to use the sparse storage form at all.

Regardless, if you only want the non-zero elements of ANY matrix, then you can do this:

NZ = M(M ~= 0);

alternatively,

NZ = M(find(M));

Either will string out the non-zeros by columns, because that is how numbers are stored in a matrix in MATLAB.

NZ = M(find(M))
NZ =
         -0.6
         -0.6
          1.8
         -2.3
          3.4
          3.4
         -3.8
         -4.3

In your question, you asked for how to do this by rows, extracting the non-zero elements in the first row, then the second row, etc.

This is most simply done by transposing the array first. Thus, we might do something like...

NZ = M.';
NZ = NZ(find(NZ))
NZ =
         -0.6
          1.8
         -2.3
          3.4
         -3.8
         -4.3
         -0.6
          3.4

See that I used .' to do the transpose, just in case any elements were complex.

好久不见√ 2024-09-05 04:16:25

M = M(M~=0)

M(find(M))

请了解如何为 SO 读者格式化代码。

编辑@Jonas建议OP只需要M中每个非零元素出现一次。要得到这个尝试将上述建议包装在unique()中,例如

unique(M(M~=0))

M = M(M~=0)

or

M(find(M))

and please learn how to format code for SO readers.

EDIT @Jonas suggests that OP wants only one occurrence of each non-zero element from M. To get this try wrapping either of the foregoing suggestions in unique(), such as

unique(M(M~=0))
噩梦成真你也成魔 2024-09-05 04:16:25

如果操作员真的想找到也是唯一的非零元素,那么有比乔纳斯建议的更好的方法。

逻辑解决方案是首先找到非零元素。然后应用unique函数。因此,请执行以下操作:

unique(M(find(M)))

如果您的目标是按特定顺序查找这些元素,那么需要在您的目标中明确定义该顺序。

If the OP REALLY wants to find the non-zero elements that are also unique, then there are far better ways to do so than Jonas suggests.

The logical solution is to find the non-zero elements FIRST. Then apply the function unique. So do this:

unique(M(find(M)))

If your goal is to find those elements in a specific order, then that order needs to be explicitly defined in your goal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文