the dimension of matrix when using 'sparse' to generate sparse matrix

91 views (last 30 days)
Why matlab has removed the high dimension operation of sparse?
I used to generate 3D sparse matrix using sparse. However, I find an error message when using this function says: Error using sparse, inputs must be 2-D.
Is this problem solvable?
  3 Comments
Torsten
Torsten less than a minute ago
I've never seen that MATLAB's "sparse" could be applied to N-dimensional arrays with N ~= 2. Can you give a link where this happened ? Do you mean the contribution from the file exchange
?
Walter Roberson
Walter Roberson 1 minute ago
The implementation of sparse() was stable for a quite long time, supporting only logical and double precision 2D matrices. As of R2025a, support was added for single precision matrices. But that's the only change in a long long time.

Sign in to comment.

Answers (3)

Umar
Umar about 19 hours ago
Edited: Umar about 19 hours ago
This answer was flagged by Dyuman Joshi

Hi @li,

I saw your question about MATLAB removing 3D sparse matrix support, and I wanted to help clarify what's happening. Both @Torsten and @Walter Roberson are absolutely correct in their responses to you. MATLAB's native sparse function has actually never supported 3D or N-dimensional arrays. It's always been limited to 2D matrices only, going all the way back to before R2006a.

I know this might be confusing because when you call something like sparse(3, 3, 3), MATLAB doesn't throw an error right away. Instead, it interprets this as the sparse(i, j, v) syntax, where i=3 is the row index, j=3 is the column index, and v=3 is the value. So you end up with a 2D matrix that has a single element at position (3,3) with value 3, not a 3D array at all. This might be why you thought it was working before.

The error message you're seeing now, " Error using sparse, inputs must be 2-D", is actually the function working correctly and enforcing its documented 2D-only limitation. Walter mentioned that the only recent change to sparse was in R2025a, when they added support for single precision matrices alongside the existing double and logical types. That's the first major enhancement in many years, and it had nothing to do with removing any dimensional capabilities.

As Torsten suggested, if you truly need 3D sparse functionality, you'll want to look at the N-dimensional sparse arrays contribution on the MATLAB File Exchange ( https://uk.mathworks.com/matlabcentral/fileexchange/29832-n-dimensional-sparse-arrays ). That's a third-party solution that provides the ndSparse class, which can handle the multidimensional sparse arrays that native MATLAB cannot.

I tested this myself to confirm, and here's some code that demonstrates the 2D limitation:

S1 = sparse(5, 5);
disp('2D sparse matrix created successfully');
disp(S1);
% This also works - 2D sparse with values
i = [1 2 3];
j = [1 2 3];
v = [10 20 30];
S2 = sparse(i, j, v, 5, 5);
disp('2D sparse matrix with values:');
disp(S2);
% This doesn't create 3D - it creates 2D with element at (3,3)
S3 = sparse(3, 3, 3);
disp('This is still 2D:');
disp(['Dimensions: ' num2str(size(S3))]);
disp(['Number of dimensions: ' num2str(ndims(S3))]);
% To truly get the error, try converting a 3D array
try
  A_3D = rand(3, 3, 3);
  S_3D = sparse(A_3D);
catch ME
  disp('Error when trying true 3D:');
  disp(ME.message);
end

Note: please see attached.

Hope this helps clar things up. The functionality you're looking for was never in base MATLAB, so nothing was actually removed. You'll need to use a File Exchange solution for 3D sparse arrays.

  4 Comments
Umar
Umar 30 minutes ago

Hi @Catalytic,

I want to clarify the intent of my answer. My goal was to provide additional value beyond what was already stated by others:

I explicitly demonstrated the difference between sparse(3,3,3) and a true 3D array with a reproducible MATLAB script. This helps users see why MATLAB behaves the way it does.

I included a practical solution using cell arrays of sparse matrices for 3D data, which is not mentioned in the previous comments. I provided links to official documentation and historical MathWorks support, showing that 3D sparse matrices were never supported, which gives authoritative context.

The combination of explanation, demonstration, and practical workaround is meant to be a complete, step-by-step answer to help users understand the limitation and a working alternative.

I hope this clarifies why this answer adds unique value, rather than simply repeating earlier comments.Let me know what is your feedback to @Li comments, could you please contribute your thoughts, we will really appreciate it.

Umar
Umar 3 minutes ago

Note: This answer has been revised in my updated response below, which incorporates technical clarifications from @Walter Roberson.

Sign in to comment.


Umar
Umar about 4 hours ago
Edited: Umar about 1 hour ago

Hi @Li,

After going through recent comments, I wanted to provide a clear explanation of the situation regarding 3D sparse matrices in MATLAB, step by step.

You asked, “Why MATLAB does not support high-dimensional sparse matrices”

Feedback: MATLAB’s `sparse` function has never supported 3D or N-dimensional sparse arrays. Sparse matrices in MATLAB are always 2D (rows × columns). According to MathWorks Support (2009), “MATLAB only supports two-dimensional sparse matrices” [link]( < Mathworks > )

Also, the official `sparse` documentation also only describes 2D usage and makes no mention of N-dimensional variants ([link]( Mathworks )).

Therefore, there was never a “high-dimension operation” to remove; the function was never designed for that.

Edit comments: As @Walter Roberson demonstrated recently, this limitation is fundamental and not related to syntax conflicts:

sparse(ones(2,3,4))
Error using sparse
Inputs must be 2-D.

This definitively shows MATLAB rejects true 3D arrays regardless of the syntax used.

You asked, “Why you see the error “Inputs must be 2-D”

Feedback: When you pass a true 3D array to `sparse`, MATLAB rejects it, because the sparse format is strictly 2D. Even if you try to `reshape` a 1D or 2D sparse matrix into 3D, MATLAB internally flattens the extra dimensions, returning a 2D matrix rather than a true 3D sparse array.

You asked, “Practical solutions to mimic 3D sparse arrays”

Feedback: Since MATLAB cannot natively create 3D sparse matrices, there are two practical approaches:

1. Cell array of 2D sparse slices

You can create a 3D-like structure by storing each 2D slice as a separate sparse matrix inside a cell array. Example discussion here: [link]( Mathworks )

2. Use third-party N-D sparse implementations

The MATLAB File Exchange has a solution called `ndSparse` for true N-dimensional sparse arrays: [link]( < ndSparse > ) as already suggested by @Torsten in his comments section.

Demonstration Script

%% Step 1: Error for a true 3D array
try
  A_3D = rand(3,3,3);
  S_3D = sparse(A_3D);
catch ME
  disp('Error for true 3D array:');
  disp(ME.message);
end
%% Step 2: sparse(3,3,3) creates 2D matrix
S = sparse(3,3,3);
disp('Size of sparse(3,3,3):');
disp(size(S));
disp('Number of dimensions:');
disp(ndims(S));
%% Step 3: Mimic 3D sparse matrix with cell array
nSlices = 3;  
slices = cell(1,nSlices);
for k = 1:nSlices
  slices{k} = sparse(rand(3,3));  % 2D sparse slice
end
disp('Slice 3:');
disp(slices{3});
% Access an element
val = slices{2}(2,3);
disp(['Element (2,3) in slice 2: ', num2str(val)]);

Results: please see attached

Explanation: * True 3D array —> error: “Inputs must be 2‑D” * sparse(3,3,3) —> creates a 2D sparse matrix * Cell array —> successfully mimics a 3D sparse structure

This explanation is chronological and addresses both of your questions:

1. MATLAB never supported high-dimensional sparse matrices (so nothing was removed). 2. You can practically work around the 2D limitation using cell arrays or the “ndSparse” class.

Hope this clarifies everything and provides a concrete solution. If you need further assistance, please let us know.

  2 Comments
Walter Roberson
Walter Roberson 4 minutes ago
Although sparse(rows, columns, pages) does not work, hypothetically the prime syntax sparse(A) could work for 3D A. But it does not work.
sparse(ones(2,3,4))
Error using sparse
Inputs must be 2-D.
This does not rely upon syntax conflicts, which themselves do not prove the point.
Umar
Umar 7 minutes ago

Thank you @Walter Roberson for that crucial clarification. You're absolutely right— the sparse(ones(2,3,4)) example definitively demonstrates the 2D limitation without any syntax ambiguity. This is a much cleaner and more rigorous proof than my sparse(3,3,3) explanation.

I genuinely appreciate you taking the time to provide this correction, and I always respect and value your expertise in helping the MATLAB community understand these technical details correctly.

Sign in to comment.


li
li about 4 hours ago
I used to generate matrix like H=rand(8,8,20); and then i would like to use this 3D matrix to generate an block diagonal matrix using blkdiag(H(8,8,:)), or generate a sparse bolck diagonal matrix using spblkdiag provided by Rody Oldenhuis . Recently, I have reused my code to do calculations, however, this command cannot function any more. So I wounder if matlab has removed this function or changed it.
The version of my last used matlab software is about 2017b. However, I can't use my program in the new 2025a software.
Or maybe I have added the ndSparse funtion in my old software and I forgeted it.
I will try it and report the feedbacks.
Thanks for all of your help.
  7 Comments
Umar
Umar about 1 hour ago

@Li - MATLAB's tril() and sparse() functions have never supported 3D arrays, so nothing was actually removed between 2017b and 2025a. I would like a second opinion from @Walter and @Torsten who are experts and do respect their opinions always in the post. It might be you had the ndSparse toolbox installed back then and forgot about it. For your specific problem, you need to apply tril to each 8×8 page individually using a loop, and for the block diagonal creation, the issue with H(8,8,:) is that it extracts only single elements (giving you 1×1×20) rather than the full pages—you need to use num2cell(H, [1 2]) to convert each page to a cell, then pass that to blkdiag. I've put together working code (took some time to implement to help you out) in the artifact below that includes tril3d() and blkdiag3d() utility functions that handle this correctly, and everything works fine with complex doubles (the built-in blkdiag has always supported complex matrices, so if you're getting an error about that, check "which blkdiag -all" to see if a custom function is shadowing the built-in). The code demonstrates the correct approach for your 8×8×20 case and creates the sparse block diagonal matrix you need.

Here is the code

% Solution for Li's 3D matrix problem
% Problem: tril() doesn't work on 3D arrays, block diagonal syntax 
%issues
%% Your immediate problem - applying tril to 3D matrices
% your data (8x8 pages, 20 deep, complex)
H = rand(8,8,20) + 1i*rand(8,8,20);
fprintf('Starting with %dx%dx%d complex matrix\n', size(H,1), 
size(H,2),   
size(H,3));
% tril doesn't accept 3D - you have to loop through pages
% there's no built-in function for this unfortunately
H_lower = zeros(size(H), 'like', H);  % pre-allocate (keeps it 
complex)
for i = 1:size(H,3)
  H_lower(:,:,i) = tril(H(:,:,i));
end
fprintf('Applied tril to all %d pages\n', size(H,3));
% quick check that it worked
if nnz(triu(H_lower(:,:,1), 1)) == 0
  fprintf('Looks good - upper triangles are zero\n');
end
%% Block diagonal - THIS is probably where your syntax was wrong
% WRONG WAY (what you might have tried):
% BD = blkdiag(H(8,8,:))  % <- this extracts single elements!
% The problem: H(8,8,:) gives you a 1x1x20 array of just the (8,8)  
%elements You need the full 8x8 pages
% RIGHT WAY:
pages = num2cell(H_lower, [1 2]);  % converts each page to a cell
BD = blkdiag(pages{:});             % now this works correctly
fprintf('\nBlock diagonal created: %dx%d\n', size(BD,1), size(BD,2));
% convert to sparse if you want
BD_sparse = sparse(BD);
sparsity = 100 * (1 - nnz(BD_sparse)/numel(BD_sparse));
fprintf('Sparse version is %.1f%% sparse\n', sparsity);
% verify it's still complex
if ~isreal(BD_sparse)
  fprintf('Complex values preserved: %.3f%+.3fi (sample)\n', ...
      real(full(BD_sparse(1,1))), imag(full(BD_sparse(1,1))));
end
%% Utility functions you can reuse
% I made these into functions so you don't have to write loops every 
%time
function result = tril3d(A, k)
  % apply tril to each page of a 3D array
  % usage: result = tril3d(A) or result = tril3d(A, k) for diagonal 
  %offset
    if nargin < 2
        k = 0;  % main diagonal by default
    end
    result = zeros(size(A), 'like', A);
    for i = 1:size(A,3)
        result(:,:,i) = tril(A(:,:,i), k);
    end
  end
function result = triu3d(A, k)
  % same thing but for upper triangular
    if nargin < 2
        k = 0;
    end
    result = zeros(size(A), 'like', A);
    for i = 1:size(A,3)
        result(:,:,i) = triu(A(:,:,i), k);
    end
  end
function BD = blkdiag3d(A, make_sparse)
  % creates block diagonal from 3D array pages
  % usage: BD = blkdiag3d(A) or BD = blkdiag3d(A, true) for sparse
    if nargin < 2
        make_sparse = false;
    end
    pages = num2cell(A, [1 2]);
    BD = blkdiag(pages{:});
    if make_sparse
        BD = sparse(BD);
    end
  end
%% Test the utility functions
fprintf('\n--- Testing utility functions ---\n');
test_data = rand(4,4,5) + 1i*rand(4,4,5);
% test tril3d
lower = tril3d(test_data);
fprintf('tril3d: processed %dx%dx%d -> check upper triangle: ',   
size(test_data));
if nnz(triu(lower(:,:,1),1)) == 0
  fprintf('pass\n');
else
  fprintf('fail\n');
end
% test triu3d  
upper = triu3d(test_data);
fprintf('triu3d: processed %dx%dx%d -> check lower triangle: ',   
size(test_data));
if nnz(tril(upper(:,:,1),-1)) == 0
  fprintf('pass\n');
else
  fprintf('fail\n');
end
% test blkdiag3d
bd_test = blkdiag3d(test_data);
fprintf('blkdiag3d: created %dx%d block diagonal\n', size(bd_test));
% with sparse option
bd_sparse_test = blkdiag3d(test_data, true);
fprintf('blkdiag3d (sparse): %d nonzeros out of %d elements\n', ...
  nnz(bd_sparse_test), numel(bd_sparse_test));
%% Complete workflow example with your dimensions
fprintf('\n--- Complete example with your 8x8x20 case ---\n');
% generate data
H_example = rand(8,8,20) + 1i*rand(8,8,20);
% apply lower triangular
H_example_lower = tril3d(H_example);
% create sparse block diagonal
BD_example = blkdiag3d(H_example_lower, true);
fprintf('Input: %dx%dx%d complex matrix\n', size(H_example));
fprintf('Output: %dx%d sparse matrix\n', size(BD_example));
fprintf('Nonzeros: %d (%.2f%% full)\n', nnz(BD_example), ...
  100*nnz(BD_example)/numel(BD_example));
% check memory usage
mem_full = 8 * 160 * 160 * 2;  % bytes for complex double
mem_sparse = whos('BD_example').bytes;
fprintf('Memory: full would be %.1f MB, sparse is %.1f MB\n', ...
  mem_full/1e6, mem_sparse/1e6);
%% Common mistakes to avoid
fprintf('\n--- Common mistakes ---\n');
H_mistake = rand(8,8,20);
% Mistake 1: wrong indexing
wrong = H_mistake(8,8,:);
fprintf('H(8,8,:) gives size %dx%dx%d <- extracts SINGLE ELEMENTS\n',   
size(wrong));
correct = num2cell(H_mistake, [1 2]);
fprintf('num2cell(H,[1 2]) gives %d cells of %dx%d each <- THIS is   
what you want\n', ...
length(correct), size(correct{1}));
% Mistake 2: trying tril on 3D directly
fprintf('\nDirect tril(3D_array) will fail:\n');
try
  bad = tril(H_mistake);
  fprintf('  No error? Unexpected.\n');
catch ME
  fprintf('  Error: %s\n', ME.message);
  fprintf('  Solution: use tril3d() or loop through pages\n');
end
% Mistake 3: sparse on 3D
fprintf('\nDirect sparse(3D_array) will fail:\n');
try
  bad = sparse(H_mistake);
  fprintf('  No error? Unexpected.\n');
catch ME
  fprintf('  Error: %s\n', ME.message);
  fprintf('  Solution: create block diagonal first, then sparse 
it\n');
end
fprintf('\n--- Done ---\n');
fprintf('Copy the utility functions (tril3d, triu3d, blkdiag3d) to use
in your code\n');

Results: please see attached

Let me know how it goes.

Walter Roberson
Walter Roberson 22 minutes ago
R2017b
>> z1=ones(3,3,3); tril(z1)
Error using tril
First input must be 2D.
So R2017b did not support tril of 3D matrices.
R2025b:
>> blkdiag((1:5)+(1:5)*1i)
ans =
Columns 1 through 3
1 + 1i 2 + 2i 3 + 3i
Columns 4 through 5
4 + 4i 5 + 5i
Notice there is no error about generating complex block diagonals.

Sign in to comment.

Categories

Find more on Sparse Matrices in Help Center and File Exchange

Products


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!