(X^2)(1,2)
X is a square matrix, I just want to get the element from position (1,2) from (X^2) why it does not work?
Indexing is syntactically not allowed in this case. The simplest workaround is to use getfield
X=magic(5)
X =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
>> getfield(X^2,{1,3})
ans =
725
That's not how Matlab works. You need to assign the result of the matrix multiplication to another matrix, then use it:
A = X^2;
disp(A(1,2));
This is assuming that you really did mean to do matrix multiplication, and not multiply element by element. In the latter case you could have done
disp(X(1,2)^2)
And if you are interested in matrix multiplied result, then
disp(X(1,:)*X(:,2))
will do it, since that is how element (1,2) is calculated. This last solution has the advantage of being very efficient since you only calculate the element you need, instead of computing the entire matrix and throwing N^2-1 elements away just to keep the one. For bigger matrices that will make a difference. Of course it makes the code slightly less readable so I would always recommend writing a comment in your code when you do that - your future self will thank you...
edit take a look at http://www.mathworks.com/matlabcentral/newsreader/view_thread/235798 - that thread broadly agrees with my first statement, although it hints that the syntax you desire might be "part of a future release". But that was said 6 years ago, and it's still not here... It also shows some pretty obscure workarounds; I recommend not going that route (because all the workarounds do is hide the fact that you compute the matrix, then pick just one element. So the workload on the computer is no smaller.)
Related
In something which made me spent several hours, I have found an inconsistency in how Matlab deals with dimensions. I somebody can explain to me OR indicate me how to report this to Matlab, please enlight me.
For size, ones,zeros,mean, std, and most every other old and common commands existing inside Matlab, the dimension arrangement is like the classical one and like the intended standard (as per the size of every dimension), the first dimension is along the column vector, the second dimension is along the row vector, and the following are the non graphical following indexes.
>x(:,:,1)=[1 2 3 4;5 6 7 8];
>x(:,:,2)=[9 10 11 12;13 14 15 16];
>m=mean(x,1)
m(:,:,1) = 3 4 5 6
m(:,:,2) = 11 12 13 14
m=mean(x,2)
m(:,:,1) =
2.5000
6.5000
m(:,:,2) =
10.5000
14.5000
m=mean(x,3)
m = 5 6 7 8
9 10 11 12
d=size(m)
d = 2 4 2
However, for graphical commands like stream3,streamline and others relying on the meshgrid output format, the dimensions 1 and 2 are swapped!: the first dimension is the row vector and the second dimension is the column vector, and the following (third) is the non graphical index.
> [x,y]=meshgrid(1:2,1:3)
x = 1 2
1 2
1 2
y = 1 1
2 2
3 3
Then, for stream3 to operate with classically arranged matrices, we should use permute(XXX,[2 1 3]) at every 3D argument:
xyz=stream3(permute(x,[2 1 3]),permute(y,[2 1 3]),permute(z,[2 1 3])...
,permute(u,[2 1 3]),permute(v,[2 1 3]),permute(w,[2 1 3])...
,xs,ys,zs);
If anybody can explain why this happens, and can indicate to me why this is not a bug, welcome.
This behavior is not a bug because it is clearly documented as the intended behavior: https://www.mathworks.com/help/matlab/ref/meshgrid.html. Specifically:
[X,Y,Z]= meshgrid(x,y,z) returns 3-D grid coordinates defined by the vectors x, y, and z. The grid represented by X, Y, and Z has size length(y)-by-length(x)-by-length(z).
Without speaking to the original authors, the exact motivation may be a bit obscure, but I suspect it has to do with the fact that the y-axis is generally associated with the rows of an image, while x is the columns.
Columns are either "j" or "x" in the documentation, rows are either "i" or "y".
Some functions deal with spatial coordinates. The documentation will refer to "x, y, z". These functions will thus take column values before row values as input arguments.
Some functions deal with array indices. The documentation will refer to "i, j" (or sometimes "i1, i2, i3, ..., in", or using specific names instead of "i" before the dimension number). These functions will thus take row values before column values as input arguments.
Yes, this can be confusing. But if you pay attention to the names of the variables in the documentation, you will quickly figure out the right order.
With meshgrid in particular, if the "x, y, ..." order of arguments is confusing, use ndgrid instead, which takes arguments in array indexing order.
I want to reduce a two dimensional matrix to row vector.
But using reshape with large matrices is really slow. The other alternative is to use colon, but i want matrix's transpose to be colon and not the matrix itself.
e.g.
A=magic(3)
A =
8 1 6
3 5 7
4 9 2
A(:) will stack up all the columns one by one. but i am looking for something like this:
AA=A(2:3,:)';
and then reshape or colon AA instead of A.
The issue is i dont want to define additional variable like AA.
Is there anyway to reduce dimension of two dimensional matrix without reshape?
You can avoid the additional variable by linear indexing. For your example:
A([2 5 8 3 6 9])
which gives
3 5 7 4 9 2
What's happening here is that you treat A as if it was already transformed into a vector, and the elements of this one-dimensional array are accessed through indices 1 through 9. Using the colon is a special case of linear indexing, A(:) is the same as A(1 : end).
Figuring out the right linear indices can be tricky, but sub2ind can help with that.
It is possible that this slightly speeds up the code, mainly because (as #Shai wrote) you avoid writing data to an intermediate variable. I wouldn't expect too much, though.
Try looking at subsref. For your example, you could use it as follows:
subsref(A',struct('type','()','subs',{{2:3,':'}}))
Update: I misunderstood the original question; I thought the OP wanted to select rows from 2:3 from the transposed A matrix keeping the columns as is. I will keep the previous answer in case it could be useful to others.
I think he/she could use the following to slice and flatten a matrix:
subsref(A(2:3,:)', struct('type','()','subs',{{':'}}))
This would give as output:
[3 5 7 4 9 2]'
Is there a way to let accumarray drop every observation but the last of each group?
What I had in mind was something similar:
lastobs=accumarray(bin,x,[],#(x){pick the observation with the max index in each group};
To give you an example, suppose I have the following:
bin=[1 2 3 3 3 4 4]; %#The bin where the observations should be put
x= [21 3 12 5 6 8 31]; %#The vector of observations
%#The output I would like is as follow
lastobs=[21 3 6 31];
I am actually thinking of accumarray only because I just used it to compute the mean of the observations for each bin. So every function that could make the trick would be fine for me.
Of course you can do this with accumarray. x(end) is the last observation in an array. Note that bin needs to be sorted for this to work, so if it isn't, run
[bin,sortIdx]=sort(bin);x = x(sortIdx); first.
lastobs = accumarray(bin(:),x(:),[],#(x)x(end)); %# bin, x, should be n-by-1
You already got your accumarray answer, but since you are looking for any solution that will do the job, consider the following application of unique.
Using unique with the 'legacy' option gives the index of the last occurrence of each value, as you need:
>> [~,ia] = unique(bin,'legacy')
ia =
1 2 5 7
>> lastobs = x(ia)
lastobs =
21 3 6 31
Now, I love accumarray, as many here are aware, but I actually prefer this solution.
I'm a newbie to Matlab and just stumped how to do a simple task that can be easily performed in excel. I'm simply trying to get the percent change between cells in a matrix. I would like to create a for loop for this task. The data is setup in the following format:
DAY1 DAY2 DAY3...DAY 100
SUBJECT RESULTS
I could only perform getting the percent change between two data points. How would I conduct it if across multiple days and multiple subjects? And please provide explanation
Thanks a bunch
FOR EXAMPLE, FOR DAY 1 SUBJECT1(RESULT=1), SUBJECT2(RESULT=4), SUBJECT3(RESULT=5), DAY 2 SUBJECT1(RESULT=2), SUBJECT2(RESULT=8), SUBJECT3(RESULT=10), DAY 3 SUBJECT1(RESULT=1), SUBJECT2(RESULT=4), SUBJECT3(RESULT=5).
I WANT THE PERCENT CHANGE SO OUTPUT WILL BE DAY 2 SUBJECT1(RESULT=100%), SUBJECT2(RESULT=100%), SUBJECT3(RESULT=100%). DAY3 SUBJECT1(RESULT=50%), SUBJECT2(RESULT=50%), SUBJECT3(RESULT=50%)
updated:
Hi thanks for responding guys. sorry for the confusion. zebediah49 is pretty close to what I'm looking for. My data is for example a 10 x 10 double. I merely wanted to get the percentage change from column to column. For example, if I want the percentage change from rows 1 through 10 on all columns (from columns 2:10). I would like the code to function for any matrix dimension (e.g., 1000 x 1000 double) zebediah49 could you explain the code you posted? thanks
updated2:
zebediah49,
(data(1:end,100)- data(1:end,99))./data(1:end,99)
output=[data(:,2:end)-data(:,1:end-1)]./data(:,1:end-1)*100;
Observing the code above, How would I go about modifying it so that column 100 is used as the index against all of the other columns(1-99)? If I change the code to the following:
(data(1:end,100)- data(1:end,:))./data(1:end,:)
matlab is unable because of exceeding matrix dimensions. How would I go about implementing that?
UPDATE 3
zebediah49,
Worked perfectly!!! Originally I created a new variable for the index and repmat the index to match the matrices which was not a good idea. It took forever to replicate when dealing with large numbers.
Thanks for you contribution once again.
Thanks Chris for your contribution too!!! I was looking more on how to address and manipulate arrays within a matrix.
It's matlab; you don't actually want a loop.
output=input(2:end,:)./input(1:end-1,:)*100;
will probably do roughly what you want. Since you didn't give anything about your matlab structure, you may have to change index order, etc. in order to make it work.
If it's not obvious, that line defines output as a matrix consisting of the input matrix, divided by the input matrix shifted right by one element. The ./ operator is important, because it means that you will divide each element by its corresponding one, as opposed to doing matrix division.
EDIT: further explanation was requested:
I assumed you wanted % change of the form 1->1->2->3->1 to be 100%, 200%, 150%, 33%.
The other form can be obtained by subtracting 100%.
input(2:end,:) will grab a sub-matrix, where the first row is cut off. (I put the time along the first dimension... if you want it the other way it would be input(:,2:end).
Matlab is 1-indexed, and lets you use the special value end to refer to the las element.
Thus, end-1 is the second-last.
The point here is that element (i) of this matrix is element (i+1) of the original.
input(1:end-1,:), like the above, will also grab a sub-matrix, except that that it's missing the last column.
I then divide element (i) by element (i+1). Because of how I picked out the sub-matrices, they now line up.
As a semi-graphical demonstration, using my above numbers:
input: [1 1 2 3 1]
input(2,end): [1 2 3 1]
input(1,end-1): [1 1 2 3]
When I do the division, it's first/first, second/second, etc.
input(2:end,:)./input(1:end-1,:):
[1 2 3 1 ]
./ [1 1 2 3 ]
---------------------
== [1.0 2.0 1.5 0.3]
The extra index set to (:) means that it will do that procedure across all of the other dimension.
EDIT2: Revised question: How do I exclude a row, and keep it as an index.
You say you tried something to the effect of (data(1:end,100)- data(1:end,:))./data(1:end,:). Matlab will not like this, because the element-by-element operators need them to be the same size. If you wanted it to only work on the 100th column, setting the second index to be 100 instead of : would do that.
I would, instead, suggest setting the first to be the index, and the rest to be data.
Thus, the data is processed by cutting off the first:
output=[data(2:end,2:end)-data(2:end,1:end-1)]./data(2:end,1:end-1)*100;
OR, (if you neglect the start, matlab assumes 1; neglect the end and it assumes end, making (:) shorthand for (1:end).
output=[data(2:,2:end)-data(2:,1:end-1)]./data(2:,1:end-1)*100;
However, you will probably still want the indices back, in which case you will need to append that subarray back:
output=[data(1,1:end-1) data(2:,2:end)-data(2:,1:end-1)]./data(2:,1:end-1)*100];
This is probably not how you should be doing it though-- keep data in one matrix, and time or whatever else in a separate array. That makes it much easier to do stuff like this to data, without having to worry about excluding time. It's especially nice when graphing.
Oh, and one more thing:
(data(:,2:end)-data(:,1:end-1))./data(:,1:end-1)*100;
is identically equivalent to
data(:,2:end)./data(:,1:end-1)*100-100;
Assuming zebediah49 guessed right in the comment above and you want
1 4 5
2 8 10
1 4 5
to turn into
1 1 1
-.5 -.5 -.5
then try this:
data = [1,4,5; 2,8,10; 1,4,5];
changes_absolute = diff(data);
changes_absolute./data(1:end-1,:)
ans =
1.0000 1.0000 1.0000
-0.5000 -0.5000 -0.5000
You don't need the intermediate variable, you can directly write diff(data)./data(1:end,:). I just thought the above might be easier to read. Getting from that result to percentage numbers is left as an exercise to the reader. :-)
Oh, and if you really want 50%, not -50%, just use abs around the final line.
I have an array with size m = 11 and my hash function is Division method : h(k) = k mod m
I have an integer k = 10 and 10 mod 11 is -1 so where should I put this key in the array? I should put this key in the slot which its index is 10?
please help me thanks
EDITED : for getting my answer well for example I have integers like k = 10,22,31,4,15,28,17,88,59
the array would be like this?thanks
10 9 8 7 6 5 4 3 2 1 0 index
10 31 59 17 28 4 15 88 22 keys
As it's usually done, 10 mod 11 is 10, so yes, you'd normally use index 10.
Edit: To generalize: at least as it's normally defined, given two positive inputs, a modulo will always produce a positive result. As such, your questions about what to do with negative results don't really make sense with respect to the normal definition.
If you really do have the possibility of getting a negative result, my immediate reaction would be to switch to some language that will produce a reasonable result. If you can't do that, then you'd probably want to move the value into the correct range by adding m to the negative number until you get a number in the range [0..m) so it fits the normal definition of mod, then use that as your index.