I have a cell array of doubles and string in which a particular column looks like this
abc = {[110;10];[20;110];[10];[220];[380];[15];[220];[110;15];[110;20];[110]};
I would like to delete all elements which are less than 110 and I tried this statement abc(cellfun(#(x) any(x<110),abc),1) = [];
I got an error A null assignment can have only one non-colon index. Could someone please explain and rectify this?
I expect the output to be like this
abc = {[110];[110];[];[220];[380];[];[220];[110];[110];[110]};
Thanks!
abc = abc(~cellfun(#(x) any(x<110),abc),1)?
That will invert the logical indices and then select the corresponding entries.
EDIT: After your comment was provided, that should do it:
abc_out = cellfun(#(x) x(x>=110), abc, 'UniformOutput', false)
Related
I am a newbie. I have problem.
I have 20 (1x100) different named vectors. I want to combine these vectors to create a 20x100 matrix with a for loop.
There are the examples of vectors.
namelist=["First","B","New"]
First = [1:100]
B = [1:2:200]
New = [4:4:400]
for i = 1: length(namelist)
new_database(i,1:end) = namelist{i}
end
But, when I want to try this I saw "The end operator must be used within an array index expression." error.
I know I can do same thing with this:
"new_database= [First;B;New]"
but i want to do this with a for loop.
Would you help me how can fix this error? or Would you explain me how can do this?
Your problem is with this line:
new_database(i,1:end) = namelist{i}
the curly braces are used with cells, exclusively and there is no need to use range indexing as you do (i, 1:end)
Generally, it is better practice to assign character arrays or strings to cells.
One question, what are you doing with the 'First', 'New' and 'B' ranges arrays?
Something like:
namelist=["First","B","New"]
First = [1:100];
B = [1:2:200];
New = [4:4:400];
new_database = cell(1, length(namelist));
for i = 1: length(namelist) % or length(new_database)
new_database{i} = namelist(i)
end
which generates this output:
EDIT: My apologies, now I see what you are trying to accomplish. You are building a database from a series of arrays, correct?
Following my previous response, you must consider some points:
1 Your new_database should be square. Regardless of the dimensions of the arrays you are passing to it, if you form a cell from them, you will invariably have empty cells if no data is passed to those rows or columns
2 In some cases, you don't need to use for-loops, where simple indexing might suffice your case problem. Consider the following example using cellstr:
titles = ["Position", "Fruits", "Mythical creatures"]
A = ["One", "Two", "Three"];
B = ["Apple", "Banana", "Durian"];
C = ["Dragon", "Cat", "Hamster"];
db = cell(4, 3);
db(1,:) = cellstr(titles)
db(2:end,1) = cellstr(A)
db(2:end,2) = cellstr(B)
db(2:end,3) = cellstr(C)
which generates this output:
I tried to find something relevant but to no avail, except this post which I can't say it was helpful.
I have two tables A and B:
A has dimensions 5x5 and non unique values in the LastName
LastName = {'Smith';'Johnson';'Williams';'Smith';'Williams'};
YearNow= [2010;2010;2010;2010;2010];
Height = [71;69;64;67;64];
Weight = [176;163;131;133;119];
BloodPressure = [124; 109; 125; 117; 122];
A = table(LastName,YearNow,Height,Weight,BloodPressure);
and B has dimensions 3x2 and unique values in LastName
LastName = {'Smith';'Johnson';'Williams'};
YearBorn= [1950;1975;1965];
B = table(LastName,YearBorn);
I want to create a new column on Table A that will contain their age after I subtract for each A.YearNow the B.YearBorn, so the last column will have the form
A.Age = [60,35,45,60,45];
When I try to use [detect,pos] = ismember(A,B(:,1)); I get an error:
A and B must contain the same variables.
Any help would be appreciated.
Instead of using ismember, which can be quite error-prone as you have to put things in the right order, you could also use Matlab's outerjoin instead:
A = outerjoin(A,B,'Type','Left','MergeKeys',true);
A.Age = A.YearNow - A.YearBorn;
Note that outerjoin modifies the ordering. See the official Matlab documentation for all the input arguments.
An additional advantage of outerjoin over ismember is that in case not all LastNames in table A exist in table B, you will have to pre-allocate output with ismember, and use the first output argument as well.
You need to extract the LastName columns and pass them to ismember. Then you can use the index vector it returns to compute the Age column as follows:
[~, index] = ismember(A.LastName, B.LastName);
A.Age = A.YearNow-B.YearBorn(index);
I have an excel file and I need to read it based on string values in the 4th column. I have written the following but it does not work properly:
[num,txt,raw] = xlsread('Coordinates','Centerville');
zn={};
ctr=0;
for i = 3:size(raw,1)
tf = strcmp(char(raw{i,4}),char(raw{i-1,4}));
if tf == 0
ctr = ctr+1;
end
zn{ctr}=raw{i,4};
end
data=zeros(1,10); % 10 corresponds to the number of columns I want to read (herein, columns 'J' to 'S')
ctr=0;
for j = 1:length(zn)
for i=3:size(raw,1)
tf=strcmp(char(raw{i,4}),char(zn{j}));
if tf==1
ctr=ctr+1;
data(ctr,:,j)=num(i-2,10:19);
end
end
end
It gives me a "15129x10x22 double" thing and when I try to open it I get the message "Cannot display summaries of variables with more than 524288 elements". It might be obvious but what I am trying to get as the output is 'N = length(zn)' number of matrices which represent the data for different strings in the 4th column (so I probably need a struct; I just don't know how to make it work). Any ideas on how I could fix this? Thanks!
Did not test it, but this should help you get going:
EDIT: corrected wrong indexing into raw vector. Also, depending on the format you might want to restrict also the rows of the raw matrix. From your question, I assume something like selector = raw(3:end,4); and data = raw(3:end,10:19); should be correct.
[~,~,raw] = xlsread('Coordinates','Centerville');
selector = raw(:,4);
data = raw(:,10:19);
[selector,~,grpidx] = unique(selector);
nGrp = numel(selector);
out = cell(nGrp,1);
for i=1:nGrp
idx = grpidx==i;
out{i} = cell2mat(data(idx,:));
end
out is the output variable. The key here is the variable grpidx that is an output of the unique function and allows you to trace back the unique values to their position in the original vector. Note that unique as I used it may change the order of the string values. If that is an issue for you, use the setOrderparameter of the unique function and set it to 'stable'
I have a char array A which basically contains a list of files names (each row one file)
(char, 526x26)
val =
0815_5275_UBA_A_1971.txt
0815_5275_UBA_A_1972.txt
0823_6275_UBA_A_1971.txt
0823_6275_UBA_A_1972.txt
0823_6275_UBA_A_1973.txt
...
I also have a variable
B = '0815_5275'
I'd like to select all rows (filenames) that start with B and save them in a new array C.
This should be simple, but somehow I can't make it work.
I've got this:
C = A(A(:,1:9) == B);
but I get the error message:
Error using ==
Matrix dimensions must agree.
I do not know in advance how many rows will match, so I can not pre-define an empty array.
thanks, any help is appreciated!
Try ismember(A(:, 1:numel(B)), B, 'rows') rather to get a logical vector that indexes only the rows you want
and now
A(C,:) to extract the rows
The reason you're getting a dimension mismatch error is because your A(:,1:9) has many rows but B only has one and Matlab does not automatically broadcast like Octave or Python. You could do it using either repmat or bsxfun but in this case ismember is the correct function to choose.
Many near-solutions are online, but nothing exact...
I am building a data matrix vector-by-vector:
OutputMatrix(NextSubject,:)=[OutputVector]
I need to lead each row with the name of the data being processed in that loop. The name has the form:
12345.dat
So if OutputVector=[1 2 3 4] the output should look like:
12345.dat 1 2 3 4
I have tried dozens of solutions, but a few examples:
{char(Filename(i).name) OutputVector}
{strcat((Filename(i).name) OutputVector)}
[Filname(i).name OutputVector]
Any help? Please :)
You can't store a string and a vector in a matrix. However, you can do that in a cell.
So you might consider doing:
OutputCell(NextSubject,:) = { Filename(i).name OutputVector };
The curly braces denote that you are storing the object as a cell.
Often though it is better to store strings and number separately. Something like:
OutputMatrix = [];
OutputFile = {};
...
OutputMatrix(NextSubject,:) = OutputVector;
OutputFile{NextSubject} = Filename(i).name;
Then if you access or select rows from output matrix, use the same index for the cell array:
foo(OutputMatrix(index,:), OutputFile(index))