I have a cell array in MATLAB that has the following columns..
Timestamp Info Joint X Y Z State
0.4449 'BASE05' 'SpineBase' -0.4222 -0.5245 2.681 'Tracked'
The 0.4449 needs to be converted to a timestamp format which I have so far been achieving by extracting column 1 and performing datestr on.
time = num(:,1);
time = num2cell(time);
Bodytime = datestr(cell2mat(time), 'HH:MM:SS');
This gives me a character array with all the timestamps.
However, I need to put this character array back into the first column of cell array. I'm having some trouble here, I was trying to convert my cell array to character array but as I have a mix of numbers and string I don't think that's the way forward. I also tried to replace the first column from the bodytime character array into my original cell array BodyData, but I don't think that's the way forward either.
Ideally I need to get something like this
Timestamp Info Joint X Y Z State
10:44:59 'BASE05' 'SpineBase' -0.4222 -0.5245 2.681 'Tracked'
My main goal here is to look up a certain timestamp of when an event happened and extract/plot (tbd) all the relative information for that time.
When you call datestr with an array of timestamps, what you are actually getting back is a "matrix" of characters, where each row is in the format HH:MM:SS. There is no greater separation between the rows of this matrix than there is between the columns of it (where column 3, for example, is the first : character of each timestamp).
You can certainly split this array back into a cell array, where each cell element is a single timestamp, which can then go back into your source cell array. To do this use mat2cell:
BodytimeCell = mat2cell(Bodytime,size(time));
However there is probably unnecessary complexity in what you've already done. Most simply, if your aim is a cell array of timestamp strings, you could do this directly with cellfun:
BodytimeCell = cellfun(#(t) datestr(t, 'HH:MM:SS'), time, 'UniformOutput',false);
However you might also consider if it really helps to store the timestamps as a strings at all. It may be more advantageous to store them as a datetime array, which can remember the format you want to display it in while still allowing you to work with the value numerically if you need to.
The structure of the data as a whole also suggests it may be better to store as a table than a cell array. This gives you more natural ways to interact with the data - for example, the numeric columns in a table can be treated like numeric arrays directly, rather than having to convert from a cell array of numbers.
Related
I have a list of values that I would like to match against the combination of multiple ranges.
So, for example, my ranges are A1:A100 and B1:B100.
Instead of concatenating A with B in a new column C, i.e.
CONCAT(A1,B1)...CONCAT(A100,B100)
and then matching my value against that new column - I would like to do something like this:
MATCH(value,CONCATENATE(A1:B100),0)
And copy this down a column near my list of values.
I have a feeling this can be done with some sort of array formula...
Yes as an array formula:
=MATCH(value,$A$1:$A$100 & $B$1:$B$100,0)
Being an array formula it must be confirmed with Ctrl-Shift-Enter instead of Enter when exiting edit mode.
Though they may seem similar in approach they are not. CONCATENATE will return a string not an array to the MATCH with all 200 values in one long string. Where the above will return 100 values, each row concatenated, as an array which can be used to search.
One further note, If performance becomes a issue, Array formulas are inherently slower, adding the helper column and using a regular MATCH will improve the responsiveness.
This should work, basically you just need to concatenate it yourself using &
=MATCH(D1,A1:A10&B1:B10,0)
D1 is the value you're trying to look for.
This is an array, so remember to hit Ctrl+Shift+Enter when you input it.
How do I convert a string from a cell to a text array inside of a function, that should use the array, without using VBA and without adding the array into any other part of the document? It will be one of these arrays on more than 1000 rows. The string format is ^[a-zA-Z0-9.,-]*$ with "," as delimiter.
This is the functionality I would like to achieve
I have an excel table with the following columns
A: ID numbers to compare, separated by comma (delimiter can be changed if needed). About 100 ID's would be good to support at least.
B: ID (Each value on the rows in the column are unique but not sorted and can't be sorted because sorting is needed based on other criterias)
C: Value (Several rows in the column can have the same value)
D: Output the one ID of the comma separated ID's that has the highest value on its row
The problem part of the output
So far I have made a function which find the correct ID in column B based on the values in column C but only if I enter the string from column A as an array constant manually within the function. I have not managed to get the function to create the array itself from column A, which is required.
Working part of the code
In this code I have entered the values from column A manually and this is working as it should.
=INDEX({"1.01-1","1.01-3","1.08-1","1.01-1-1A"},MATCH(MAX(INDEX(C$10:C$20,N(IF(1,MATCH({"1.01-1","1.01-3","1.08-1","1.01-1-1A"},B$10:B$20,0))))),INDEX(C$10:C$20,N(IF(1,MATCH({"1.01-1","1.01-3","1.08-1","1.01-1-1A"},B$10:B$20,0)))),0))
Note that the start row is not the first row and the array is used 3 times in the function.
Code to try to convert the string to a text array
Not working but if wrapped in SUMPRODUCT() it provide an array to the SUMPRODUCT() function, of course not usable since I then can't pass on the array. The background to this code can be found in question Split a string (cell) in Excel without VBA (e.g. for array formula)!.
=TRIM(MID(SUBSTITUTE(A10,",",REPT(" ",99)),(ROW(OFFSET($A$1,,,LEN(A10)-LEN(SUBSTITUTE(A10,",",""))+1))-1)*99+((ROW(OFFSET($A$1,,,LEN(A10)-LEN(SUBSTITUTE(A10,",",""))+1)))=1),99))
The second code output the first item of the array and inserted in the first code do not change this result as it did when wrapping the second code in SUMPRODUCT().
Here is a picture of my simplified test setup in Excel for this case, identical to what is described above.
Simplified test setup
I'm not really sure what you are doing with your formula.
But to convert contents of a cell to a comma separated text array to be used as the array argument to the INDEX or MATCH functions, you can use the FILTERXML function. You'll need to educate yourself about XML and XPATH to understand what's going on, but there are plenty of web resource for this.
For example, with
A10: "1.01-1","1.01-3","1.08-1","1.01-1-1A"
The formula below will return 1.08-1. Note the 3 for the row argument to the INDEX function.
=INDEX(FILTERXML("<t><s>" & SUBSTITUTE(SUBSTITUTE(A10,"""",""), ",", "</s><s>") & "</s></t>", "//s"),3)
I have a struct array imported from a tab file, with 100+ name\double rows. The first row has a character value (name\char). I'm trying to load this as a matrix and converted it to cells, removing the top row entirely.
But when I use cell2mat(array), it has the error:
All contents of the input cell array must be of the same data type.
I know this is from the Names vs. double columns. But is there a way to convert this to a matrix? Or, if the data is rows of
name | 1000x1 double
is it better just to leave this as a cell array?
It's not possible to have a matrix containing both strings and numeric values. If you want something like that, cell array is your only option. But, it will be very limiting if you want to process the numeric values using matrix/vector operations, or functions that expect matrices/vectors as input. One option would be to store the strings and numeric data separately; keep the strings in a cell array S and the numeric data in a matrix M. Then, keep track of the elements. For example, S{i} and row M(i, :) could both correspond to entry i from your original table. Another option would be to make your own data structure using struct(), which can contain both strings and numeric values.
maybe this question seems stupid... I would like to fprintf a dataset formatted in rows and columns. I know the procedure so far
for(i=0;i<number_of_rows;i++)
{
for(j=0;j<number_of_columns;j++)
fprintf(file,"%g\t",array[i][j]);
fprintf(file,"\n");
}
What essentially does this code is to fill up first the rows and then the columns. I have datasets that are created by columns. Thus, I want to fill up every column before I pass to the next one. I don't know before the runtime the length of the output data in order to make a proper 2D array. And I need to print out first a whole column, then the other. How can I do this?
And I need to print out first a whole column, then the other. How can I do this?
That would involve appending to a previously printed line. And, as you may know, adding content into a file involves rewriting the entire rest of the file. You can probably guess that would be incredibly inefficient and also complicated to implement.
I don't know before the runtime the length of the output data in order to make a proper 2D array
If your problem is the length of the data, then I assume that by proper 2D array you mean that you intend to pad each cell of a column to be the same width.
In that case, I recommend not to waste time on the idea of writing column first. Instead, calculate the widths at runtime. First sprintf into a matrix of strings and calculate the length of each cell. Then print the matrix of strings using the calculated lengths.
As the title suggests, this is likely an indexing problem, but possibly also about incompatibilities. I have sets of data, all in mixed object types; matrices, structs, double, char, cell.
What I want to achieve is quite simple: I have a function from the matlab community that allows me to extract stock price data from Yahoo. This function looks like this:
market_data = hist_stock_data('start_date','end_date','name_of_stock')
This function return a struct with 8 field - 1 char, 1 cell and 6 doubles, and I have successfully implemented it for one single stock - but I need more!
I have the names of the stocks saved in a separate file, currently as a cell, each stock in a row of its own, appearing as a string if called upon, e.g 'ADS.DE' (Adidas stock name). These strings have either 6 or 7 characters i.e are not uniform. I have the stocks saved at text too, so maybe there's an alternative to a cell? Snipet from Matlab:
stock_names =
'ADS.DE'
'ALV.DE'
'BAS.DE'
'BAYN.DE'
'BEI.DE'
'BMW.DE'
What I would like to do is create my own function, simply with a for-loop or something similar, to carry out the 'hist_stock_data' function above for each of the stocks in my list, and to then extract from each of the corresponding structs that are returned, a select few of the fields (including potentially one of each of the kinds, char, cell and double).
Ideally I would have a matrix at the end, that has just one column for each of the stocks in my list.
I know I can extract them from the structs by doing for example:
struct.price % the stock price field of a given struct
but I also have problems inserting this into another matrix or somewhere else where I can do further mathematical analysis on it (functions: cov(), corr(), eig() and so on).
I would be grateful for any help and suggestions - please let me know if I can provide more info!
Assuming hist_stock_data can't already take a cell array of stock names and return a corresponding struct array (worth checking), It's as simple as:
for ii=1:numel(stock_names)
market_data(ii) = hist_stock_data(start_date, end_date, stock_names{ii});
end
Then you can extract fields from the struct array into vectors with concatenation:
vector_data = [market_data.scalar_field];
matrix_data = [market_data.column_vector_field]; % or,
matrix_data = vertcat(market_data.row_vector_field]);
cell_data = {market_data.nonscalar_field};
which might be useful for certain things:
prices = {market_data.price}; % assuming price is a vector
avgprices = cellfun(#mean, prices);
Alternatively, instead of extracting each field individually, you might prefer to pass the struct array to struct2cell, then just use cell2mat or cellfun to do things with individual rows of the resulting cell array.
Note that the cell arrays still don't mind if the data size for each stock differs - dealing with this in the analysis may be non-trivial since the correct approach (pool, truncate, zero-pad, interpolate, etc.) depends on the data and what exactly you're doing with it.