Dang Khoa
Dang Khoa

Reputation: 5823

MATLAB - how do I (elegantly) interpolate a matrix?

Suppose I have a cell array with 3 elements; the first and third cells are matrices, while the second is empty:

>> P
P = 
  [3x8 double]    []    [3x8 double]

I can fill in the second matrix by interpolating for every individual element in the matrix, but surely there must be a way to do this in one shot?

EDIT: An average would certainly work for P. But suppose I have something like

>> Q
Q = [3x8 double]    [3x8 double]     [3x8 double]    []    []    [3x8 double]

So given my four known matrices, I could use a fancier interpolation (like spline) to fill in the missing matrices.

Upvotes: 2

Views: 5815

Answers (3)

Ansari
Ansari

Reputation: 8218

Something like this will work for your toy case:

l = length(P{1}(:)); m = size(P{1}, 1); n = size(P{1}, 2);
myfun = @(x) interp1([1 3], [P{1}(x) P{3}(x)], 2)
P{2} = reshape(arrayfun(myfun, 1:l), m, n);

More general code (verified!!) that will work in general. You can specify which type of interpolation to use in the one interp1 call:

[m, n] = size(P{1}); l = m*n;
avbl = find(not(cellfun('isempty', P)));
missing = find(cellfun('isempty', P));

extractor = @(k) cellfun(@(x, k) x(k), {P{avbl}}, cellmat(1, length(avbl), 1, 1, k))
myfun = @(x) interp1(avbl, extractor(x), missing)
intermediate = reshape(arrayfun(myfun, 1:l, 'UniformOutput', false), m, n);
ext2 = @(k) cellfun(@(p) p(k), intermediate);
P(missing) = arrayfun(ext2, 1:length(missing), 'UniformOutput', false);

Let me know if you want me to explain some of the parts. It's basically just calling cellfun a few times and then reshaping the output.

Upvotes: 2

Amro
Amro

Reputation: 124563

You can perform all the interpolation in a single function call to INTERP1, but it requires setting the data into the desired shape, then back once done:

%# cell array of matrices (some are missing)
sz = [3 8];         %# all of same size
Q = {ones(sz), [], 3*ones(sz), [], [], 6*ones(sz)};

%# indices of missing matrices
idx = ~cellfun(@isempty,Q);
x = 1:numel(Q);

%# merge cells into a multidimensional matrix, call INTERP1, then divide back
QQ = Q(idx);
QQ = permute(cat(3,QQ{:}), [3 1 2]);
QQ = interp1(x(idx), QQ, x);            %# one call to interpolation function
QQ = reshape(num2cell(permute(QQ, [2 3 1]), [1 2]), 1,[]);

Just keep in mind that vectorization sometimes comes at the cost of readability...

Upvotes: 4

Chris A.
Chris A.

Reputation: 6887

Do you mean:

     p{2} = (p{1} + p{3}) / 2;  % note the curly braces

?

Upvotes: 0

Related Questions