Reputation:
I have two cell arrays, named as countryname
and export
.
There is only one column in countryname
, which is the code of the names of countries:
USA
CHN
ABW
There are two columns in export
:
USA ABW
USA CHN
CHN USA
ABW USA
Each pair (X,Y) in a row of export
means "country X has relation with country Y". The size of countryname
has been simplified to 3. How can I achieve the following in MATLAB?
Create a square 3 by 3 (in general n by n, where n is the size of
countryname
) matrix M such that
M(i,j)=1
if country i has relation with country j
M(i,j)=0
otherwise.
The country names are relabeled as positive integers in countryname
.
Upvotes: 1
Views: 102
Reputation: 8568
This is using basic MATLAB functionalities only. Solution posted above by @rayryeng is surely much more advanced and may be faster to code as well. However, this should also help you in understanding at fundamental level
clear
country={'USA','CHN','ABW'};
export={'USA' 'ABW'; 'USA' 'CHN'; 'CHN' 'USA' ; 'ABW' 'USA'};
M=zeros(length(country));
for i=1:length(country)
c=country(i);
ind_state=strfind(export(:,1),char(c)); % this gives state of every which is 1 or blank.
ind_match=find(not(cellfun('isempty', ind_state))); % extracting only indices which are 1.
exp_match=export(ind_match,2); % find corresponding export rel countries from second column
% useful only when your first ind_match matrix has more than 1 element.
% Like 'USA' appears twice in first column of export countries.
for j=1:length(exp_match)
c=exp_match(j);
ind_state=strfind(country,char(c));
ind_match=find(not(cellfun('isempty', ind_state)));
M(i,ind_match)=1; % Selective make elements of M 1 when there is match.
end
end
M
Upvotes: 1
Reputation: 104504
The first thing you need to do is establish a mapping from the country name to an integer value from 1 to 3. You can do that with a containers.Map
where the input is a string and the output is an integer. Therefore, we will assign 'USA'
to 1, 'CHN'
to 2 and 'ABW'
to 3. Assuming that you've initialized the cell arrays like you've mentioned above:
countryname = {'USA', 'CHN', 'ABW'};
export = {'USA', 'ABW'; 'USA', 'CHN'; 'CHN', 'USA'; 'ABW', 'USA'};
... you would create a containers.Map
like so:
map = containers.Map(countryname, 1:numel(countryname));
Once you have this, you simply map the country names to integers and you can use the values
function to help you do this. However, what will be returned is a cell array of individual elements. We need to unpack the cell array, so you can use cell2mat
for that. As such, we can now create a 4 x 2
index matrix where each cell element is converted to a numerical value:
ind = cell2mat(values(map, export));
We thus get:
>> ind
ind =
1 3
1 2
2 1
3 1
Now that we have this, you can use sparse
to create the final matrix for you where the first column serves as the row locations and the second column serves as the column locations. These locations will tell you where it will be non-zero in your final matrix. However, this will be a sparse matrix and so you'll need to convert the matrix to full
to finally get a numerical matrix.
M = full(sparse(ind(:,1), ind(:,2), 1));
We get:
>> M
M =
0 1 1
1 0 0
1 0 0
As a more convenient representation, you can create a table
to display the final matrix. Convert the matrix M
to a table using array2table
and we can add the row and column names to be the country names themselves:
>> T = array2table(M, 'RowNames', countryname, 'VariableNames', countryname)
T =
USA CHN ABW
___ ___ ___
USA 0 1 1
CHN 1 0 0
ABW 1 0 0
Take note that the above code to create the table
only works for MATLAB R2013b and above. If that isn't what you require, just stick with the original numerical matrix M
.
Upvotes: 5