locating the grids in which a dataset falls into and extracting this data in matlab - matlab

I have two sets of data. One set of data is a matrix containing different samples in each row and information regarding each sample in the columns, one of these columns contains longitude data and another one contains latitude data for the sample. The other dataset consists of three grids. One grid contains the latitude of the data, the second grid contains the longitude of the data and the third grid, the data for the 1° latitude longitude grid.
What I would like is to find out which data in the second dataset corresponds with the data in the second dataset. What I mean by this, is if a sample falls into a particular grid of the second dataset, the data in this grid needs to be extracted and it needs to be known for what sample the data applies.
So just say in the grid between latitudes 60 and 59, and longitudes 100 and 101 sample x falls. Just say the data in the gridded dataset is 10 for this particular grid. I would like to know that 10 (the data in the grid) applies to sample x.
In the end I would like to have the grid data that corresponds to a sample in a new matrix that could act as a partner to the sample dataset (ie. if sample x is in row 40 then in the matrix 10 is in row 40), or alternatively added to the same dataset as a new column. Keeping in mind that some samples will fall into the same grid.
I'm fairly inexperienced in matlab, I have tried the brushing tool but this does not work for this example. All I could think of that could potentially work is round each long and lat in the sample data to an even number and then find which samples overlap in long and lat and then intersect the long in the sample data with the long grid and then do the same for the lat grid finding the row and column each sample falls into and then find the data for each sample. This seems like a long way to go about it and I'm not too sure how well it would work as well.
I have completed this method and it has worked to an extent.... I have the rows and columns in which the data is for each sample (ie. sample x can be found in row 8 column 100). However when I try and extract this data from the grid it is not a matrix containing one column but many columns, the answer is still in the sample place of the matrix. How do I go about taking one data point from each row of a grid and ending up with a matrix of only one column (or one row in which I can turn into a column)?
Thank you

Presuming your first data set is in a matrix X, where the first column is latitude and the second is longitude and any other columns are existing data:
xlat = floor(X(1,:));
xlon = floor(X(2,:));
lat = % a list of the latitudes covered in the grid
lon = % a list of the longitudes covered in the grid
data = % the matrix of data you want to extract - a 2D grid
Such that lat(n),lon(m) together forms a reference to the left-bottom corner of the grid square, which contains data in data(n,m). floor rounds down, so that anything between 100 and 101 will be linked to 100, etc.
Now:
[~ n] = ismember(xlat,lat);
[~ m] = ismember(xlon, lon);
n and m are not latitudes or longitudes but indexes which relate the points in your data set X to some values in lat and lon which then refer to some value in the grid data.
Here's the last trick - use sub2ind to convert your n and m references to a single reference to the position in the grid, then extract all the required data in one go:
ind = sub2ind(size(data),n,m); % presuming the size of data is lat x lon);
Xdata = data(ind);
Xdata should be a single column, with the same size as the number of rows in X.

Related

Pairwise Similarity and Sorting Samples

The following is a problem from an assignment that I am trying to solve:
Visualization of similarity matrix. Represent every sample with a four-dimension vector (sepal length, sepal width, petal length, petal width). For every two samples, compute their pair-wise similarity. You may do so using the Euclidean distance or other metrics. This leads to a similarity matrix where the element (i,j) stores the similarity between samples i and j. Please sort all samples so that samples from the same category appear together. Visualize the matrix using the function imagesc() or any other function.
Here is the code I have written so far:
load('iris.mat'); % create a table of the data
iris.Properties.VariableNames = {'Sepal_Length' 'Sepal_Width' 'Petal_Length' 'Petal_Width' 'Class'}; % change the variable names to their actual meaning
iris_copy = iris(1:150,{'Sepal_Length' 'Sepal_Width' 'Petal_Length' 'Petal_Width'}); % make a copy of the (numerical) features of the table
iris_distance = table2array(iris_copy); % convert the table to an array
% pairwise similarity
D = pdist(iris_distance); % calculate the Euclidean distance and store the result in D
W = squareform(D); % convert to squareform
figure()
imagesc(W); % visualize the matrix
Now, I think I've got the coding mostly right to answer the question. My issue is how to sort all the samples so that samples from the same category appear together because I got rid of the names when I created the copy. Is it already sorted by converting to squareform? Other suggestions? Thank you!
It should be in the same order as the original data. While you could sort it afterwards, the easiest solution is to actually sort your data by class after line 2 and before line 3.
load('iris.mat'); % create a table of the data
iris.Properties.VariableNames = {'Sepal_Length' 'Sepal_Width' 'Petal_Length' 'Petal_Width' 'Class'}; % change the variable names to their actual meaning
% Sort the table here on the "Class" attribute. Don't forget to change the table name
% in the next line too if you need to.
iris_copy = iris(1:150,{'Sepal_Length' 'Sepal_Width' 'Petal_Length' 'Petal_Width'}); % make a copy of the (numerical) features of the table
Consider using sortrows:
tblB = sortrows(tblA,'RowNames') sorts a table based on its row names. Row names of a table label the rows along the first dimension of the table. If tblA does not have row names, that is, if tblA.Properties.RowNames is empty, then sortrows returns tblA.

Plotting x-axis and y-axis with different (indep) limits in Matlab

I developed an Android app such that each scan is set to 1 Minute, and during this time the sensor collects many many readings randomly. I want to plot one sensor data of one scan only as follows:
The time of the scan is put manually in seconds for only 1 minute (from 1:60 sec) in the x-axis. While the vector of random readings collected from the sensor (sometimes reach hundreds of values) in the y-axis.
How I can do this in Matlab?
I tried using this code but gives me an error. "Vectors must be the same length."
This is my code:
x1 = linspace(0,60);
plot(x1,vector1,'o-r',x1,vector2,'+-k','LineWidth',lw,'MarkerSize',msz);
xlabel('Time (s)');
ylabel('sensor readings')
In order to match the amount of values you have to modify the input for linspace:
x1 = linspace(0,60,length(vector1));
This way you will automatically get the right amount of entries for your x-axis vector.
You basically tell linspace to create a vector that ranges from 0 to 60 with length(vector1) entries, so that it matches the length of your data set.
Note that if your second data set has a different amount of entries as your first, you will need to create a different x-axis vector that respectively matches its amount of values.

plotting structure elements and dimensions in matlab

I'm trying to create a 3D plot in Matlab of a structure element, Bstruct.scen_1. In this structure, each row is a year, each column is a distance, and the cell value is a population size (so for example, row 3, column 7 would yield the number of adults in year 3 at 7 km.) I want the X-axis to be the number of columns in Bstruct.scen_1, the Y-axis to be the actual value in the cell at (X,Z), and the Z-axis to be the number of rows in Bstruct.scen_1.
Conceptually, what I'd like to accomplish is:
plot3(Bstruct.scen_1(1:num_cols), Bstruct.scen_1(cellvalue), Bstruct.scen_1(1:num_rows))
I'm struggling with the syntax of structures and would really appreciate help in plotting both the elements and the dimensions of this structure. (I mostly code in R with 'tidy' data.) Thank you!
The value of a structure field can be any data type. It sounds like the scen_1 field contains a 2D matrix. The plot3 function expects an X, Y, and Z coordinate for each data point. In your case, if you're wanting to plot the value of the matrix at each 2D location, using the function surf (or mesh) might provide a good start:
% random data for demonstration
Bstruct.scen_1 = rand(20, 10);
figure;
surf(Bstruct.scen_1);

How to change the value of a random subset of elements in a matrix without using a loop?

I'm currently attempting to select a subset of 0's in a very large matrix (about 400x300 elements) and change their value to 1. I am able to do this, but it requires using a loop where each instance it selects the next value in a randperm vector. In other words, 50% of the 0's in the matrix are randomly selected, one-at-a-time, and changed to 1:
z=1;
for z=1:(.5*numberofzeroes)
A(zeroposition(rpnumberofzeroes(z),1),zeroposition(rpnumberofzeroes(z),2))=1;
z=z+1;
end
Where 'A' is the matrix, 'zeroposition' is a 2-column-wide matrix with the positions of the 0's in the matrix (the "coordinates" if you like), and 'rpnumberofzeros' is a randperm vector from 1 to the number of zeroes in the matrix.
So for example, for z=20, the code might be something like this:
A(3557,2684)=1;
...so that the 0 which appears in this location within A will now be a 1.
It performs this loop thousands of times, because .5*numberofzeroes is a very big number. This inevitably takes a long time, so my question is can this be done without using a loop? Or at least, in some way that takes less processing resources/time?
As I said, the only thing that needs to be done is an entirely random selection of 50% (or whatever proportion) of the 0's changed to 1.
Thanks in advance for the help, and let me know if I can clear anything up! I'm new here, so apologies in advance if I've made any faux pa's.
That's very easy. I'd like to introduce you to my friend sub2ind. sub2ind allows you to take row and column coordinates of a matrix and convert them into linear column-major indices so that you can access multiple values in a matrix simultaneously in a single call. As such, the equivalent code you want is:
%// First access the values in rpnumberofzeroes
vals = rpnumberofzeroes(1:0.5*numberofzeroes, :);
%// Now, use the columns of these to determine which rows and columns we want
%// to access A
rows = zeroposition(vals(:,1), 1);
cols = zeroposition(vals(:,2), 2);
%// Get linear indices via sub2ind
ind1 = sub2ind(size(A), rows, cols);
%// Now set these locations to 1
A(ind1) = 1;
The first statement gets the first half of your matrix of coordinates stored in rpnumberofzeroes. The first column is the row coordinates, the second column is the column coordinates. Notice that in your code, you wish to use the values in zeroposition to access the locations in A. As such, extract out the corresponding rows and columns from rpnumberofzeroes to figure out the right rows and columns from zeroposition. Once that's done, we wish to use these new rows and columns from zeroposition and index into A. sub2ind requires three inputs - the size of the matrix you are trying to access... so in our case, that's A, the row coordinates and the column coordinates. The output is a set of column major indices that are computed for each row and column pair.
The last piece of the puzzle is to use these to index into A and set the locations to 1.
This can be accomplished with linear indexing as well:
% find linear position of all zeros in matrix
ix=find(abs(A)<eps);
% set one half of those, selected at random, to one.
A(ix(randperm(round(numel(ix)*.5)))=1;

Handles for individual matrix columns/rows/elements -- Matlab

I'm currently using Matlab and I am plotting the contents of the rows of a matrix, where each column is an independent data set. As the matrix is large I don't want to have to go through the tedius task of writing up the plot labels for each data set individually, so I was wondering if there is a specific way to include a handle/name for each column in such a way that it will automatically apply the plot label, and will adjust accordingly if columns are added or removed from the matrix?
Thanks!
Specifics, if they help:
Amplified spontaneous emission (ASE) in an optical fibre amplifier. Rows act as storage for a discretised ASE spectrum, columns are a given position along the fibre amplifier (it is this position -- the distance along the fibre corresponding to the column -- which I want to use as the label) and each element contains power information. The plot gives spectral power of ASE in the fibre for different positions along its length.
If by labels you mean the plot legend, you can do that by using cells. Consider matrix A
A = repmat([1:3], 3, 1)
A =
1 2 3
1 2 3
1 2 3
You can call plot to plot the columns of the matrix
plot(A);
Here, you will get 3 horizontal lines at y=1, 2 and 3. You can create your legend as follows
l{1} = 'dataset1';
l{2} = 'dataset2';
l{3} = 'dataset3';
Then you type
legend(l)
to show the legend. However, no one will create the legend for you, so you must create the cell array yourself. You can do it automatically, of course, e.g. the above legend can be created by a simple loop
for i=1:size(A, 2)
l{i} = ['dataset' num2str(i)];
end