I just search the following related discussions:
How do I find a specific cell within a cell array?.
https://www.mathworks.com/matlabcentral/answers/84242-find-in-a-cell-array
However, they are not what I want exactly.
v = [1 0]; u = [0 1];
C = {v, u; u, u+u}
I create a cell C above with each element a row vector.
If I do
C{2,2}
it shows
ans =
0 2
Inversely, if I know [0 2], I want to find where it is, i.e., I want to get {2,2}, how could I do?
For the scalar case, the answer is shown in the second link; however, I cannot find the answer for the vector case so far.
Thanks!
Following this answer you linked to you can do :
found = cellfun(#(c) isequal(c,[0 2]),c)
which outputs
found =
2×2 logical array
0 0
0 1
lastly to get the coordinates you would use find :
[row,col] = find(found==1)
The output will be
row = 2
col = 2
I have two numpy arrays of shape arr1=(~140000, 3) and arr2=(~450000, 10). The first 3 elements of each row, for both the arrays, are coordinates (z,y,x). I want to find the rows of arr2 that have the same coordinates of arr1 (which can be considered a subgroup of arr2).
for example:
arr1 = [[1,2,3],[1,2,5],[1,7,8],[5,6,7]]
arr2 = [[1,2,3,7,66,4,3,44,8,9],[1,3,9,6,7,8,3,4,5,2],[1,5,8,68,7,8,13,4,53,2],[5,6,7,6,67,8,63,4,5,20], ...]
I want to find common coordinates (same first 3 elements):
list_arr = [[1,2,3,7,66,4,3,44,8,9], [5,6,7,6,67,8,63,4,5,20], ...]
At the moment I'm doing this double loop, which is extremely slow:
list_arr=[]
for i in arr1:
for j in arr2:
if i[0]==j[0] and i[1]==j[1] and i[2]==j[2]:
list_arr.append (j)
I also tried to create (after the 1st loop) a subarray of arr2, filtering it on the value of i[0] (arr2_filt = [el for el in arr2 if el[0]==i[0]). This speed a bit the operation, but it still remains really slow.
Can you help me with this?
Approach #1
Here's a vectorized one with views -
# https://stackoverflow.com/a/45313353/ #Divakar
def view1D(a, b): # a, b are arrays
a = np.ascontiguousarray(a)
b = np.ascontiguousarray(b)
void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
return a.view(void_dt).ravel(), b.view(void_dt).ravel()
a,b = view1D(arr1,arr2[:,:3])
out = arr2[np.in1d(b,a)]
Approach #2
Another with dimensionality-reduction for ints -
d = np.maximum(arr2[:,:3].max(0),arr1.max(0))
s = np.r_[1,d[:-1].cumprod()]
a,b = arr1.dot(s),arr2[:,:3].dot(s)
out = arr2[np.in1d(b,a)]
Improvement #1
We could use np.searchsorted to replace np.in1d for both of the approaches listed earlier -
unq_a = np.unique(a)
idx = np.searchsorted(unq_a,b)
idx[idx==len(a)] = 0
out = arr2[unq_a[idx] == b]
Improvement #2
For the last improvement on using np.searchsorted that also uses np.unique, we could use argsort instead -
sidx = a.argsort()
idx = np.searchsorted(a,b,sorter=sidx)
idx[idx==len(a)] = 0
out = arr2[a[sidx[idx]]==b]
You can do it with the help of set
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr2 = np.array([[7,8,9,11,14,34],[23,12,11,10,12,13],[1,2,3,4,5,6]])
# create array from arr2 with only first 3 columns
temp = [i[:3] for i in arr2]
aset = set([tuple(x) for x in arr])
bset = set([tuple(x) for x in temp])
np.array([x for x in aset & bset])
Output
array([[7, 8, 9],
[1, 2, 3]])
Edit
Use list comprehension
l = [list(i) for i in arr2 if i[:3] in arr]
print(l)
Output:
[[7, 8, 9, 11, 14, 34], [1, 2, 3, 4, 5, 6]]
For integers Divakar already gave an excellent answer. If you want to compare floats you have to consider e.g. the following:
1.+1e-15==1.
False
1.+1e-16==1.
True
If this behaviour could lead to problems in your code I would recommend to perform a nearest neighbour search and probably check if the distances are within a specified threshold.
import numpy as np
from scipy import spatial
def get_indices_of_nearest_neighbours(arr1,arr2):
tree=spatial.cKDTree(arr2[:,0:3])
#You can check here if the distance is small enough and otherwise raise an error
dist,ind=tree.query(arr1, k=1)
return ind
I have an array of structures. Lets say
s(1).value, ... , s(5).value.
I have a vector of values, lets say vals = [1 2 3 4 5], that i want to assign to the array of structures. So written in pseudocode i want: s(:).value = vals.
As shown below there is a know solution. But is it really not possible to do this assignment in 1 line as in the pseudocode?
% Vector of values
vals = [1 2 3 4 5];
n = length(vals);
% Initialize struct
s(n).values = 0;
% Put vals into my struct.values
[s(1:n).values] = ???
% Known solution that i am not satisfied with:
vals_c = num2cell(vals);
[s(1:n).values] = vals_c{:};
Best regards, Jonas
It's possible to do this in one line using cell2struct in conjuction with num2cell.
% Vector of values
vals = [1 2 3 4 5];
n = length(vals);
% Put vals into my struct.values
s = cell2struct(num2cell(vals), 'values', 1)
% transpose if orientation is important
s = s.';
it's not pretty, but it does do it in one line. cell2struct supports multiple entries so you may be able to populate many fields.
The big downside is that it creates the struct from scratch, so you'd have to do a struct merge if you need to add this data to an existing struct.
Having recently gone through the same phase I thought I'd answer this one.
To create a new structure with one field:
field = 'f';
value = {'some text';
[10, 20, 30];
magic(5)};
s = struct(field,value)
Create a nonscalar structure with several fields:
field1 = 'f1'; value1 = zeros(1,10);
field2 = 'f2'; value2 = {'a', 'b'};
field3 = 'f3'; value3 = {pi, pi.^2};
field4 = 'f4'; value4 = {'fourth'};
s = struct(field1,value1,field2,value2,field3,value3,field4,value4)
Also, as I'd always suggest, going over the documentation a few times is quite necessary and useful, so there you go. https://in.mathworks.com/help/matlab/ref/struct.html
I am sure this question must be answered somewhere else but I can't seem to find the answer.
Given a matrix M, what is the most efficient/succinct way to return two matrices respectively containing the row and column indices of the elements of M.
E.g.
M = [1 5 ; NaN 2]
and I want
MRow = [1 1; 2 2]
MCol = [1 2; 1 2]
One way would be to do
[MRow, MCol] = find(ones(size(M)))
MRow = reshape(MRow, size(M))
MCol = reshape(MCol, size(M))
But this does not seem particular succinct nor efficient.
This essentially amounts to building a regular grid over possible values of row and column indices. It can be achieved using meshgrid, which is more effective than using find as it avoids building the matrix of ones and trying to "find" a result that is essentially already known.
M = [1 5 ; NaN 2];
[nRows, nCols] = size(M);
[MCol, MRow] = meshgrid(1:nCols, 1:nRows);
Use meshgrid:
[mcol, mrow] = meshgrid(1:size(M,2),1:size(M,1))
I have a struct array: a 1x10 struct array with fields: N, t, q, r, T, each of which is a vector of type double.
The 10 array entries each represent the outcome of a testing condition in an experiment. I would like to be able to make a function that takes two indices, index1 and index2, and modifies the constituent N, t, q, r vectors (T is a single number) so that they become length index1:index2. Something like
function sa = modifier(struct_array, index1, index2)
sa = structfun(#(x) x(index1:index2), struct_array, 'UniformOutput', false)
stuff
end
Now, where stuff is, I've tried using structfun and cellfun, see here except that those return a struct and a cell array, respectively, whereas I need to return a struct array.
The purpose of this is to be able to get certain sections of the experimental results, e.g. maybe the first five entries in each vector inside each cell correspond to the initial cycles of the experiment.
Please let me know if this is possible, and how I might go about it!
You can try this:
From this question's answer, I figured out how to loop through struct fields. I modified the code to address your question by extracting a subsample from each field that goes through the for loop and then copy the desired subset of that data into a new struct array with identically named fields.
% Define indexes for extraction
fieldsToTrim = {'a' 'b'};
idx = 2:3; % Create index vector for extracting selected data range
% Define test struct to be read
teststruct.a = [1 2 3];
teststruct.b = [4 5 6];
teststruct.c = [7 8 9];
% Get names of struct fields
fields = fieldnames(teststruct);
% Loop through each field and extract the subset
for i = 1:numel(fields)
if max(strcmp(fields{i},fieldsToTrim)) > 0
% If current matches one of the fields selected for extraction
% extract subset
teststructResults.(fields{i}) = teststruct.(fields{i})(idx);
else
% Else, copy all contents on field to resulting struct
teststructResults.(fields{i}) = teststruct.(fields{i});
end
end
Finally, to turn this into a function, you can modify the above code to this:
function teststructResults = extractSubsetFromStruct(teststruct,fieldsToTrim,idx1, idx2)
% idx1 and idx2 are the start and end indicies of the desired range
% fieldsToTrim is a string array of the field names you want
% included in the trimming, all other fields will be fully copied
% teststruct is your input structure which you are extracting the
% subset from
% teststructResults is the output containing identically named
% struct fields to the input, but only containing data from the selected range
idx = idx1:idx2; % Create index vector for extracting selected data range
% Get names of struct fields
fields = fieldnames(teststruct);
% Loop through each field and extract the subset
for i = 1:numel(fields)
if max(strcmp(fields{i},fieldsToTrim)) > 0
% If current matches one of the fields selected for extraction
% extract subset
temp = teststruct.(fields{i});
teststructResults.(fields{i}) = temp(idx);
else
% Else, copy all contents on field to resulting struct
teststructResults.(fields{i}) = teststruct.(fields{i});
end
end
end
I successfully ran the function like this:
teststruct =
a: [1 2 3]
b: [4 5 6]
c: [7 8 9]
>> extractSubsetFromStruct(teststruct,{'a' 'b'},2,3)
ans =
a: [2 3]
b: [5 6]
c: [7 8 9]