Adjusting table columns by a grouped value

When working with my dataset, I find that I need to adjust the data in ways that makes the plots more understandable. In this particular example, I'm trying to adjust the times in a table by finding the minimum value for every run, then subtracting the minimum value to every run so that each run in my dataset all start at t=0 on a plot.
I can find the mimium value, and have created a table with those values, however I am not sure how to apply these values to the main table, so that I can create an additional column with the adjusted time. I believe it has something to do with rowfun, but I can't figure out how to get around the different sizes of the rows to get a proper calculation. I will be adding what I have so far in an attachment. Thank you.
EDIT:
If it'll make any sense, I'm trying to do something akin to this in the code:
adjtfcn= @(times,mintime)(minus(times,mintime));
test.adjtimes=rowfun(adjtfcn,...
test, "inputvariables", [test.times,mint.min_times],...
"groupingvariables","cycleNumber")

 Accepted Answer

One optiopn is to sue findgroups and then accumarray to create the different tables. They need to be separate since they are differnt lengths. The results appear to be sorted correctly by the ‘times’ variable.
Try this —
load('test')
whos('-file','test')
Name Size Bytes Class Attributes mint - 4683 table test - 1015708 table
mint
mint = 26x3 table
cycleNumber GroupCount min_times ___________ __________ __________ 0 7176 300.03 1 7016 71966 2 1667 1.4203e+05 3 3263 1.759e+05 4 3203 2.0843e+05 5 3148 2.4037e+05 6 3100 2.7176e+05 7 4390 3.0266e+05 8 1833 3.6557e+05 9 1691 3.8382e+05 10 1656 4.0064e+05 11 1634 4.1711e+05 12 1616 4.3336e+05 13 5676 4.4942e+05 14 534 5.0608e+05 15 443 5.1133e+05
test
test = 59499x3 table
cycleNumber times EcellV ___________ ______ ______ 0 300.03 3.6273 0 300.03 3.6289 0 310.03 3.6984 0 320.03 3.7031 0 330.03 3.7052 0 340.03 3.7065 0 350.03 3.7074 0 360.03 3.708 0 370.03 3.7084 0 380.03 3.7085 0 390.03 3.7088 0 400.03 3.7089 0 410.03 3.7089 0 420.03 3.709 0 430.03 3.7091 0 440.03 3.709
[G,id] = findgroups(test.cycleNumber);
Result = accumarray(G, (1:numel(G)).', [], @(x){test(x,:)})
Result = 26x1 cell array
{7176x3 table} {7016x3 table} {1667x3 table} {3263x3 table} {3203x3 table} {3148x3 table} {3100x3 table} {4390x3 table} {1833x3 table} {1691x3 table} {1656x3 table} {1634x3 table} {1616x3 table} {5676x3 table} { 534x3 table} { 443x3 table}
Result{1}
ans = 7176x3 table
cycleNumber times EcellV ___________ ______ ______ 0 300.03 3.6273 0 300.03 3.6289 0 310.03 3.6984 0 320.03 3.7031 0 330.03 3.7052 0 340.03 3.7065 0 350.03 3.7074 0 360.03 3.708 0 370.03 3.7084 0 380.03 3.7085 0 390.03 3.7088 0 400.03 3.7089 0 410.03 3.7089 0 420.03 3.709 0 430.03 3.7091 0 440.03 3.709
Result{end}
ans = 4374x3 table
cycleNumber times EcellV ___________ __________ ______ 25 5.856e+05 3.8021 25 5.856e+05 3.8025 25 5.8561e+05 3.8104 25 5.8562e+05 3.8122 25 5.8563e+05 3.8134 25 5.8564e+05 3.8143 25 5.8565e+05 3.8151 25 5.8566e+05 3.8159 25 5.8567e+05 3.8165 25 5.8568e+05 3.817 25 5.8569e+05 3.8175 25 5.857e+05 3.818 25 5.8571e+05 3.8185 25 5.8572e+05 3.8191 25 5.8573e+05 3.8194 25 5.8574e+05 3.8199
.

5 Comments

Desmond
Desmond on 23 Aug 2024
Edited: Desmond on 23 Aug 2024
So if I understand this correctly, this is making 26 different tables? If that's the case, how would I reference them all when making the plot? Also, if I'm understanding this correctly, even if I do this, I still have the issue where despite separating them into different tables, they still aren't corrected by the time value.
Perhaps I should explain it in a different way. Let's take Result{1} for instance. The minimum time value for that one is 300.03. I want to take all of the time values in Result{1}, and subtract them at 300.3, so that they start from 0. I want to do this for all of the groups, so when I plot them, they all start at 0. Currently, if I plot them, say using gscatter(), I end up getting them starting at when they started in the tests instead of 0.
That way, the data would look something like this:
cycleNumber times EcellV
___________ ______ ______
0 0 3.6273
0 0 3.6289
0 10.03 3.6984
That’s an easy fix. For every table, subtract the first time value from the resto f them.
load('test')
whos('-file','test')
Name Size Bytes Class Attributes mint - 4683 table test - 1015708 table
mint
mint = 26x3 table
cycleNumber GroupCount min_times ___________ __________ __________ 0 7176 300.03 1 7016 71966 2 1667 1.4203e+05 3 3263 1.759e+05 4 3203 2.0843e+05 5 3148 2.4037e+05 6 3100 2.7176e+05 7 4390 3.0266e+05 8 1833 3.6557e+05 9 1691 3.8382e+05 10 1656 4.0064e+05 11 1634 4.1711e+05 12 1616 4.3336e+05 13 5676 4.4942e+05 14 534 5.0608e+05 15 443 5.1133e+05
test
test = 59499x3 table
cycleNumber times EcellV ___________ ______ ______ 0 300.03 3.6273 0 300.03 3.6289 0 310.03 3.6984 0 320.03 3.7031 0 330.03 3.7052 0 340.03 3.7065 0 350.03 3.7074 0 360.03 3.708 0 370.03 3.7084 0 380.03 3.7085 0 390.03 3.7088 0 400.03 3.7089 0 410.03 3.7089 0 420.03 3.709 0 430.03 3.7091 0 440.03 3.709
VN = test.Properties.VariableNames;
[G,id] = findgroups(test.cycleNumber);
Result = accumarray(G, (1:numel(G)).', [], @(x){test(x,:)})
Result = 26x1 cell array
{7176x3 table} {7016x3 table} {1667x3 table} {3263x3 table} {3203x3 table} {3148x3 table} {3100x3 table} {4390x3 table} {1833x3 table} {1691x3 table} {1656x3 table} {1634x3 table} {1616x3 table} {5676x3 table} { 534x3 table} { 443x3 table}
for k = 1:numel(Result)
Result{k}.times = Result{k}.times - Result{k}.times(1);
end
Result{1}
ans = 7176x3 table
cycleNumber times EcellV ___________ ______ ______ 0 0 3.6273 0 0.002 3.6289 0 10.002 3.6984 0 20.002 3.7031 0 30.002 3.7052 0 40.002 3.7065 0 50.002 3.7074 0 60.002 3.708 0 70.002 3.7084 0 80.002 3.7085 0 90.002 3.7088 0 100 3.7089 0 110 3.7089 0 120 3.709 0 130 3.7091 0 140 3.709
Result{end}
ans = 4374x3 table
cycleNumber times EcellV ___________ ______ ______ 25 0 3.8021 25 0.002 3.8025 25 10.002 3.8104 25 20.002 3.8122 25 30.002 3.8134 25 40.002 3.8143 25 50.002 3.8151 25 60.002 3.8159 25 70.002 3.8165 25 80.002 3.817 25 90.002 3.8175 25 100 3.818 25 110 3.8185 25 120 3.8191 25 130 3.8194 25 140 3.8199
figure
hold on
for k = 1:numel(Result)
plot(Result{k}.times, Result{k}.EcellV, 'DisplayName',sprintf('Cycle # %2s',Result{k}.cycleNumber(1)))
end
hold off
grid
xlabel(VN{2})
ylabel(VN{3})
legend('Location','eastoutside')
Does this look correct?
.
Yes that's exactly what I'm looking for. Thanks! Really the only thing I need to figure out left is the color coding, since matlab has so few options!
There are three ways to specify the color of a line, as shown on this documentation page. There are only 8 that are named or have "short names" (red, green, blue, cyan, magenta, yellow, black, and white) but you can specify an RGB triplet or a hex color code. For example, if I want a line with a lot of blue, some red, and only a dash of green:
c = [0.4 0.1 0.9];
plot(1:10, 1:10, 'Color', c, 'LineWidth', 4) % Make it thick so it's easy to see
That's not a half bad purple. Or I could have used a hex color code. For a lot of red, some green, and only a little blue:
c = '#E08018';
figure
plot(1:10, 1:10, Color = c, LineWidth = 4)
I'd call that orange or maybe a dark mustard. [Naming colors can be tricky.]
As always, my pleasure!
Perhaps this —
load('test')
whos('-file','test')
Name Size Bytes Class Attributes mint - 4683 table test - 1015708 table
mint
mint = 26x3 table
cycleNumber GroupCount min_times ___________ __________ __________ 0 7176 300.03 1 7016 71966 2 1667 1.4203e+05 3 3263 1.759e+05 4 3203 2.0843e+05 5 3148 2.4037e+05 6 3100 2.7176e+05 7 4390 3.0266e+05 8 1833 3.6557e+05 9 1691 3.8382e+05 10 1656 4.0064e+05 11 1634 4.1711e+05 12 1616 4.3336e+05 13 5676 4.4942e+05 14 534 5.0608e+05 15 443 5.1133e+05
test
test = 59499x3 table
cycleNumber times EcellV ___________ ______ ______ 0 300.03 3.6273 0 300.03 3.6289 0 310.03 3.6984 0 320.03 3.7031 0 330.03 3.7052 0 340.03 3.7065 0 350.03 3.7074 0 360.03 3.708 0 370.03 3.7084 0 380.03 3.7085 0 390.03 3.7088 0 400.03 3.7089 0 410.03 3.7089 0 420.03 3.709 0 430.03 3.7091 0 440.03 3.709
VN = test.Properties.VariableNames;
[G,id] = findgroups(test.cycleNumber);
Result = accumarray(G, (1:numel(G)).', [], @(x){test(x,:)});
for k = 1:numel(Result)
Result{k}.times = Result{k}.times - Result{k}.times(1);
end
% Result{1}
%
% Result{end}
cm = colormap(turbo(numel(Result)));
figure
hold on
for k = 1:numel(Result)
plot(Result{k}.times, Result{k}.EcellV, 'DisplayName',sprintf('Cycle # %2s',Result{k}.cycleNumber(1)), 'Color',cm(k,:))
end
hold off
grid
xlabel(VN{2})
ylabel(VN{3})
legend('Location','eastoutside')
Choose whatever colormap you want.
.

Sign in to comment.

More Answers (0)

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Products

Release

R2024a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!