index 398120 is out of bounds for axis 0 with size 398120 - filtering

I am trying to filter a numpy array with the code below. but I get this error: index 398120 is out of bounds for axis 0 with size 398120, how can I solve it?
for n in range(m):
if n == 0:
t1dc[n]=t1[n]
t2dc[n]=t2[n]
t3dc[n]=t3[n]
else:
t1dc[n]=0.0158*t1[n]+0.9843*t1dc[n-1]
t2dc[n]=0.0158*t2[n]+0.9843*t2dc[n-1]
t3dc[n]=0.0158*t3[n]+0.9843*t3dc[n-1]

Related

Replace array value at SOME specific rows in matlab

I try to replace the array values at some specific row (row number 1, 10, 12, 20, 39 etc, not continuous) using the linear index from find. However I don't know how to proceed after this few lines of code:
[valmax, ~]=max(A); %Where A will consist of more than one MAX value
idxmax=find(A==valmax);
mclr=repmat([1 0 0],[10 1]); %Create the matrix of my value
mclr(idxmax,:)=[0 1 0]; %replace the value at idxmax index, this line won't work
Any idea how to fix this? Or there are other function instead of using find?
Thanks!
you can use ind2sub to convert the linear indexes into row indexes:
A = randi(5,[10 3]); % random matrix
[valmax, ~] = max(A(:)); %Where A will consist of more than one MAX value
idxmax = find(A == valmax);
% convert linear index into row index
[rowmax,colmax] = ind2sub(size(A),idxmax);
rowmax = unique(rowmax); % get unique rows
mclr = repmat([1 0 0],[10 1]); %Create the matrix of my value
mclr(rowmax,:) = repmat([0 1 0],[numel(rowmax) 1]); %replace the value at idxmax index
however it's more efficient to directly get the rows containing max values using any(X, 2):
rowmax = find(any(A == valmax,2));

Creating a weight adjacency matrix

I need to assign weights to edges of a graph, from the following papers:
"Fast linear iterations for distributed averaging" by L. Xiao and S. Boyd
"Convex Optimization of Graph Laplacian Eigenvalues" by S. Boyd
I have the adjacency matrix for my graph (a 50 by 50 matrix), with 512 non-zero values.
I also have a 256 by 1 vector with the optimal weights.
For the software I'm using, I need a 50 by 50 matrix with the weight of edge (i,j) in the relevant position of the adjacency matrix (and with the opposite sign for edge (j,i)).
My attempt is below, but I can't get it working.
function weights = construct_weight_mtx(weight_list, Adj)
weights = zeros(size(Adj));
positions = find(Adj);
for i=1:length(positions)/2
if Adj(i) == 1
weights(i) = weight_list(i);
end
end
weights = weights - weights';
find(Adj) == find(weights);
end
You're finding the nonzero positions in the original adjacency matrix, but you're finding all of them. To get around this, you then take only the first half of those positions.
for i=1:length(positions)/2 ...
Unfortunately, this takes the indices from complete columns rather than just the positions below the diagonal. So if your matrix was all 1's, you'd be taking:
1 1 1 0 0 ...
1 1 1 0 0 ...
1 1 1 0 0 ...
...
instead of:
1 0 0 0 0 ...
1 1 0 0 0 ...
1 1 1 0 0 ...
...
To take the correct values, we just take the lower triangular portion of Adj and then find the nonzero positions of that:
positions = find(tril(Adj));
Now we have only the 256 positions below the diagonal and we can loop over all of the positions. Next, we need to fix the assignment in the loop:
for i=1:length(positions)
if Adj(i) == 1 %// we already know Adj(i) == 1 for all indices in positions
weights(i) = weight_list(i); %// we need to update weights(positions(i))
end
end
So this becomes:
for i=1:length(positions)
weights(positions(i)) = weight_list(i);
end
But if all we're doing is assigning 256 values to 256 positions, we can do that without a for loop:
weights(position) = weight_list;
Note that the elements of weight_list must be in the proper order with the nonzero elements of the lower-triangular portion ordered by columns.
Completed code:
function weights = construct_weight_mtx(weight_list, Adj)
weights = zeros(size(Adj));
positions = find(tril(Adj));
weights(positions) = weight_list;
weights = weights - weights.'; %// ' is complex conjugate; not a big deal here, but something to know
find(Adj) == find(weights); %// Not sure what this is meant to do; maybe an assert?
end

Matlab 2-D density plot

I am trying to do a density plot for a data containing two columns with different ranges. The RMSD column is [0-2] and Angle is [0-200] ranges.
My data in the file is like this:
0.0225370 37.088
0.1049553 35.309
0.0710002 33.993
0.0866880 34.708
0.0912664 33.011
0.0932054 33.191
0.1083590 37.276
0.1104145 34.882
0.1027977 34.341
0.0896688 35.991
0.1047578 36.457
0.1215936 38.914
0.1105484 35.051
0.0974138 35.533
0.1390955 33.601
0.1333878 32.133
0.0933365 35.714
0.1200465 33.038
0.1155794 33.694
0.1125247 34.522
0.1181806 37.890
0.1291700 38.871
I want both x and y axis to be binned 1/10th of the range
The 0 of both the axis to be starting in the same
Print the number of elements in each grid of the matrix like this and make a density plot based on these number of elements
0 0.1 0.2 (RMSD)
0 0 1 3
20 2 0 4
40 1 0 5
60 0 0 2
(Angle)
I can find ways to do 1-D binning but then I am stumped about how to make a density plot from those values and havent even dared to attempt2-D binning + plotting.
Thanks for the help
I think you want hist3. Assuming you want to specifty bin edges (not bin centers), use
result = hist3(data, 'Edges', {[0 .1 .2], [0 20 40 60]}).';
where data denotes your data.
From the linked documentation:
hist3(X,'Edges',edges), where edges is a two-element cell array of numeric vectors with monotonically non-decreasing values, uses a 2-D grid of bins with edges at edges{1} in the first dimension and at edges{2} in the second. The (i,j)th bin includes the value X(k,:) if
edges{1}(i) <= X(k,1) < edges{1}(i+1)
edges{2}(j) <= X(k,2) < edges{2}(j+1)
With your example data this gives
result =
0 0 0
8 14 0
0 0 0
0 0 0
For those who don't have Statistics and Machine Learning Toolbox to run bivariate histogram (hist3), it may be more practical using an alternative to solve 2-D hist problem. The following function generates the same output
function N = hist3_alt(x,y,edgesX,edgesY)
N = zeros(length(edgesY)-1,length(edgesX)-1);
[~,~,binX] = histcounts(x,edgesX);
for ii=1:numel(edgesX)-1
N(:,ii) = (histcounts(y(binX==ii),edgesY))';
end
It's simple and efficient. Then you could run the function like this:
N = hist3_alt(x,y,[0:0.1:2],[0:20:200])

Matlab:Efficient assignment of values in a sparse matrix

I'm working in Matlab and I have the next problem:
I have a B matrix of nx2 elements, which contains indexes for the assignment of a big sparse matrix A (almost 500,000x80,000). For each row of B, the first column is the column index of A that has to contain a 1, and the second column is the column index of A that has to contain -1.
For example:
B= 1 3
2 5
1 5
4 1
5 2
For this B matrix, The Corresponding A matrix has to be like this:
A= 1 0 -1 0 0
0 1 0 0 -1
1 0 0 0 -1
-1 0 0 1 0
0 -1 0 0 1
So, for the row i of B, the corresponding row i of A must be full of zeros except on A(i,B(i,1))=1 and A(i,B(i,2))=-1
This is very easy with a for loop over all the rows of B, but it's extremely slow. I also tried the next formulation:
A(:,B(:,1))=1
A(:,B(:,2))=-1
But matlab gave me an "Out of Memory Error". If anybody knows a more efficient way to achieve this, please let me know.
Thanks in advance!
You can use the sparse function:
m = size(B,1); %// number of rows of A. Or choose larger if needed
n = max(B(:)); %// number of columns of A. Or choose larger if needed
s = size(B,1);
A = sparse(1:s, B(:,1), 1, m, n) + sparse(1:s, B(:,2), -1, m, n);
I think you should be able to do this using the sub2ind function. This function converts matrix subscripts to linear indices. You should be able to do it like so:
pind = sub2ind(size(A),1:n,B(:,1)); % positive indices
nind = sub2ind(size(A),1:n,B(:,2)); % negative indices
A(pind) = 1;
A(nind) = -1;
EDIT: I (wrongly, I think) assumed the sparse matrix A already existed. If it doesn't exist, then this method wouldn't be the best option.

Creating Individual Matrix based on Label Matrix from DataMatrix

Let label be a matrix of size N x 1 (type double) and data be a matrix of size N x M (type double). The entries in the Label matrix looks like [ 1; 23; 135; ....; 6] which conveys that the
First row in the data matrix belongs to label 1
Second row in the data matrix belongs to label 2 and label 3
Third row in the data matrix belongs to label 1, label 3 and label 5 and so on
I would like to create a cell array say Individual{i} which stores all those rows from the data matrix which belongs to label i as given by the label matrix.
The resultant Individual{i} matrix will be size N_i x M.
Is there any efficient way to do the thing rather than looping row by row of data and label matrix?
I would turn your matrix label into a Boolean matrix L:
L = [ 1 0 0 0 0 0 ;
0 1 1 0 0 0 ;
1 0 1 0 1 0 ;
...
0 0 0 0 0 1 ];
for your example. You can use a sparse matrix if N or the number of labels is very large.
Then I think what you call N_i is sum(L(:, i)) and L' * data would compute the sum of all the rows in data with label L.
What do you want to do with the data once it's reached the Individual cell array? There's almost certainly a better way to do it...
Given the correct variables: N, M, data, label as you described, here's a sample code that creates the desired cell array Individual:
%# convert labels to binary-encoded format (as suggested by #Tom)
maxLabels = 9; %# maximum label number possible
L = false(N,maxLabels);
for i=1:N
%# extract digits of label
digits = sscanf(num2str(label(i)),'%1d');
%# all digits should be valid label indices
%assert( all(digits>=1) && all(digits<=maxLabels) );
%# mark this row as belong to designated labels
L(i,digits) = true;
end
%# distribute data rows according to labels
individual = cell(maxLabels,1);
for i=1:maxLabels
individual{i} = data(L(:,i),:);
end