简体   繁体   中英

2D table conversion for example: y = f(x1,x2) => x1 = f(y, x2)

The problem I need to resolve is to convert 2D look-up table.

在此处输入图片说明

This table could be defined as an array

Table = [ -54 97 ... 362;
          -60 114 ... 425;
          ...
          -111 31 ... 277;]

x1 = [0 20 ... 100]
x2 = [800 1200 ... 4800].

So given any x1 , x2 within the arrange, y = f(x1,x2) defined by the above table could give a y value.

Now, I need to get x1 given y and x2 . That is, given rpm and y value, figure out appropriate x1 . for example, 800 rpm and 97, gives value 20%. If it is 800 and 107, returns 28.3%.

Either Matlab or Python could be used.

In Matlab:

My other answer assumed the most general case where the value for the RPM could be anything in the range of 800 to 4800. However, if you're certain that your chosen value will be one of the rows, you need only consider the values in that row:

Percent = [0 20 30 40 ... 90 100];
RPM = [800; 1200; 1400; ... 4400; 4800];
Table = [ -54 97 ... 362;
          -60 114 ... 425;
          ...
          -111 31 ... 277;]
x2 = 800;
y = 107;

RPM_id = find(RPM == x2,1);
Table_row = Table(RPM_id,:);
x1 = interp1(Table_row,Percent,y)

Which once again results in

x1 =
   28.3333

To avoid multiple construction of interpolation, I propose to use griddedInterpolant so that all interpolants are built once and then you can query ad libitum.

Note that you should think about interpolation, that is what numerical scheme you want to use to compute values that do not belong to the initial table (like (800;107) in the OP). Basic (and default) scheme is linear interpolation; with your table (not uniform), higher order interpolation schemes may be amongst 'makima' and 'spline'. See the doc for more info about all of this.

Code for building the interpolant is as follows, assuming that the whole table is stored in variable T :

rpm = [800 1200 1400 1600:400:4800];
N = [0 20:10:100];
[g_rpm, g_N] = meshgrid(rpm, N);
G = griddedInterpolant(rpm, N ,T);

Add a fourth parameter to specify the interpolation scheme (eg 'makima' ).

Then, to find the desired value, you can build your own function as follows:

F = @(r, t) fminsearch(@(x) abs(t-G(r,x)), 50);

50 is a priori startint value; you must refine it in case T is not montonic.

On the inputs in the OP:

F(800, 97) gives 20

F(800, 107) gives 28.333 (with linear interpolation, 28.224 with makima interpolation and 26.898 with spline interpolation)

Enhancement

In the case you want to vectorize the computation, you can do this by enclosing the body of function F with arrayfun :

F = @(R,T) arrayfun(@(r,t) fminsearch(@(x) abs(t-G(r,x)), 25), R, T);

So now you can put several couple of inputs at once like this:

F([800 2000],[100 100])

ans =

       21.966       15.564

In Matlab:

The general case is where x2 value is not an element of the RPM vector. If it is sure to be so, you can convert the below 2D interpolation into a 1D interpolation. But for the general case you can guess an x1, interpolate (x1,x2) into your table and see if the resultant value equals your y value.

Percent = [0 20 30 40 ... 90 100];
RPM = [800; 1200; 1400; ... 4400; 4800];
Table = [ -54 97 ... 362;
          -60 114 ... 425;
          ...
          -111 31 ... 277;]


x2 = 800;
y = 107;

% we square the difference since we want the error to be > 0
F = @(s) (interp2(Percent, RPM, Table,s,x2) - y).^2; 

x1 = fminbnd(@(x) F(x),0,100) 

Which results in

x1 =
   28.3333

Edit: A previous version of this solution was based on evenly-distributed values for percents. There is no column for 10% so the answer for the example was wrong. The solution has been updated to reflect the correct percentages.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM