I have a vector m which ranges from 1 to 12 randomly.
3 12 12 7 10 3 6 12 10 12
I have a conversion table
1 2 3 4 5 6 7 8 9 10 11 12
0.6 0.7 1.8 0.9 0.5 1.6 0.9 1.5 1.8 0.8 0.9 0.5
That means if m(1)==3, I want to change m(1) to be 1.8.
if m(2)==12, I want to change m(2) to be 0.5.
May I know what it the quickest way to do this conversion? Thank you.
This can be done with indexing
conversion_table = [0.6 0.7 1.8 0.9 0.5 1.6 0.9 1.5 1.8 0.8 0.9 0.5];
m = [3 12 12 7 10 3 6 12 10 12];
m = conversion_table(m)
Related
I have a time vector in Matlab which does not have consistent sampling time, ex. t = [0.1 0.2 0.3 0.4 0.5 0.6 0.7 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 2.9 3 3.1], I have another vector which is time based as a = [2 5 2 4 5 7 8 0 10 1 0 25 6 14 5 2 7 98], when I plot(t,a) there is straight line connecting the two points with larger sampling time, how can I remove these gaps where the sampling time is not consistent and it jumps to larger value? I know defining NaN between 0.7 and 1.3 and also 2 and 2.9 in t and also in a for the same interval might help, but how to distinguish if sampling time changes?
Maybe you can try the following codes, and here are two approaches that you can make it:
Approach 1: adding nan
clc;
clear;
close all;
t = [0.1 0.2 0.3 0.4 0.5 0.6 0.7 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 2.9 3 3.1]
a = [2 5 2 4 5 7 8 0 10 1 0 25 6 14 5 2 7 98]
dt = diff(t);
idx = find(dt > mode(dt));
tC = mat2cell(t',[idx(1),diff([idx,length(t)])]);
aC = mat2cell(a',[idx(1),diff([idx,length(t)])]);
nadd = dt(idx)/mode(dt);
T = [];
A = [];
for i = 1:length(nadd)
T = [T; tC{i};ones(int32(nadd(i)),1)*nan];
A = [A; aC{i};ones(int32(nadd(i)),1)*nan];
endfor
T = [T;tC{end}];
A = [A;aC{end}];
plot(T,A)
Approach 2: dividing vector by intervals
clc;
clear;
t = [0.1 0.2 0.3 0.4 0.5 0.6 0.7 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 2.9 3 3.1]
a = [2 5 2 4 5 7 8 0 10 1 0 25 6 14 5 2 7 98]
dt = diff(t);
idx = find(dt > mode(dt));
tC = mat2cell(t',[idx(1),diff([idx,length(t)])]);
aC = mat2cell(a',[idx(1),diff([idx,length(t)])]);
hold on;
arrayfun(#(k) plot(tC{k},aC{k}),1:(length(idx)+1));
I'm analyzing an induction motor, varying the frequency and absolute value of the stator current. Since the FEM-Tool only works with a current input, I need to vary the current over the frequency to obtain current-values of constant torque for each frequency.
To generate a mesh, I use 2 for-loops:
The outer loop sets the current.
The inner loop varies the frequency with said current, gets the machine's torque and finally, the matrices are appended adding the current stator-current, frequency and torque each in separate matrices. Plotted it looks like this:
Example of the plot using the raw data
For the plot I used smaller, more imprecise matrices and rather arbitrary values:
I_S = [ 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 ];
fre = [ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 ];
tor = [ 0 0.1 0.3 0.5 0.7 1 1.5 2 2.6 3.3 0 1.1 1.3 1.5 1.7 2 2.5 3 3.6 4.3 0 2.1 2.3 2.5 2.7 3 3.5 4 4.6 5.3 ];
While tor is shown as the colormap in the plot. Each matrix has a length of 30.
One simulation needs about 20-30 seconds. Thus, to get a precise mesh, the FEM-tool needs several hours to generate.
I would like to interpolate the spaces in between the known ones.
It seems that either the way of creating the matrices is the problem or the interp*...-functions of Octave/MATLAB simply don't work for this kind of interpolation.
Is there a way to achieve a mesh/grid-like interpolation from this type of matrices? I found many examples with x,y as variables and z as a math-function but rarely 3 linear/non-linear matrices.
Your data need to be in a meshgrid form, that is 2D:
// Known data
current = [0:2];
frequency = [0:9];
[current2D, frequency2D] = meshgrid(current,frequency);
torque2D = [ 0 0.1 0.3; 0.5 0.7 1; 1.5 2 2.6; 3.3 0 1.1; 1.3 1.5 1.7; 2 2.5 3; 3.6 4.3 0; 2.1 2.3 2.5; 2.7 3 3.5; 4 4.6 5.3 ];
// Interpolated data
currentToInterpolate = [0.5 1.5];
frequncyToInterpolate = [0.5 : 8.5];
[currentToInterpolate2D, frequencyToInterpolate2D] = meshgrid(currentToInterpolate,frequncyToInterpolate);
interpolatedTorque2D = interp2(current2D,frequency2D,torque2D,currentToInterpolate2D,frequencyToInterpolate2D);
Can someone help me on the below?
nColss:1 3 4 4.5;
aa:([]amount:250000+500000*5?10;n1M:0.5*5?4;n3M:2+0.5*5?4;n4M:4+0.5*5?4;n4.5M:6+0.5*5?4);
aa:update nRng:{[l;n] (min l | l l bin n),(l l binr n & max l)}[nColss] each aa[`amount]%1000000 from aa;
aa:update nRng2:{`$("n",'string x),'"M"} each aa[`nRng] from aa;
amount n1M n3M n4M n4.5M nRng nRng2
250000 1.5 2 4 7 1 1f `n1M`n1M
2250000 0.5 2 5 6.5 1 3f `n1M`n3M
4250000 1.5 2.5 5 6 4 4.5 `n4M`n4.5M
250000 1 3.5 4.5 7.5 1 1f `n1M`n1M
1250000 1 2.5 4 7 1 3f `n1M`n3M
How can I generate a column nValue containing for each line the value of the columns specified in the nRng2 column?
Something like this
nValue
1.5 1.5
0.5 2
5 6
1 1
1 2.5
I was trying something like
aa[aa[`nRng2]]
that generates
index value
0 (1.5 0.5 1.5 1 1;1.5 0.5 1.5 1 1)
1 (1.5 0.5 1.5 1 1;2 2 2.5 3.5 2.5)
2 (4 5 5 4.5 4;7 6.5 6 7.5 7)
3 (1.5 0.5 1.5 1 1;1.5 0.5 1.5 1 1)
4 (1.5 0.5 1.5 1 1;2 2 2.5 3.5 2.5)
then I would need to take the diagonal of this matrix, but I am stuck at it.
I get slightly different values in the aa table when I enter your example code, but something like this seems to work:
q)aa[`nValue]:{x x`nRng2} each aa
q)aa
amount n1M n3M n4M n4.5M nRng nRng2 nValue
-----------------------------------------------------
4750000 0.5 2 4.5 6 4.5 4.5 n4.5M n4.5M 6 6
1250000 0 3.5 5 6 1 3 n1M n3M 0 3.5
3750000 0.5 2.5 5.5 7 3 4 n3M n4M 2.5 5.5
250000 1 3 5 6.5 1 1 n1M n1M 1 1
750000 0 3 4.5 7 1 1 n1M n1M 0 0
To give a quick explanation of what this is doing; by doing each aa we are essentially passing each record from the table into the lambda function as a dictionary (a table in kdb+ is simply a list of dictionaries). Within this we index into the record with nRng2 to get the column names, and then index into the dictionary again using those column names. We then assign this using index notation to add a new column
As in this link, I have:
| 0.1 0.2 0.3 0.4
----------------------
1 | 10 11 12 13
2 | 11 12 13 14
3 | 12 13 14 15
4 | 13 14 15 16
Y = [0.1 0.2 0.3 0.4];
X = [1 2 3 4];
Z = [10 11 12 13; 11 12 13 14; 12 13 14 15; 13 14 15 16];
I plotted the surface Z using the command "surf(X,Y,Z)" in matlab. I got:
But really I don't understand the plotted surface. Can someone explain to me in details (in a text) what happens in this surface? For example: how can we observe the point (2,0.2,12)?
Include some labels and a colorbar and everything should be clear:
Y = [0.1 0.2 0.3 0.4];
X = [1 2 3 4];
Z = [10 11 12 13; 11 12 13 14; 12 13 14 15; 13 14 15 16];
surf(X,Y,Z)
colorbar
xlabel('X')
ylabel('Y')
zlabel('Z')
As suggested in the comments you can find your point on the surface by adding:
hold on;
plot3(2,0.2,12,'ro','MarkerSize',10,'MarkerFaceColor','r');
it then appears as a red dot.
Your table contains 16 points, these are plotted and the area inbetween, colored according to the applied colormap with the lowest z-value of the group of 4, which is according to the doc the surface height.
Actually it would be cleaner coding if you'd include the following line before the plot:
[X,Y] = meshgrid(X,Y);
this way all your input variables get the same dimensions:
X =
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
Y =
0.1 0.1 0.1 0.1
0.2 0.2 0.2 0.2
0.3 0.3 0.3 0.3
0.4 0.4 0.4 0.4
Z =
10 11 12 13
11 12 13 14
12 13 14 15
13 14 15 16
In case of surf the function does that for you, but other plotting functions are may not that tolerant.
Once again, sorry if this has been asked before and if its too specific but I'm very stuck and can't quite find a solution.
I have a matrix of say 3 members of a structure called 2, 4 and 16 (in column 1) that have values along their relative distance e.g. member 2 has values at the start, 0m, then at 0.5m then the end of its length 1.5m, where member 4 starts at 0m etc. So that my matrix looks like this:
2 0 125
2 0.5 25
2 1.5 365
4 0 25
4 0.6 57
16 0 354
16 0.2 95
16 0.8 2
and I want to create a matrix that has the overall distance along all the members 2, 4 and 16 combined:
2 0 125
2 0.5 25
2 1.5 365
4 1.5 25
4 2.1 57
16 2.1 354
16 2.3 95
16 3.1 2
is there any way to do this in matlab? Like possibly locating the first zero and adding the value above it to all the rest of the values below then find the next zero value and so on?
Please tell me if this isn't clear, I realise it's a bit confusing but not too sure how to explain it better!
I came up with the following:
idx = find(diff(M(:,1)));
v = zeros(size(M,1),1);
v(idx+1) = M(idx,2);
M(:,2) = M(:,2) + cumsum(v);
The result:
M =
2 0 125
2 0.5 25
2 1.5 365
4 1.5 25
4 2.1 57
16 2.1 354
16 2.3 95
16 2.9 2
Note the last value in the second column disagrees with what you described (2.9 vs 3.1). Either you had a typo, or I'm still not getting it...
data = [2 0 125;
2 0.5 25;
2 1.5 365;
4 0 25;
4 0.6 57;
16 0 354;
16 0.2 95;
16 0.8 2];
idx0 = find(data(:,2)==0);
idx0 = idx0(2:end); %ignore first zero of first member, doesn't need an offset
offset = data(idx0-1,2);
N = size(data,1);
for ii=1:numel(idx0)
idxs = 1:N>=idx0(ii);
data(idxs,2) = data(idxs,2) + offset(ii);
end