Matlab: repeat string elements N times - matlab

I have a 1x500 cell of words that have variable length. For example:
words = {'SO','TODAY', 'IS', 'THURSDAY',...}
In addition, I have two 500x1 arrays of integers, the first contains numbers referring to the starting row, the second contains numbers referring to the end row. For example:
startRow = 283 endRow = 309
309 332
332 367
... ...
What I need to do is, I need to fill a 1x3000 matrix of zeros from row 283-308 with the word 'SO' (so that the word is in every row), from row 309-331 with the word 'TODAY', from 332-367 with the word 'IS' and so on until the last element of endRow has been processed.
This is my code so far:
new_val = zeros(1,3000);
for t = 1:size(startRow,1)
count(1,t) = endRow(t)-startRow(t);
word{t} = words{t};
end
for i = 1:size(startRow,1)
new_val(1,startRow(i):endRow(i)-1) = repmat(word{1,i},count(i),1);
end
The problem occurs in the second loop because assignment dimensions mismatch. The size of the left hand element after one iteration is [1,26], the size of the right hand element is [26,2] after one iteration because apparently 'SO' is counted as 2 elements. I don't know what to do about this problem, so any suggestions, hints and tips are appreciated very much. Thank you!

You can't fill a matrix with strings !
So you have to create a [3000x1] cell array.
mycell = cell(3000,1);
And you fill the cell with:
for i = 1:length(startRow)
mycell(startRow(i):endRow(i)) = words(i);
end

Related

Searching for a matched string within nested cell and delivering the index

I have a nested cell array which is called
values. Description as an image. In this example, there are 5 sub cells. Usually this number is variable from 1 to 30. Each cell has two subsub cells:
he first one, or values{5,1}{1,1}, has always only one char value
(in this example, TOTAL or MGS)
the second one, or values{5,1}{2,1}, has matrix consisting from tow columns: on the left - tempearature values, on the right - physical properties.
My goal is to find the sub cell containing the char value 'TOTAL' (values{5,1}) and somehow to get the index of the matrix (the output would be values{5,1}{2,1})
To adress the challenge, I have written my handmade solution. This code works if there is in the char 'TOTAL' in a{5,1}{1,1} and takes a corresponding value next to 298.15 K. However, the string 'TOTAL' could be elsewhere. In this case, I have a problem. In this solution, the double loop takes long time. So, do you have another solution how to find the index of a cell with 'TOTAL' avoiding loops?
for m = 1:numel(values)
for n = 1:numel(values(m))
a = values(m);
if string(a{5,1}{1,1}) == 'TOTAL'
k = a{5,1}{2,1}(:,1); %column with temp numbers
n = 298.15; %RT
[~,~,idx] = unique(round(abs(k-n)));
minVal = k(idx==1);
valueAtRT = sprintf('%f', a{1,1}{5,1}(length(a{1,1}{5,1})+idx));
break;
end
end
end
Thanks for any help.
I have found the solution assuming there is only one cell with 'TOTAL':
is = cellfun( #(cac) strcmp(cac{1},'TOTAL'), values, 'uniformoutput',false );
num = values{is}{2};
valueAtRT = interp1( num(:,1), num(:,2), 298.15, 'nearest', 'extrap' );
is delivers the index of the cell, where the char 'TOTAL' is stored and the third line delivers the value next to 298.15.

Copy array by indexing cell numbers

I am trying to extract specific columns from a "nested" array, the columns I need are nested, there are about a thousand columns, of which I only need the ones marked by index in another part of the array.
I have one Array{1,15} containing cells with numerical values (e.g. 2,5,10,53). These values are the index numbers i need to extract from another array.
indexnum = OutArray{1,15}(:);
Which arranges them in a column instead of a row, totally not necessary but seemed easier for me to progress with this.
Then I have the array containing the actual columns I want to extract/copy to a new array.
OutArray{1,14}{i,1}
So by the example numbers above, I need to copy column 2,5,10 and 53 to another array.
One of my more current attempts looks like this:
NewArray = []; %create new array
indexnum = OutArray{1,15}(:); %copy right index values to column
for i = indexnum{:} %use numeric value of every cell
NewArray = [NewArray, OutArray{1,14}{1,i}] %copy corresponding columns to NewArray
end
I also tried to use cell2mat(indexnum(1,:)), but that didn't help either.
To make clear the structure of the array:
OutArray{1,15} Contains cells with 1 value per column, which are index numbers for other array
OutArray{1,14} contains nested cells, 1 cell per column
OutArray{1,14}{1,x} contains columns with ~30 values per column, of which I want to copy the columns with the right indexes
For another array in which I just needed to copy all columns this code worked fine:
new1 = [];
for i = 1:length(OutArray{1,4})
new1 = [new1, OutArray{1,4}{i,1}]
end
It was a bit hard to understand because of so many cells into cells but your screenshots were very helpful. I will first highlight the errors and needed changes in your attemp:
NewArray = []; %create new array
indexnum = OutArray{1,15}(:); %copy right index values to column
for i = indexnum{:} %use numeric value of every cell
NewArray = [NewArray, OutArray{1,14}{1,i}] %copy corresponding columns to NewArray
end
Doing OutArray{1,15}(:) is exactly the same as OutArray{1,15} as you are just selecting the full cell of cells.
Your for loop uses indexnum{:} as the iterator but {:} returns a comma separated list and it does not work like (:) for arrays that give the full vector instead. In this case, when you assign indexnum{:} to a variable you get only the first element of the list. An example to ilustrate this:C = {1, 2, 3}; C{:} displays the full list, but x = C{:} only makes x = 1. To get all the elements you could group them in an array by doing: x = [C{:}].
So in your case you just need to add brackets to for i = [indexnum{:}] to get the iterator working.
To sum up, your code would be changed to:
NewArray = []; %create new array
indexnum = OutArray{1,15}; %copy right index values to column
for i = [indexnum{:}]
NewArray = [NewArray, OutArray{1,14}{1,i}}];
end
In addition, you could avoid the for loop and variables initialization with this single line code:
NewArray = [OutArray{1,14}{1,[OutArray{1,15}{1,:}]}];
As you can see, it just takes row 1 of your data OutArray{1,14} and the columns specified at each element of the indexes OutArray{1,15}. Brackets are needed twice because when indexing a cell with curly braces with more than one index at a time you always get a list and need to convert into an array as explained above.

Save cell containing different length vectors to text file in MATLAB

I am trying to save a cell array containing different length column vectors to a text file in MATLAB, but I am a bit stuck.
cell_structure = {[1;2;3;...546] [1;2;3;...800] [1;2;3;...1011] [1;2;3;...1118] [1;2;3;...1678]}
I tried using the following code:
fid = fopen( 'myFile.txt', 'w' ) ;
for cId = 1 : numel( cell_structure )
fprintf( fid, '%f ', cell_structure{cId} ) ;
fprintf( fid, '\r\n' ) ;
end
The problem is when I open the text file the column vectors are saved as row vectors and their length is limited to 545. Any help would be much appreciated.
Your first iteration of the for loop prints the ENTIRE first array, in cell_structure. It doesn't matter whether this array is a row or a column vector, since you're using fprintf(), it's going to print each element out, one after another.
This is a little trickier than I can manage at work right now... but you will need to pad your shorter vectors to match the length of your largest.
Then:
for k = 1:size_of_largest_vector
for j = 1:total_number_of_columns
new_cell{k,j} = cell_structure{j}(k)
end
end
This will give you an array of all your column vectors.
Then, use a space delimited csvwrite() to write the columns.
I used Elijah Rockers idea to pad out the shorter column vectors so they are all the same length. And Crowley pointed out that dmlwrite and cvswrite cannot handle empty cells. I found a function that can handle empty cells:
https://github.com/mkoohafkan/UCBcode-Matlab/blob/master/OtherPeoplesFunctions/dlmcell.m
And here is my code to pad out and the save data.
for k = 1:max(cellfun('length',cell)); %longest column vector length
for j = 1:length(cell); % number of colum vctors
if k > length(cell{j}); % if the index is longer than colum vector length
new_cell{k,j} = []; % pad vector
else
new_cell{k,j} = cell{j}(k); %otherwise add to array
end
end
end
dlmcell('test.txt',new_cell,',')
It works like a charm, all of the column vectors in the cell array are now saved in separate columns of the text file.

How to add elements to a vector in a loop

Let's say I have a cell array raweeg each cell of which is a matrix with time points in the first column and some markers in the second. I want to create a vector to store the time points, when the marker is not equal to -1. I found a non-elegant (and not working) way to create a vector of zeros of size 1x1 and then to append the following values in a loop.
P.S.: There are exactly 96 non-"-1" values and corresponding time points.
startpoints = zeros(1,1);
for i = length(raweeg{1,1}(:,1))
if raweeg{1,1}(i,2) ~= -1
startpoints(end+1,1) = raweeg{1,1}(i,1);
end
end
Thank you
Vectorize it like this, for a given cell of raweeg:
startpoints = raweeg{1,1}(raweeg{1,1}(:,2) ~= -1, 1);
This is called logical indexing.
Just be sure your markers are not generated with floating point computations, or the comparisons will likely fail often.
P.S. The problem in your code is the for loop statement, which should be:
for i = 1:length(raweeg{1,1}(:,1))
Or better, for i = 1:size(raweeg{1,1},1).
With out the "1:" part, it just has a single iteration, the last row.

Store a particular set points in a new cell array

I had asked a similar question few weeks back but I think that question was not framed properly so please excuse me for asking the same question again
I have a column vector with values
32.5
25.8
25.91
25.92
16.52
16.7
Now I want to create a cell array such that my first cell contains the first value, my second cell array contains value from 25.8 to 25.92 and finally my third cell array contains the values 16.52 and 16.7 .
How can I solve this problem.
Since you didn't explain why you want the vector split up, I assume the specified division is arbitrary. The following should do what you want, assuming v is the column vector:
c = {v(1) v(2:4) v(5:6)};
Basically you are constructing three new vectors out of pieces of the original, and putting them together into a cell array.
This is a way with for loop.
A = [...
32.5
25.8
25.91
25.92
16.52
16.7];
[U,~,ic] = unique(floor(A));
B = cell(length(U),1); % Result
for k = 1:length(A)
B{ic(k)} = [B{ic(k)} A(k)];
end
Thank to unique command the result is even sorted.