Can I take data while setting them

3 views (last 30 days)
I am trying to select the 2nd and 3rd column of a 4x4 rand matrix but I want to do it in one command
a=rand(4);
b=a(:,2:3);
disp(b)
Above is the obvious way of doing it, but I am wondering if it's possible for some correct version of this to exist:
b=rand(4)(:,2:3)
Obviously the line above is written "wrong", I just wanted to paint a picture
  1 Comment
Arif Hoq
Arif Hoq on 31 Jan 2022
a=rand(4);
b=a(:,2:3);
disp(b)
0.0827 0.2787 0.5218 0.1236 0.8095 0.3440 0.7532 0.5671
try it
b=a(:,2:3)
b = 4×2
0.0827 0.2787 0.5218 0.1236 0.8095 0.3440 0.7532 0.5671

Sign in to comment.

Accepted Answer

Yongjian Feng
Yongjian Feng on 31 Jan 2022
Not sure how useful the command you proposed is.
  • If you create first a=rand(4) and then take 8 of them as a(:,2:3), the rest 8 you created in a are still there for you to use later, if you want to. In other words, it makes sense that you first create 16 random numbers and then use 8 of them (first).
  • For the way you propose, b=rand(4)(:, 2:3), b only stores 8 out of 16 random numbers rand(4) creates. The rest 8 of them are created and then destroyed right the way. Then what is the point here to create them? Why not just b=rand(4,2) directly?

More Answers (1)

John D'Errico
John D'Errico on 31 Jan 2022
Edited: John D'Errico on 31 Jan 2022
I'll write this as an answer, intead of a comment on @Yongjian Feng's excellent response, as otherwise my thought can become lost in the thread of comments.
I've seen this request before. But the point made by @Yongjian Feng is correct. Creating something to then dipose of most of it immediately seems silly. Better to just create what you really want anyway.
However, I could see a case where it might be of value. For example, supose I wanted to compute a set of uniformly distributed random numbers such that the sum is 1. We know how to do this in general, a good tool for it is randfixedsum on the file exchange.
For example:
randfixedsum(5,3,1,0,1)
ans =
0.47946 0.07333 0.020025
0.3808 0.087437 0.44272
0.0021769 0.038825 0.17867
0.082437 0.75576 0.17091
0.055123 0.044651 0.18768
So set of 3 numbers as rows of the result, where each row sums to exactly 1, yet the individual elements are uniformly distributed. This tool uses a valid method for that purpose. But suppose we wanted to generate only the first two elements of those sets? Thus, for whatever purpose we might have, we need only the first two columns? Honestly, I can't think of a god reason why. But the first two columns are NOT something trivially created using rand. In fact, they have a subtly differetn distribution. And while with some effort, I could come up with a way to generate a similar set of numbers that yields only the first two columns, suppose I do not understand the mathematics involved? All I need are those first two columns. Another simple example might be that I need only the fitst two rows of the result of magic(5).
Ok, those examples may seem trivial, and even wildly silly. I have no idea why I might do those things. But here is a better example, where I really do use aonly part of a useful result.
Suppose I have a time series.
n = 200;
y = sin((1:n)/10) + randn(1,n)/10;
plot(1:n,y,'.')
I'd like to compute a derivative estimate of that seies at each point, using a moving filter, based on the dirivative of a local cubic polynomial fit to 7 points in a window. So fit a cubic polynomial in a moving sence, then report only the first derivative of that polynomial. No problem. My solution is to use pinv like this:
V = (-3:3)';
M = V.^(0:3);
K = pinv(M);
K = K(2,:)
K = 1×7
0.0873 -0.2659 -0.2302 -0.0000 0.2302 0.2659 -0.0873
So take the second row of the psuedo-inverse of the matrix M. This vector K is the convoluution kernel I want to employ. Thus:
dydx = conv(y,K,'valid');
plot(4:197,dydx,'.')
These are the least squares estimates of the slopy of the curve y at those points. And what I effectively wanted to do was to write K as
K = pinv(M)(2,:);
without an intermediate step, where the result of pinv is created nd saved as a variable. But I cannot do that in MATLAB. And there are probably good reasons why not. But occasoinally, we all see similar things happen. Now, in fact, since I understand the pseudo-inverse code, I could write it more directly using the svd(M). But suppose I did not? Or suppose this was a yet less trivial computation, where the result was something I could not easily perform in some alternative way?
So, yes, I concur that what has been requested is not valid to do in MATLAB. but every once in a while, we all have a hankering for something like it. One simple solution is to write a wrapper code. that will extract only the row I wanted. So....
row2 = @(X) X(2,:);
K = row2(pinv(M))
K = 1×7
0.0873 -0.2659 -0.2302 -0.0000 0.2302 0.2659 -0.0873
And that does as directed, and in reality, it creates the entire array, then throws most of it in the bit bucket. But even if I could move this back a step, with a construct as is wanted,
K = pinv(M)(2,:);
that entire array really was created, and implicitly returned, but then the parser says, hey! he only wants the second row.
Suppose we could do exactly that in MATLAB? I.e., tell the parser to take the result of pinv, but now only return the 2nd row of the matrix? What you should understand is that still, at some level, the entire array was still generatd as a result of pinv, but then the 2nd row was extracted. Even so, we still had to do all the work to create it.
And that means the quasi-kludge solution of a wrapper like the function row2 I wrote is just as good, and does not require me to rewrite the MATLAB parser to accept a completely new syntax.

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!