Let's say I have some parameters such as a,b,c, and I need to store the test results by changing them.
The thing is that the the number of parameters will be keep increasing, so I can't keep them as static column.
For example :
Test 1 : a = 10, b = 20, c = 1
Test 2 : a = 11, b = 21, c = 11
Test 3 : a = 11, b = 20, c = 1
...
Test 1001 : d = 30
I thought about having a table for parameters as follows.
id name value
1 a 10
2 b 20
3 c 1
4 a 11
5 b 21
6 c 11
...
100 d 30
And a table for using the option. The orders are not important.
id usage
1 1-2-3
2 4-5-6
3 4-5-3
The problem for this approach is that the number of the option used for each test is not fixed. It can be 1, but it also can be 1-2-3-4-5-6-7.
Questions
Is there any better method for this problem? Not using two tables or someting?
If I have to use this method, how can I deal with the variable element problem? Use string or equivalent?
Take a look at this discussion.
Related
I have a set of values in the following pattern.
A B C D
1 5 6 11
2 6 5 21
3 7 3 42
4 3 7 22
1 2 3 54
2 3 2 43
3 4 3 27
4 3 2 14
I exported the every column into MATLAB workspace as follows.
A = xlsread('F:\R.xlsx','Complete Data','A2:A43');
B = xlsread('F:\R.xlsx','Complete Data','B2:B43');
C = xlsread('F:\R.xlsx','Complete Data','C2:C43');
D = xlsread('F:\R.xlsx','Complete Data','D2:D43');
I need help with code where the it has to check the Column A, find the lowest D value and output the corresponding B and C values. I need the output to look like.
1 5 6 11
2 6 5 21
3 4 3 27
4 3 2 14
I read through related questions and understand that I need to make it a matrix and sort it based on the element on the 4th column using
sortrows
and get indices of the sorted elements. But I am stuck here. Please Guide me.
You can export those columns in one go as:
ABCD = xlsread('F:\R.xlsx','Complete Data','A2:D43');
Now use sortrows to sort the rows according to the first and the fourth column.
req = sortrows(ABCD, [1 4]);
☆ If all elements of the first column exist twice then:
req = req(1:2:end,:);
☆ If it is not necessary that all elements of the first column will exist twice then:
[~, ind] = unique(req(:,1));
req = req(ind,:);
I have below set of data.
LLimit ULimit Col C
1 3 a
3 5 b
5 11 c
11 15 d
15 17 e
17 20 f
in col D if i enter 3.5 i need result in col E as "b" (corrosponding value to lowerlimit and upper limit). I have used If or statement, However is there a way i can do this using Index, Match or array. I tried and it works absolutely fine with the limit numbers (like 5, 11, 17, 3 etc) but not working with between numbers like 14 (between 11 and 14).
Below is what i used
{=INDEX(F5:F10,MATCH(1,(((D5:D10)>=H4)*((E5:E10)>=H4))*1,0))}
Was trying to attach workbook, but don't know how to do it.
Try this
Assuming D2=3.5 then
In E2
=INDEX(C2:C7,SUMPRODUCT((A2:A7<=D2)*(B2:B7>=D2)*(ROW(C2:C7)-ROW(C2)+1)))
Edit:
To exclude the lower boundary, try this
=INDEX(C2:C7,SUMPRODUCT((A2:A7<D2)*(B2:B7>=D2)*(ROW(C2:C7)-ROW(C2)+1)))
Use Vlookup as follow:
=VLOOKUP(D2,$A$2:$C$7,3)
$A$2:$C$7 is your initial table LLimit ULimit Col C
Vlookup will look in the first column for the value <= D2 and return the corresponding value in column 3
Update
For non sorted column A your Formula needs a modification:
={INDEX($C$2:$C$7,MATCH(1,($A$2:$A$7<=D2)*($B$2:$B$7>=D2),0),1)}
You wrote the same condition >= for both limit
{=INDEX($F$5:$F$10,MATCH(1,((($D$5:$D$10)<=H4)*(($E$5:$E$10)>=H4))*1,0))}
To be clear the following is not my original problem which has data that is much larger and this code is in the context of a larger application and code base. I have reduced my work to the simplest example that’s now at toy or didactic size for clarity and dev and unit testing because that helps a lot for these purposes as well as for sharing on stackexchange. I am experienced in R but not in octave (Matlab). This is code for octave version 4.0.0. I seem to be stuck on translating group computations such as R’s tapply() or by() as well as writing and calling user defined functions (plus a bit of additional processing than those built-ins), but now written in the octave language.
Starting state is an array a as shown:
a = [5 1 8 0; 2 1 9 0; 2 3 3 0; 5 3 9 0]
a =
5 1 8 0
2 1 9 0
2 3 3 0
5 3 9 0
The process I need to do is essentially just this: Group by column 1, find the min statistic in column 3, return the value stored in column 2 of the same row, and write the value to column 4. I want no optional packages to be used. The built-in accumarray and min functions together get me pretty close but I’ve not found the needed syntax. Matlab seems to have many versions of parameter passing syntaxes developed over different releases and please note my code needs to run in Octave 4.0.0.
Final state desired is same array a, but column 4 is updated as shown:
a =
5 1 8 1
2 1 9 3
2 3 3 3
5 3 9 1
My best few code snippets of near-misses and most interesting things among all my failed attempts (not shown, as there are many pages of attempts that do not work) are:
[x,y] = min(a(a(:,1)==5,3),[],1)
x = 8
y = 1
Notice that y is index of row within the group, but not row within the a array, which is fine and good as long as I later do a computation to translate indexes from group-relative to global-relative, and inside there read the value of a(y,2) which is the correct answer value for each row.
>> [x,y] = min(a(a(:,1)==2,3),[],1)
x = 3
y = 2
>> [~,y] = min(a(a(:,1)==2,3),[],1);
>> y
y = 2
Notice that y is all I need from min() since it’s the index of the row of interest.
>> accumarray(a(:,1), a(:,3), [], #([~,y]=min([],[],1)))
parse error:
syntax error
Notice that with some kind of syntax I need to pass to min() in its first parameter the group of values determined by parameters 1 and 2 of accumarray.
I ultimately need to have something like this happen within the group computations after min() returns row index y:
a(y,4) = a(y,2); % y is the desired row index found by min() within each group
So, I tried to write a function that’s named for possibly simpler syntax:
>> function idx = ccen(d)
[~,y]=min(d,[],1);
idx=a(y,2);
end
>> accumarray(a(:,1), a(:,3), [], #ccen)
error: 'a' undefined near line 3 column 5
error: called from
ccen at line 3 column 4
accumarray at line 345 column 14
Seems to me, that to my surprise, a is not accessible to function ccen. Now what can I do? Thank you for reading.
When declaring functions in MATLAB / Octave, any variables declared outside the scope (by default) are not accessible. This means that even though you have a declaration for a, when you create that function, a is not accessible within the scope of the function.
What you can do is modify ccen so that a is supplied to the function so it can access the variable when the function is being called. After, wrap an anonymous function around your call to ccen when calling accumarray. Anonymous functions however do have the luxury of capturing the scope of variables that aren't explicitly declared as input variables into the function:
So first:
function idx = ccen(a, d) %// Change
[~,y]=min(d,[],1);
idx=a(y,2);
end
And now...
out = accumarray(a(:,1), a(:,3), [], #(x) ccen(a,x)); %// Change last parameter
This call is acceptable because the anonymous function is capturing a at the time of creation. Notice how x in the anonymous function is what is piped in from the accumarray calls. You're simply forwarding that as the second parameter to ccen and keeping a constant. This doesn't change the way the function is being run.... it's just resolving a scope issue.
I get the following in Octave:
octave:10> a = [5 1 8 0; 2 1 9 0; 2 3 3 0; 5 3 9 0]
a =
5 1 8 0
2 1 9 0
2 3 3 0
5 3 9 0
octave:11> function idx = ccen(a,d)
> [~,y]=min(d,[],1);
> idx=a(y,2);
> end
octave:12> out = accumarray(a(:,1), a(:,3), [], #(x) ccen(a,x))
out =
0
1
0
0
1
I know I can intertwine 2 arrays by
C = [A(:),B(:)].'; %'
D = C(:)
But how can I intertwine 3 arrays with a (pendulum type of pattern going back and forth) See image below with arrows showing the intertwining path pattern I'm trying to get (each column is an array). Also the number pattern I'm trying to get is also next to it, in one large column. Please note the numerical values are just examples to make it easier to read. the numerical values could be decimals also
I tried the code below but the pattern is incorrect.
A=[1,2,3,4,5]
B=[10,20,30,40,50,60,70,80,90]
C=[100,200,300,400,500]
D = [A(:),B(:),C(:)].'; %'
E = D(:)
I get an error in the D array due to the fact that the B array is a larger size than A and C but the number pattern is also not following the pattern I'm trying to get.
1
10
100
2
20
200
3
30
300
4
40
400
5
50
500
error: horizontal dimensions mismatch (5x1 vs 9x1)
The pattern from the 3 arrays I'm trying to get is below.
Please note the numerical values are just examples to make it easier to read. the numerical values could be decimals also
1
10
100
20
2
30
200
40
3
50
300
60
4
70
400
80
5
90
500
PS: I'm using Octave 3.8.1 which is like matlab
Have you tried the following?
D = zeros(4 * size(A, 2) - 1, 1); % initialization
D(1 : 4 : end) = A;
D(2 : 2 : end) = B;
D(3 : 4 : end) = C;
I have a 12-D array and am using each dimension as an index value in an optimization problem.
A(:,:,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10)
each index value i is a value from 1 to 5.
I want to sort A from greatest to least and keep track of the indices so I know which indices correspond to to what value of A.
So my ideal output would be a 2 column cell/array with one column being the value and the other other column being the index values.
For a simple 3D example: say I have a 3D array: A(:,:,i1).
Where:
A(:,:,1) = 2
A(:,:,2) = 6
A(:,:,3) = 13
A(:,:,4) = 11
A(:,:,5) = 5
I would like my output to be:
13 3
11 4
6 2
5 5
2 1
EDIT:
assume I have 1x1x3x3 sized input such that
A(1,1,1,1) = 3
A(1,1,2,1) = 1
A(1,1,3,1) = 23
A(1,1,1,2) = 12
A(1,1,2,2) = 9
A(1,1,3,2) = 8
A(1,1,1,3) = 33
A(1,1,2,3) = 14
A(1,1,3,3) = 6
the expected output would be:
33 [1,1,1,3]
23 [1,1,3,1]
14 [1,1,2,3]
12 [1,1,1,2]
9 [1,1,2,2]
8 [1,1,3,2]
6 [1,1,3,3]
3 [1,1,1,1]
1 [1,1,2,1]
This should be a generic code for any multi-dimensional input array -
%// Sort A and get the indices
[sorted_vals,sorted_idx] = sort(A(:),'descend');
%// Set storage for indices as a cell array and then store sorted indices into it
c = cell([1 numel(size(A))]);
[c{:}] = ind2sub(size(A),sorted_idx);
%// Convert c to the requested format and concatenate with cell arary version of
%// sorted values for the desired output
out = [num2cell(sorted_vals) mat2cell([c{:}],ones(1,numel(A)),numel(size(A)))];
The generic code owes its gratitude to this fine solution.
I guess this is what you want:
b=A(:);
[sorted_b,ind]=sort(b,'descend');
[dim1,dim2,dim3,dim4]=ind2sub(size(A),ind);
%arranging in the form you want
yourCell=cell(size(b,1),2);
yourCell(:,1)=mat2cell(sorted_b,ones(size(b,1),1),1);
%arranging indices -> maybe vectorized way is there for putting values in "yourCell"
for i=1:size(b,1)
yourCell{i,2}=[dim1(i) dim2(i) dim3(i) dim4(i)];
end
For the array A, given by you, my output looks like:
33 [1,1,1,3]
23 [1,1,3,1]
14 [1,1,2,3]
12 [1,1,1,2]
9 [1,1,2,2]
8 [1,1,3,2]
6 [1,1,3,3]
3 [1,1,1,1]
1 [1,1,2,1]
which matches with your output.