conditional assignment in dolphindb - matlab

A matlab-like conditional assignment statement works for vectors in dolphindb:
x=1 2 3
x[x<2]=2
x;
[2,2,3]
But looks like a conditional assignment statement on tables doesn't work in dolphindb:
t=table(1 2 3 as x, 4 5 6 as y)
t[`x][t[`x]<2]=2
Syntax Error: [line #2] Please use '==' rather than '=' as equal operator in non-sql expression.
Anyone knows how to do it on tables?

Code:
x = [1 1 4 3]';
y = [4 1 5 6]';
t = table(x,y);
t.x(x<2) = 2
Results:
t =
x y
_ _
2 4
2 1
4 5
3 6

Related

Without for loop, can I generate list [1 2 3 2 3 4 3 4 5 ...] in matlab?

Unlike Python, MATLAB list generation expression is limited. In MATLAB I am only allowed to do a:b:c. Can I generate a list [1 2 3 2 3 4 3 4 5 ...] in MATLAB without using for loop?
N = 3;
M = 4;
result = reshape((1:N).'+(0:M-1), 1, []);
gives
result =
1 2 3 2 3 4 3 4 5 4 5 6
How it works
(1:N).'+(0:M-1) uses implicit expansion to create the M×N matrix
1 2 3 ... M
2 3 4 ... M+1
3 4 5 ... M+2
...
N N+1 N+2 ... N+M-1
Then reshape(..., 1, []) reshapes this matrix into a row vector, reading the elements in column-major order (down, then across).
One approach would be to make three lists [1,2,3...], [2,3,4...] and [3,4,5...] and interleave them. Alternatively, you can take advantage of the pattern: [1,2,3,4,5,6,7,8,9]-[0,0,0,2,2,2,4,4,4]=[1,2,3,2,3,4,3,4,5]. The repelem() function is useful for this kind of operation.
You can try cell2mat + arrayfun like belwn
n = 3;
m = 3;
res = cell2mat(arrayfun(#(x) x+(1:n),1:m,'UniformOutput',false));
such that
res =
2 3 4 3 4 5 4 5 6

Matlab: Using a matrix as a mask to perform elementwise operations

In Matlab, I have two matrices: one with integers,x, and one with booleans, y:
x =
2 4 2
3 3 1
4 1 5
y =
0 0 1
1 1 0
1 0 1
What I now want to do is to assign some elements of x to 5, and I want to use y as a mask to determine which elements should be set to 5. So elements with a corresponding value of 0 in y should remain as they are in x, but those with a corresponding value of 1 in y should be set to 5. Therefore, the output should be:
2 4 5
5 5 1
5 1 5
I have tried the following:
x(y) = 5
Which gives me the error:
Subscript indices must either be real positive integers or logicals.
And I have also tried:
y(x) = 5
Which gives me the following:
5 5 1
5 1 0
5 0 1
Can somebody please explain what is going on here, and what I need to do to get my desired result?
The error you've got is due to the fact that, apparently, y is of type double while, in this case, it should be of type logical
You could try:
x(logical(y))=5
Hope this helps
Its not a fancy solution but will solve your problem
>> x = [ 2 4 2;3 3 1;4 1 5];
y = logical([ 0 0 1;1 1 0;1 0 1]);
f = x(:);
f(y(:)) = 5;
x = reshape(f,size(x))
x =
2 4 5
5 5 1
5 1 5
>>
x(find(y)) = 5; should work fine.

Assiging the maximum value of a column to the row

Say we have the following matrix
1 3 6
5 4 7
5 3 9
What I'm trying to do is for each row, I assign it the maximum value of the column. So, for instance, I'm expecting the following output:
x(1) = 6
x(2) = 7
x(3) = 9
I tried doing that using by writing the code below, but didn't get the expected putput:
x=[1 3 6;5 4 7; 5 3 9]
[rows, columns] = size(x);
for i=1:columns
for j=1:rows
[maximum, position] = max(x(j,:));
disp('MAXIMUM')
x(j)=maximum
end
end
What should I do to get the expected output?
You can use the built-in max function with a dimension specifier: max(x,[],dim).
In your case, assuming your matrix is called A:
>> x=max(A,[],2)
ans =
6
7
9
If I understood correctly your question, you can just use the max function. It naturally operates on columns, therfore, some transposition is necessary.
x=[1 3 6;5 4 7; 5 3 9]
y = max(x')'
y =
6
7
9
You can even reassing the values on the fly
x = max(x')'.

Sort a vector and count the identical occurrences

What is a Matlab-efficient way (no loop) to do the following operation: transform an input vector input into an output vector output such as output(i) is the number of integers in input that are less or equal than input(i).
For example:
input = [5 3 3 2 4 4 4]
would give:
output = [7 3 3 1 6 6 6]
First of all, don't use input for a variable name, it's a reserved keyword. I'll use X here instead.
An alternative way to obtain your desired result would be:
[U, V] = meshgrid(1:numel(X), 1:numel(X));
Y = sum(X(U) >= X(V))
and here's a one-liner:
Y = sum(bsxfun(#ge, X, X'))
EDIT:
If X has multiple rows and you want to apply this operation on each row, this is a little bit trickier. Here's what you can do:
[U, V] = meshgrid(1:numel(X), 1:size(X, 2));
V = V + size(X, 2) * idivide(U - 1, size(X, 2));
Xt = X';
Y = reshape(sum(Xt(U) >= Xt(V))', size(Xt))'
Example:
X =
5 3 3 2 4 4 4
3 9 7 7 1 2 2
Y =
7 3 3 1 6 6 6
4 7 6 6 1 3 3
I have found a possible answer:
output = arrayfun(#(x) sum(x>=input),input)
but it doesn't take advantage of vectorization.

Define function as interpolation of x,y data

I have 2 columns of x y data in data.txt like this:
0 0
1 1
2 4
3 9
4 16
5 25
Now I want to define a function f(x) where x is the first column and f(x) is the second column, and then be able to print values of this function like so:
f(2)
Which should give me 4.
How do I achieve this?
Assuming that you want some return value for numbers between the ones you have as reference, you can use linear interpolation:
function y= linearLut(x)
xl = [0 1 2 3 4 5];
yl = [0 1 4 9 16 25];
y = interp1(xl,yl,x);
end
A more generic version of the function might be:
function y= linearLut(xl,yl,x)
y = interp1(xl,yl,x);
end
And then you can create specific instances by using anonymous functions:
f = #(x)(linearLut([0 1 2 3 4],[0 1 4 9 16],x));
f(4);
You can import the file using textread(), then use find in order to select the right row.
Out of my head and untested:
function y = findinfile(x)
m = textread(data.txt)
ind = find(m(:,1)==x)
y = m(ind,2)
end
If you only need to find the correct value in the array (without interpolation) you can use:
function out=ff(b)
a = [0 1 2 3 4 5 ; 3 4 5 6 7 8]';
[c,d]=find(a(:,1)==b);
out = a(c,2);