This is a simplistic example of a problem I am facing:
depth = [0:1:20]';
data = rand(1,length(depth))';
d = [depth,data];
d = [d;d;d];
Consider the matrix 'd'. Here we have depth in the first column followed by temperature measurements recorded at that depth in column 2 (in this example we have 3 days of data). How could I alter this matrix so that each column represents a specific depth and each row represents time. So, finally I should have 3 rows with 21 columns.
If I understand correctly your array d has the data for day 1 in rows 1:21, for day 2 in rows 22:42, and so on. Column 1 of d holds the depths (3 times), and column 2 holds the measurements.
One way to get the results in the form you want is to execute:
d2 = reshape(d(:,2),21,3)'; % note the ' for transposition here
This leaves you with an array with 3 rows and 21 columns. Each column represents the measurements for one depth, each row the measurements for one day.
Related
I have a cell with dimension 41X41 as shown below
that has values equal to 1, it means all its values are equal to ones as shown below:
Based on many values, I could not include it here in one figure, but its dimension is 41 x 41.
What I was trying to do is calculate the number of ones in each row minus one as shown in the snippet of line code below:
ccc = sum(isSmaller{cc,:} == 1)-1
In order to get a cell with 1 row with 40 columns dimension that has 40s. as shown below:
My problem is instead of 40 columns is still showing 41 columns after deleting one from each row as indicated below.
May I get assistance, please? I need it to be 1 row with 40 columns.
Note: I do not care for the first 40 rows or columns or the lasts or the middle ones. I just need it to be done by itself only by minus one.
After that, I need to sum all the 40s in this ccc = 1x40.
Below is my try:
for cc = 1:length(isSmaller)
ccc = sum(isSmaller{cc,:} == 1)-1
end
If I understand correctly, isSmaller is a 1-by-1 cell array whose single cell contains a 41-by-41 matrix of logical values all equal to 1 (true):
isSmaller={true(41)};
Then you wish to calculate the sum of each row of this matrix inside of a cell and subtract one from the result:
sum(isSmaller{1},1)-1
But since you only care about the first 40 rows you can trim off the last row with:
sum(isSmaller{1}(:,1:40),1)-1
Or:
sum(isSmaller{1}(:,1:end-1),1)-1
This returns a 1-by-40 matrix where each element is 40.
Finally, you want to sum over the 40 elements of this matrix:
sum(sum(isSmaller{1}(:,1:end-1),1)-1)
This returns 1600, as expected.
No for loops are needed if this is all you need to do and your example is representative. I urge you to read through Matlab's documentation on cell arrays, in particular on how to access data within them.
I have a 35 x 24 matrix of numbers. Each of the 35 rows obviously has a maximum value. I'm trying to write a short piece of code which determines which of the 24 columns contains the most of these max values. The catch is that no loops are allowed.
For example if the maximum values for 30 different rows all happened to lie in column 7 then I would want MATLAB to return the answer 7 since this is the column with the most max row values.
If the values in each row are unique, we can simply use the second output of max combined with the mode to figure out which column contains the maximum of each row most often.
% Find the column which contains the maximum value
[~, column] = max(data, [], 2);
result = mod(column);
However, below is a more general solution that allows a given maximum value to occur multiple times per row.
maximaPerColumn = sum(bsxfun(#eq, data, max(data, [], 2)), 1);
result = find(maximaPerColumn == max(maximaPerColumn));
Explanation
First we want compute the maximum value for each row (maximum across columns, dimension 2).
rowMaxima = max(data, [], 2);
Then we want to replace each row with a 1 if the value is equal to the max of that row and 0 otherwise. We can easily do this using bsxfun.
isMaxOfRow = bsxfun(#eq, data, rowMaxima);
Then we want to figure out how many times a given column contains a max of a row. We can simply sum down the columns to get this.
maximaPerColumn = sum(isMaxOfRow, 1);
Now we want to find the column which contained the maximum number of maxima. We use find due to the fact that more than one column could contain the same number of maxima.
result = find(maximaPerColumn == max(maximaPerColumn));
I think you are looking for this:
sum(A==max(A,[],2))
Example:
A = [1 1 1;
2 2 2;
3 2 1]
M = sum(A==max(A,[],2))
Returns:
[3 2 2]
The first column has the most row wise max values. You could use find to identify this column.
find(M==max(M))
I need help with taking the following data which is organized in a large matrix and averaging all of the values that have a matching ID (index) and outputting another matrix with just the ID and the averaged value that trail it.
File with data format:
(This is the StarData variable)
ID>>>>Values
002141865 3.867144e-03 742.000000 0.001121 16.155089 6.297494 0.001677
002141865 5.429278e-03 1940.000000 0.000477 16.583748 11.945627 0.001622
002141865 4.360715e-03 1897.000000 0.000667 16.863406 13.438383 0.001460
002141865 3.972467e-03 2127.000000 0.000459 16.103060 21.966853 0.001196
002141865 8.542932e-03 2094.000000 0.000421 17.452007 18.067214 0.002490
Do not be mislead by the examples I posted, that first number is repeated for about 15 lines then the ID changes and that goes for an entire set of different ID's, then they are repeated as a whole group again, think first block of code = [1 2 3; 1 5 9; 2 5 7; 2 4 6] then the code repeats with different values for the columns except for the index. The main difference is the values trailing the ID which I need to average out in matlab and output a clean matrix with only one of each ID fully averaged for all occurrences of that ID.
Thanks for any help given.
A modification of this answer does the job, as follows:
[value_sort ind_sort] = sort(StarData(:,1));
[~, ii, jj] = unique(value_sort);
n = diff([0; ii]);
averages = NaN(length(n),size(StarData,2)); % preallocate
averages(:,1) = StarData(ii,1);
for col = 2:size(StarData,2)
averages(:,col) = accumarray(jj,StarData(ind_sort,col))./n;
end
The result is in variable averages. Its first column contains the values used as indices, and each subsequent column contains the average for that column according to the index value.
Compatibility issues for Matlab 2013a onwards:
The function unique has changed in Matlab 2013a. For that version onwards, add 'legacy' flag to unique, i.e. replace second line by
[~, ii, jj] = unique(value_sort,'legacy')
I have one column matrix with n rows of postitive and negative values . I want difference between row 2 and row 1 , row 3 and row 2 and so on. I should need the difference in a single column
How do you want to measure the difference?
You cannot get all those differences in one single column without using a suitable norm, try "help norm"
[n,m]= size(A);
d=zeros(1,n)
for k= 1:n-1
d(k) = norm(A(k,:))-norm(A(k+1,:));
end
The output is stored in the column-vector d.
I have a 3650x1 column vector of time series data in ascending order from 1/1/2000 through 12/31/2010. This means that the observations are in rows and the 1/1/2000 observation is in the first row and the 12/31/2010 observation is in the last row.
I also have a row vector of offsets and an empty matrix called z_scores:
offsets = [5 10 15 20]
z_scores = nan(3650, 4)
I am trying to populate z_scores. Each column in z_scores corresponds to a series of offset z-scores.
For example, the first column of z_scores will contain z-scores of 5 periods. The second column of z_scores will contain z-scores of 10 periods, etc. The first offset indicies of z_scores will be NaN in each column.
Currently, I loop through offsets which is fine. However I would prefer a vectorized solution in each iteration of offset if possible.
for i=1:length(offset)
z_scores(:, i) = (data() - mean()) / std() % help!
end
I have all the toolboxes so I can use built in functions. If someone wants to suggest a non-vectorized solution, I would be happy do see it!
for i=1:length(offsets)
N = offsets(i);
z_scores(1:N, i) = zscore(data(1:N));
end