I have a data structure which contains 1520 values. Is it possible to create a matrix using a for loop instead of writing out the matrix manually? The data points are named U_Velocity1 to U_Velocity1520. I'm trying to make a 18x40 matrix where the first column is made from values of U_Velocity1 to 18 and the seconds column is made from the values of U_Velocity19 to 76 and so on. Regards Jer
Considering the following example:
s.a1 = 1;
s.a2 = 3;
s.a3 = 5;
s.a4 = 10;
arr = reshape(struct2array(s),2,2)
arr =
1 5
3 10
Just replace the numbers and variables with your code.
Related
I'm working in Matlab.
I have a two-dimensional matrix with two columns. Lets consider elements in the first column as labels. Labels may be repeated.
How to multiply all elements in the second column for every label?
Example:
matrix = [1,3,3,1,5; 2,3,7,8,3]'
I need to get:
a = [1,3,5; 16,21,3]'
Can you help me with doing it without for-while cycles?
I would use accumarray. The preprocessing with unique assigns integer indices 1:n to the values in the first row, which allow accumarray to work without creating unnecessary bins for 2 and 4. It also enables the support for negative numbers and floats.
[ulable,~,uindex]=unique(matrix(:,1))
r=accumarray(uindex,matrix(:,2),[],#prod)
r=[ulable,r]
/You can also use splitapply:
[ulable,~,uindex]=unique(matrix(:,1))
r=splitapply(#prod,matrix(:,2),uindex)
r=[ulable,r]
You can do it without loops using accumarray and the prod function:
clear
clc
matrix = [1,3,3,1,5; 2,3,7,8,3]';
A = unique(matrix,'rows');
group = A(:,1);
data = A(:,2);
indices = [group ones(size(group))];
prods = accumarray(indices, data,[],#prod); %// As mentionned by #Daniel. My previous answer had a function handle but there is no need for that here since prod is already defined in Matlab.
a = nonzeros(prods)
Out = [unique(group) a]
Out =
1 16
3 21
5 3
Check Lauren blog's post here, accumarray is quite interesting and powerful!
Try something like this, I'm sure it can be improved...
unValues = unique(matrix(:,1));
bb = ones(size(unValues));
for ii = 1:length(unValues)
bb(ii) = bb(ii)*prod(matrix(matrix(:, 1) == unValues(ii), 2));
end
a = [unValues bb];
First of all thank you for reading my question.
I am trying to import data from a file with following format into Matlab:
#Text
#Text: Number
...
#Text: Number
Set1:
1 2
3 4
Set2:
5 6
7 8
...
I would like to get those numbers into two matrices of the form:
(1 5
3 7)
and
(2 6
4 8)
I started by only building the first of those two matrices.
Winkel = 15;
xp = 30;
M = readtable('Ebene_1.txt')
M([1:4],:) = [];
M(:,3) = [];
for i=0:Winkel-1
A = table2array(M((2+i*31:31+i*31),1))
end
But this solution only gave me cell arrays which I could not transform into normal vectors.
I also tried to use the importdata command, but could not find a way to get this to work either. I know there are many other questions similar to mine, but I could not find one where all the data were in a single column. Also, there are many Matlab-commands for importing data into Matlab and I am not sure which would be the best.
First time asking such a question online so feel free to ask me for more details.
You can import the data you provided in your sample using readtable, however because of the format of your file you will need to tweak the function a bit.
You can use detectImportOptions to tell the function how to import the data.
%Detect import options for your text file.
opts = detectImportOptions('Ebene_1.txt')
%Specify variable names for your table.
opts.VariableNames = {'Text','Number'};
%Ignore last column of your text file as it does not contain data you are interested in.
opts.ExtraColumnsRule = 'ignore';
%You can confirm that the function has successfully identified that the data is numeric by inspecting the VariableTypes property.
%opts.VariableTypes
%Read your text file with detectImportOptions.
M = readtable('Ebene_1.txt',opts)
Now that you have table M, simply apply basic Matlab operations to obtain the matrices as you specified.
%Find numerical values in Text and Number variables. Ignore NaN values.
A = M.Text(~isnan(M.Text));
B = M.Number(~isnan(M.Number));
%Build matrices.
A = [A(1:2:end)';A(2:2:end)']
B = [B(1:2:end)';B(2:2:end)']
Output:
A =
1 5
3 7
B =
2 6
4 8
I am trying to convert a structure array to a matrix. Each field of the structure stores a vector that can reach up to 520000 rows. There can be up to 20 fields in a single structure array, but number of rows is the same across the fields.
As a down scaled example consider the structure s, where each field is an integer:
s=struct('a',1,'b',2);
s(2)=struct('a',3,'b',4);
s=s';
In the desired output, each field will correspond to a column. a values will be in the first column, while b values will be in the second:
desiredOutput = [1 2; 3 4];
I have approached this in an indirect way:
cell2mat(struct2cell(s))'
However, this involves two transformations which i find unnecessary due to the well behaved nature of my structure.
I have also approached this using a for loop:
fields = fieldnames(s);
nrows = size(s,1);
ncols = numel(fields);
desiredOutput = nan(nrows,ncols);
for jj=1:ncols
desiredOutput(:,jj) = [s.(fields{fields(jj)})]';
end
I hoped to find a struct2mat function but it does not exist. Is there a simpler way to accomplish this task that I am not aware of?
I had something similar to this written out. So, if you don't mind, I will 'kinda' copy that out over here.
data(1,1).val = 1;
data(1,2).val = 2;
data(2,1).val = 3;
data(2,2).val = 4;
This gives a 2x2 struct with field val.
A = reshape([data.val],size(data))
Now, A looks like this [ 1 2 : 3 4]
A =
1 2
3 4
Does that help?
I have the matrix below:
a = [1 2 1 4;
3 4 9 16;
0 0 -2 -4;
0 0 -6 -8]
How can I arbitrary remove any given rows or columns? for example second row and third column of the above matrix?
Just assign the column or line to the empty matrix:
a(2,:) = [];
a(:,3) = [];
Note : I compare the other solution to mine, following the link put inside. On a big array (created as rand(1e4)) and on 10 runs where I delete 2 columns and 2 rows, the average times are 0.932ms for the empty-matrix assignment, and 0.905ms for the kept-row (or -column) assignment. So the gap seen there is not as big as 1.5x mentioned in the link. Always perform a little benchmark first :) !
Edit Fastest solution is to create the index mask for rows and columns, and reassign your array with these masks. Ex:
a = rand(10000);
kr = true(size(a,1),1);
kr([72,6144]) = false; % some rows to delete
kc = true(1,size(a,2));
kc([1894,4512]) = false; % some columns to delete
a = a(kr,kc);
On this test, it's clearly twice faster than performing the suppression on rows and columns separately.
A slightly more efficient way (although possibly more complicated to set up) is to reassign all the rows you want to keep (when compared with setting the rows you want to delete to the empty matrix). So for example if you want to delete rows 5 and 7 from a matrix you can either do
A = A([1:4, 6, 8:end],:)
or
A = A(setdiff(1:size(A,1), [5,7] ),:)
but the best method is likely to use logical indexing (which is often a natural step in Matlab workflows anyway):
idx = true(size(A,1),1);
idx([5,7]) = false;
A = A(idx,:)
I am trying to split an array of unknown length in Matlab into two arrays of random lengths. I think I was able to do it but it is a little clunky. I also would like to be able to save all of the possible combinations afterwards (a matrix for subarray 1 and a matrix for subarray 2), but I am having trouble doing this because it cant be saved in a matrix because they all have different lengths. Should I use cells instead?
Here is my code for splitting the arrays
Array = [1 2 4 5 6 2 3]
x = randi(length(Array))
newArray1 = Array(1:x)
newArray2 = Array(x+1:end)
Would like to run the above code a few times and save each combination of array1 and array 2 in its own matrix or cell like below
all_of_Array1 = [all_ofArray1:newArray1]
all_of_Array2 = [all_ofArray2:newArray2]
Thanks!
So you just want a loop?
%//Pre-allocation
n = 10;
newArray1{n} = [];
newArray2{n} = [];
for k = 1:n
%//Generate Array here if it changes at each iteration
Array = [1 2 4 5 6 2 3]
x = randi(length(Array)-1);
newArray1{k} = Array(1:x)
newArray2{k} = Array(x+1:end)
%//Or replace the 2 lines above with newArray{k,1}=... and newArray{k,2}=...
end