I have a problem in general when Matlab is unable to work out how to logically store values of differing uint types. For example:
tempC = {uint8(5) uint16(16)}
For me, it seems logical to be able to convert this into a matrix of type integer using cell2mat(tempC), which returns
>> cell2mat(tempC)
Error using cell2mat (line 45)
All contents of the input cell array must be of the same data type.
Of course, I understand that the truncation behaviour of integers depends on the type (e.g. uint8 forces all numbers greater than 255 to be 255), however, in this case I would say it would be safe enough to output cell2mat(tempC) with uint16 type. Does anyone have any ideas on how this can be achieved in general?
cell2mat will not work if there are cells of differing types. cell2mat merges the cells together into a matrix, but matrix elements in MATLAB must all share the same type. This is fundamental to how MATLAB works with numeric matrices. If you didn't have all of the same type, then you should use cell arrays... which is what they are for.
However, one thing I can suggest is figure out the type of all of the elements in your matrix, then iterate through each cell and cast them all to be the largest precision type. You can then use cell2mat on this intermediate result to complete the conversion. However, what I have written doesn't actually require calling cell2mat in the end. You'll see later.
Something like this:
%// Get all of the possible types in the array
types = unique(cellfun(#class, tempC, 'uni', 0));
%// Figure out the largest type
vals = cellfun(#(x) double(intmax(x)), types);
[~,ind_max] = max(vals);
%// Cast all values to this type
class_max = types{ind_max};
tempC = cellfun(#(x) cast(x, class_max), tempC);
We first determine all of the possible classes that your cell array contains. We then figure out which of the types is the largest of them all. This can be done by using intmax on each of the types. intmax tells you the largest possible integer that is available for that type, so we basically choose the type that generates the largest possible integer. Take note that I had to cast to double as the output of intmax certainly does output the maximum associated for an integer type, but the output is also cast to that type. This is required so that I can combine all of these elements into an array of the same type - double.
Once we get the type producing the maximum possible integer, we then go through the cell array and cast all of the values to this type. Take note that I used cellfun for the final call which outputs a numeric array - no need to use cell2mat here. In the last line of code, I use cast to cast all of the numbers in the cell array to this type, thus achieving "coercion".
Using your example array, this is what I get, as well as what class the final array is in:
>> tempC
tempC =
5 16
>> class(tempC)
ans =
uint16
Related
In the code below image index range only accept to deal with int16 however I can't find a proper explanation for this case. In the same code, you can notice if I change the data type to int8 for same value error will present.
K>> t2 = int8(t)
t2 =
int8
45
K>> I2 = flt_rot(t:end,:);
K>> I2 = flt_rot(t2:end,:);
Error using :
Colon operands must be in the range of the data type.
Why did this happen?
To understand this problem, first a little background:
MATLAB has a rather unique behavior with respect to numeric values of different types. Originally, MATLAB only used double-precision floating point values (double). At some point it became possible to store arrays of other types, but it was not possible to use those for much. It was not until MATALB 7.0 or so that arithmetic with non-doubles was possible (I'm a bit hazy exactly when that was introduced). And these operations are still a bit "awkward", if you will.
For one, MATLAB does not allow operations with mixed types:
>> int8(4)+int16(6)
Error using +
Integers can only be combined with integers of the same class, or scalar doubles.
Note that error message: "scalar doubles". The one exception to mixed types is that any operation is possible if one of the operands is a scalar double.
Another thing to note is that any operation with a non-double type and a double type results in values of the non-double type:
>> int8(4)+6
ans =
int8
10
The color operator (:) is no exception:
>> int8(4):6
ans =
1×3 int8 row vector
4 5 6
Finally, the last thing to know to understand this problem is that end is a function that returns a double scalar value (yes, it really is a function, albeit a very special one, see help end).
If you have an array flt_rot that is 200x300, end in the first index returns 200. That is, flt_rot(t2:end,:) is the same as flt_rot(t2:200,:). Since t2 is a int8 type:
>> t2=int8(45);
>> t2:200
Error using :
Colon operands must be in the range of the data type.
The solution to your problem is to not use numeric values of type other than double for anything except in large data sets where the amount of memory used matters. For indexing, using an integer is not going to give you any speedup over using doubles, but will give you lots of other problems. There is a reason that the default values are always doubles.
This will work:
I2 = flt_rot(double(t2):end,:);
I want a column vector that contains only the character A, that is,
A
A
A
A
like this. So i have tried
'A'*ones(4,1)
But in place of A, it takes on value 65. How can i get A ?
You can do it this way:
repmat('A',4,1)
Or use your approach but include char to convert back to string after the multiplication:
char('A'*ones(4,1))
Multiplication of chars with doubles gives doubles; the charis cast to double, using the corresponding ASCII value.
Just cast back to char:
char('A'*ones(4,1))
but probably Luis' answer is faster ;)
I am using MATLAB to load a text file that I want to make a sparse matrix out of. The columns in the text file refer to the row indices and are double type. I need them to be integers to be able to use them as indices for rows and columns. I tried using uint8, int32 and int64 to convert them to integers to use them to build a sparse matrix as so:
??? Undefined function or method 'sparse' for input
arguments of type 'int64'.
Error in ==> make_network at 5
graph =sparse(int64(listedges(:,1)),int64(listedges(:,2)),ones(size(listedges,1),1));
How can I convert the text file entries loaded as double so as to be used by the sparse function?
There is no need for any conversion, keep the indices double:
r = round(listedges);
graph = sparse(r(:, 1), r(:, 2), ones(size(listedges, 1), 1));
There are two reasons why one might want to convert to int:
The first, because you have data type restrictions.
The second, your inputs may contain fractions and are un-fit to be used as integers.
If you want to convert because of the first reason - then there's no need to: Matlab works with double type by default and often treats doubles as ints (for example, when used as indices).
However, if you want to convert to integers becuase of the second reason (numbers may be fractionals), then you should use round(), ceil() or floor() - whatever suits your purpose best.
There is another very good reason ( and really the primary one..) why one may want to convert indices of any structure (array, matrix, etc.) to int.
If you ever program in any language other than Matlab, you would be familiar with wanting to save memory space, especially with large structures. Being able to address elements in such structures with indices other than double is key.
One major issue with Matlab is the inability to more finely control the size of multidimensional structures in this way. There are sparse matrix solutions, but those are not adequate for many cases. Cell arrays will preserve the data types upon access, however the storage for every element in the cell array is extremely wasteful in terms of storage (113 bytes for a single uint8 encapsulated in a cell).
Premise: I found something that seems to be related to my problem, but I'm not sure how to use it, thus I'm asking a new question.
I have a cell matrix, call it A, which would look something like this:
[ 'string' 'string' 'number'
'string' 'string' 'number'
........................... ]
and I need to compare a cell array I just created, call it B = ['string' 'string' 'number'], with matrix A to see if B is already there somwhere. If I try touse ismember, matlab returns an error because an argument is not a string.
What should I do?
Thanks for the help
Your question is a bit unclear, so this answer is only valid if these assumptions are:
You really mean cell arrays and not char arrays in 2nd dimension as
your code snippets suggest.
Your cell arrays A and B have the same number of elements in the 2nd
dimension.
The following line will return a column vector of ones and zeros, where a one indicate a match of the B elements with a row in X:
sum(cellfun(#isequal,X,repmat(B,size(X,1),1)),2)==size(X,2)
Brief explanation:
repmat replicates B to the size of X.
cellfun compares every single element in the two matrices.
sum counts the number of string matches in each row.
== checks if all elements in a given row matches.
Hope it helps
Not exactly sure which variables you have, but this may work:
Turn everything into a string and then use ismember, for example:
['string' '_' 'string' '_' num2str(number)]
Make sure to do this on both inputs of ismember.
Depending on the size of your variables, it may be easier to just attach everything (or everything that is unique) to B and then run unique afterwards.
I'm working on a model to use matlab as graphical representation for other model. Therefore I'd like to have a matrix that can be updated with both letters and numbers. Numbers will represent a speed while for example '-' may represent a empty section. In the matlab documentation and on internet I found a lot of interesting tips, but not what I need.
Thanks in advance!
You cannot represent data of numeric type (integers/floating points) and data of char type in a matrix. However, you can, use cells, which are similar to matrices, and can hold different data types in each cell. Here's an example.
A={[1 2 3],'hello';'world',[4,5,6]'}
A =
[1x3 double] 'hello'
'world' [3x1 double]
Here the first cell contains a row vector, the second and third cells contain strings and the fourth cell contains a column vector. Indexing into a cell is similar to that of arrays, with one minor difference: use {} to group the indices. e.g., to access the element in the second row, first column, do
A{2,1}
ans =
world
You can also access an element of an array inside a cell like
A{2,2}(2)
ans =
5
If you're wanting to store mixtures of numeric and character type data, yoda has the correct suggestion: use cell arrays.
However, based on the example you described you may have another option. If the character entries in your matrix are there for the purpose of identifying "missing data", it may make more sense to use a purely numeric matrix containing unique values like NaN or Inf to identify data points that are empty or where data is not available.
When performing operations on your matrix, you would then have to index only elements that are finite (using, for example, ISFINITE) and perform your calculations on them. There are even some functions in the Statistics Toolbox that will perform operations ignoring NaN values. This may be a cleaner way to go since you can keep your matrix as a numeric type ('single' or 'double' precision) instead of having to mess with cell arrays.