Obtain each residue with MultiNonlinearModelFit global analysis

Dear All,
I use the MultiNonlinearModelFit function to carry out a global analysis of several chemical kinetics (Absorbance vs. time). It works well but I would like to retrieve the residues for each kinetic separately?
Is there a quick way or do I have to do it by hand for each kinetics?
I tried to use “FitResiduals” (see the code below with 2 kinetics), but it gives me a single vector without the x-coordinate and I guess that corresponds to the residuals for one of the kinetics.

If you have any idea how to do this quickly (I have 15 kinetics to analyze at a time, that’s a lot!), I’ll be glad you share it!
Thank you in advance for your advice and help.
Hélène

Clear[k3, k4, ea360, eh360, ef360, ea380, eh380, ef380]
sol = ParametricNDSolve[{Derivative[1][ag][t] == -k3*ag[t], 
    Derivative[1][gox][t] == k3*ag[t], 
    Derivative[1][h][t] == k3*ag[t] - 2*k4*h[t]*h[t], 
    Derivative[1][ff][t] == 2*k4*h[t]*h[t], ag[0] == 0.000006, 
    h[0] == 0, gox[0] == 0, ff[0] == 0}, {ag, gox, h, ff}, {t, 0, 
    2000}, {k3, k4}];
{agFunc, goxFunc, hFunc, fFunc} = {ag, gox, h, ff} /. sol;
model360[k3_, k4_, ea360_, eh360_, ef360_][
   t_] := (((agFunc[k3, k4][t])*ea360) + (eh360*
      hFunc[k3, k4][t]) + (ef360*fFunc[k3, k4][t]));
model380[k3_, k4_, ea380_, eh380_, ef380_][
   t_] := (((agFunc[k3, k4][t])*ea380) + (eh380*
      hFunc[k3, k4][t]) + (ef380*fFunc[k3, k4][t]));
fit = MultiNonlinearModelFit[{Abs360, 
    Abs380}, {model360[k3, k4, ea360, eh360, ef360][t], 
    model380[k3, k4, ea380, eh380, ef380][t]}, {{k3, 0.1}, {k4, 
     450}, {ea360, 5000}, {eh360, 1500}, {ef360, 3000}, {ea380, 
     5000}, {eh380, 2000}, {ef380, 2000}}, {t}];
mle = fit["BestFitParameters"]
Show[ListPlot[{Abs360, Abs380}], 
 Plot[{model360[k3, k4, ea360, eh360, ef360][t] /. mle, 
   model380[k3, k4, ea380, eh380, ef380][t] /. mle}, {t, 0, 310}]]
residu = fit["FitResiduals"]
ListPlot[residu]

I’m going to assume that you’re using my repository function, in which case I’m glad to hear that it’s of use to you.

Without the exact details of the datasets, I cannot completely answer your question, but it comes down to this: MultiNonlinearModelFit internally joins all datasets together into a single one. This means that fit["FitResiduals"] has all of the residuals you need; you just need to split them up again. Concretely, you should have

Length @ fit["FitResiduals"] === Total[Length /@ {Abs360, Abs380}]

So Take[fit["FitResiduals"], Length[Abs360]] should get you the residuals for the first dataset and Drop[fit["FitResiduals"], Length[Abs360]] should give you those for the other one.

Dear Sjoerd,
Thank you so much for your kind help and for this very useful function. Yes I’m using your repository function! I really appreciate and this function saves me precious time!

Your solution to separate the residues is doing well. I tried to adapt it to my case where I have at least 15 kinetics and therefore 15 residues at the end.
I found the following example to extract the 2nd set of residues, but I guess it should be more elegant. Note that, finally, the dimension of all the data vector is the same.

Take[fit["FitResiduals"], {Length[Abs360] + 1, 2*Length[Abs360]}]

In addition, to associate x coordinates (given by the data vector Xdata) to each residue vector, I use Timeseries like this

`res360 = TimeSeries[residu360, {Xdata}] 

But isn’t there another way of associating x-coordinates?

Below, two different kinetics.

Many thanks
Hélène

Abs360 = {{0.1, 0.020578}, {0.2, 0.0206772}, {0.3, 0.0201706}, {0.4, 
   0.0203716}, {0.5, 0.0201917}, {0.6, 0.0198135}, {0.7, 
   0.0199346}, {0.8, 0.0196224}, {0.9, 0.0195781}, {1, 
   0.0196144}, {1.1, 0.0192659}, {1.2, 0.0193823}, {1.3, 
   0.0191421}, {1.4, 0.0189982}, {1.5, 0.0193048}, {1.6, 
   0.0189436}, {1.7, 0.0188917}, {1.8, 0.0191417}, {1.9, 
   0.0187902}, {2, 0.0188375}, {2.1, 0.0189052}, {2.2, 
   0.0183759}, {2.3, 0.0187808}, {2.4, 0.0185128}, {2.5, 
   0.0183641}, {2.6, 0.0186758}, {2.7, 0.0184845}, {2.8, 
   0.0184009}, {2.9, 0.0185606}, {3, 0.0183937}, {3.1, 
   0.0184206}, {3.2, 0.0183251}, {3.3, 0.0183891}, {3.4, 
   0.0183389}, {3.5, 0.0183337}, {3.6, 0.018388}, {3.7, 
   0.0184438}, {3.8, 0.0182679}, {3.9, 0.0184027}, {4, 
   0.0183829}, {4.1, 0.0182594}, {4.2, 0.0184188}, {4.3, 
   0.0181372}, {4.4, 0.0182514}, {4.5, 0.0181963}, {4.6, 
   0.0181273}, {4.7, 0.0182523}, {4.8, 0.0182289}, {4.9, 
   0.0182162}, {5, 0.0184325}, {5.1, 0.0184163}, {5.2, 
   0.0181779}, {5.3, 0.0184368}, {5.4, 0.0181866}, {5.5, 
   0.0183913}, {5.6, 0.0184662}, {5.7, 0.0181838}, {5.8, 
   0.0184663}, {5.9, 0.0182806}, {6, 0.0182477}, {6.1, 
   0.018397}, {6.2, 0.0181889}, {6.3, 0.0186968}, {6.4, 
   0.0183699}, {6.5, 0.0182666}, {6.6, 0.0185456}, {6.7, 
   0.0183102}, {6.8, 0.018459}, {6.9, 0.0184074}, {7, 
   0.0183427}, {7.1, 0.0185573}, {7.2, 0.0186108}, {7.3, 
   0.0183396}, {7.4, 0.0186407}, {7.5, 0.0186582}, {7.6, 
   0.0184255}, {7.7, 0.0187252}, {7.8, 0.0184347}, {7.9, 
   0.0183682}, {8, 0.0187422}, {8.1, 0.0184937}, {8.2, 
   0.0184836}, {8.3, 0.0186525}, {8.4, 0.0182987}, {8.5, 
   0.0185847}, {8.6, 0.0186894}, {8.7, 0.0185912}, {8.8, 
   0.0186902}, {8.9, 0.018508}, {9, 0.0185523}, {9.1, 
   0.0188243}, {9.2, 0.0184394}, {9.3, 0.0187197}, {9.4, 
   0.0188471}, {9.5, 0.0185477}, {9.6, 0.0187264}, {9.7, 
   0.0187072}, {9.8, 0.0187788}, {9.9, 0.0189129}, {10, 
   0.0187566}, {12, 0.0187736}, {14, 0.0188994}, {16, 0.0190955}, {18,
    0.019202}, {20, 0.0194405}, {22, 0.0195111}, {24, 0.0197144}, {26,
    0.0198916}, {28, 0.0200099}, {30, 0.0201967}, {32, 0.020273}, {34,
    0.0204846}, {36, 0.0206786}, {38, 0.0207093}, {40, 
   0.0208471}, {42, 0.0210193}, {44, 0.0211584}, {46, 0.0212226}, {48,
    0.0214754}, {50, 0.0214993}, {52, 0.0215167}, {54, 
   0.0216675}, {56, 0.0218844}, {58, 0.0219545}, {60, 0.0220378}, {62,
    0.0221628}, {64, 0.0222014}, {66, 0.0223362}, {68, 
   0.0224844}, {70, 0.0225561}, {72, 0.02266}, {74, 0.0227757}, {76, 
   0.0228907}, {78, 0.0229685}, {80, 0.0229929}, {82, 0.0231938}, {84,
    0.0232257}, {86, 0.0233388}, {88, 0.0234633}, {90, 0.023574}, {92,
    0.023637}, {94, 0.0237275}, {96, 0.0238103}, {98, 0.023883}, {100,
    0.0239616}, {102, 0.0240022}, {104, 0.0242009}, {106, 
   0.0242503}, {108, 0.0242852}, {110, 0.0242963}, {112, 
   0.0244763}, {114, 0.0244621}, {116, 0.0246056}, {118, 
   0.0246208}, {120, 0.0246888}, {122, 0.0247914}, {124, 
   0.0249202}, {126, 0.0249675}, {128, 0.0250516}, {130, 
   0.025148}, {132, 0.0251178}, {134, 0.0251709}, {136, 
   0.0252728}, {138, 0.0253096}, {140, 0.0253722}, {142, 
   0.0253175}, {144, 0.0254264}, {146, 0.0254797}, {148, 
   0.025505}, {150, 0.025691}, {152, 0.0256809}, {154, 
   0.0256734}, {156, 0.0257156}, {158, 0.0258192}, {160, 
   0.025893}, {162, 0.0259137}, {164, 0.0259853}, {166, 
   0.0260135}, {168, 0.0260477}, {170, 0.026035}, {172, 
   0.0260938}, {174, 0.0262055}, {176, 0.0262037}, {178, 
   0.0263215}, {180, 0.026325}, {182, 0.0264696}, {184, 
   0.0265687}, {186, 0.0265805}, {188, 0.0266117}, {190, 
   0.0266924}, {192, 0.0266742}, {194, 0.0267336}, {196, 
   0.0267832}, {198, 0.0267737}, {200, 0.026911}, {202, 
   0.0269651}, {204, 0.0270751}, {206, 0.0270431}, {208, 
   0.0270912}, {210, 0.027113}, {212, 0.0272397}, {214, 
   0.0272315}, {216, 0.0272136}, {218, 0.0272959}, {220, 
   0.0273545}, {222, 0.0274866}, {224, 0.0275066}, {226, 
   0.0275655}, {228, 0.0275749}, {230, 0.0276744}, {232, 
   0.0276867}, {234, 0.0276864}, {236, 0.0277598}, {238, 
   0.0277984}, {240, 0.0277882}, {242, 0.0278638}, {244, 
   0.0278838}, {246, 0.0279382}, {248, 0.0279682}, {250, 
   0.0278752}, {252, 0.0279206}, {254, 0.0280338}, {256, 
   0.0280315}, {258, 0.0280694}, {260, 0.0279798}, {262, 
   0.0279821}, {264, 0.0279889}, {266, 0.028129}, {268, 
   0.0281517}, {270, 0.0281573}, {272, 0.0281823}, {274, 
   0.0282926}, {276, 0.0282894}, {278, 0.0282789}, {280, 
   0.0283418}, {282, 0.0283163}, {284, 0.0283835}, {286, 
   0.0283738}, {288, 0.0284595}, {290, 0.0284795}, {292, 
   0.0285648}, {294, 0.0286267}, {296, 0.0287073}, {298, 
   0.0286502}, {300, 0.0286367}, {302, 0.0287067}, {304, 
   0.0287968}, {306, 0.0288177}, {308, 0.0287733}, {310, 0.0288294}}
Abs380 = {{0.1, 0.0181389}, {0.2, 0.0184868}, {0.3, 0.0178332}, {0.4, 
   0.0177303}, {0.5, 0.0178026}, {0.6, 0.0174869}, {0.7, 
   0.0173248}, {0.8, 0.0171897}, {0.9, 0.0169962}, {1, 
   0.0169126}, {1.1, 0.0167383}, {1.2, 0.016798}, {1.3, 
   0.0165851}, {1.4, 0.0165418}, {1.5, 0.016441}, {1.6, 
   0.0162169}, {1.7, 0.0162628}, {1.8, 0.0162034}, {1.9, 
   0.0161954}, {2, 0.01608}, {2.1, 0.016113}, {2.2, 0.0157913}, {2.3, 
   0.0159812}, {2.4, 0.0160256}, {2.5, 0.0158312}, {2.6, 
   0.0159551}, {2.7, 0.0157653}, {2.8, 0.0156584}, {2.9, 
   0.015745}, {3, 0.0156091}, {3.1, 0.0157609}, {3.2, 0.01556}, {3.3, 
   0.0157248}, {3.4, 0.0157816}, {3.5, 0.0154636}, {3.6, 
   0.0157627}, {3.7, 0.0158029}, {3.8, 0.0155156}, {3.9, 
   0.0158137}, {4, 0.0155531}, {4.1, 0.015659}, {4.2, 
   0.0156929}, {4.3, 0.015593}, {4.4, 0.0156778}, {4.5, 
   0.0155809}, {4.6, 0.0154291}, {4.7, 0.0154669}, {4.8, 
   0.0154293}, {4.9, 0.015723}, {5, 0.0156523}, {5.1, 
   0.0156986}, {5.2, 0.0155511}, {5.3, 0.0157644}, {5.4, 
   0.0155238}, {5.5, 0.0156571}, {5.6, 0.015863}, {5.7, 
   0.0155556}, {5.8, 0.0158089}, {5.9, 0.0156503}, {6, 
   0.0157223}, {6.1, 0.0158217}, {6.2, 0.0155532}, {6.3, 
   0.0160364}, {6.4, 0.0157282}, {6.5, 0.0156189}, {6.6, 
   0.0157618}, {6.7, 0.0158884}, {6.8, 0.0158203}, {6.9, 0.01588}, {7,
    0.0156828}, {7.1, 0.0158321}, {7.2, 0.0160212}, {7.3, 
   0.0159493}, {7.4, 0.0161421}, {7.5, 0.0161392}, {7.6, 
   0.0158274}, {7.7, 0.0163127}, {7.8, 0.0159013}, {7.9, 
   0.0159812}, {8, 0.0163415}, {8.1, 0.0159965}, {8.2, 
   0.0160544}, {8.3, 0.0162358}, {8.4, 0.0159259}, {8.5, 
   0.0160865}, {8.6, 0.0161892}, {8.7, 0.0159022}, {8.8, 
   0.0162839}, {8.9, 0.016172}, {9, 0.0161034}, {9.1, 
   0.0161834}, {9.2, 0.0159591}, {9.3, 0.0162201}, {9.4, 
   0.0165077}, {9.5, 0.0162628}, {9.6, 0.0163246}, {9.7, 
   0.0162409}, {9.8, 0.016113}, {9.9, 0.0165561}, {10, 
   0.0163162}, {12, 0.0164887}, {14, 0.0167024}, {16, 0.0169761}, {18,
    0.0172264}, {20, 0.0175545}, {22, 0.0177088}, {24, 
   0.0180255}, {26, 0.0182986}, {28, 0.0185049}, {30, 0.0187261}, {32,
    0.0189013}, {34, 0.0192133}, {36, 0.0194547}, {38, 
   0.0195735}, {40, 0.0197712}, {42, 0.0200076}, {44, 0.0202209}, {46,
    0.0203705}, {48, 0.0206359}, {50, 0.0207846}, {52, 
   0.0208819}, {54, 0.0210565}, {56, 0.0213355}, {58, 0.0215136}, {60,
    0.0216291}, {62, 0.0218163}, {64, 0.0219576}, {66, 
   0.0221403}, {68, 0.0223647}, {70, 0.0225111}, {72, 0.0226069}, {74,
    0.022768}, {76, 0.0229539}, {78, 0.0230557}, {80, 0.0231378}, {82,
    0.0233842}, {84, 0.0234898}, {86, 0.0236244}, {88, 
   0.0238199}, {90, 0.0239548}, {92, 0.0240781}, {94, 0.0241836}, {96,
    0.0243121}, {98, 0.0244319}, {100, 0.0245564}, {102, 
   0.0246573}, {104, 0.0248724}, {106, 0.0249553}, {108, 
   0.0250335}, {110, 0.0251292}, {112, 0.0252884}, {114, 
   0.0253397}, {116, 0.0255432}, {118, 0.0255406}, {120, 
   0.0256459}, {122, 0.0258265}, {124, 0.0259592}, {126, 
   0.0260849}, {128, 0.0261496}, {130, 0.0262936}, {132, 
   0.0263212}, {134, 0.026418}, {136, 0.0265173}, {138, 
   0.0266018}, {140, 0.0266927}, {142, 0.0266983}, {144, 
   0.0268009}, {146, 0.0268993}, {148, 0.026971}, {150, 
   0.027157}, {152, 0.027201}, {154, 0.0272143}, {156, 
   0.0273452}, {158, 0.0274349}, {160, 0.0275074}, {162, 
   0.0276118}, {164, 0.0276734}, {166, 0.0277374}, {168, 
   0.0278183}, {170, 0.0278857}, {172, 0.0279445}, {174, 
   0.0280758}, {176, 0.0281244}, {178, 0.0282472}, {180, 
   0.0282469}, {182, 0.02841}, {184, 0.0285597}, {186, 
   0.0285776}, {188, 0.0286631}, {190, 0.0287524}, {192, 
   0.0287935}, {194, 0.0288491}, {196, 0.0289568}, {198, 
   0.0289707}, {200, 0.0290475}, {202, 0.0291832}, {204, 
   0.0292882}, {206, 0.0293192}, {208, 0.0293785}, {210, 
   0.0294645}, {212, 0.0295221}, {214, 0.0295769}, {216, 
   0.0295911}, {218, 0.0296945}, {220, 0.0297766}, {222, 
   0.0298977}, {224, 0.0299722}, {226, 0.0300396}, {228, 
   0.030075}, {230, 0.0301933}, {232, 0.0302031}, {234, 
   0.0302301}, {236, 0.0303071}, {238, 0.0303941}, {240, 
   0.0304433}, {242, 0.0305153}, {244, 0.0305661}, {246, 
   0.0305933}, {248, 0.0306978}, {250, 0.0306024}, {252, 
   0.0307296}, {254, 0.0308356}, {256, 0.0308429}, {258, 
   0.0308795}, {260, 0.030867}, {262, 0.0308705}, {264, 
   0.030907}, {266, 0.031066}, {268, 0.0310614}, {270, 
   0.0310895}, {272, 0.0311751}, {274, 0.0312486}, {276, 
   0.0313024}, {278, 0.0313239}, {280, 0.0313797}, {282, 
   0.0314123}, {284, 0.0314332}, {286, 0.0314901}, {288, 
   0.031552}, {290, 0.0316208}, {292, 0.0316881}, {294, 
   0.031775}, {296, 0.0318724}, {298, 0.031852}, {300, 
   0.0318658}, {302, 0.0319538}, {304, 0.0320357}, {306, 
   0.0320862}, {308, 0.0320489}, {310, 0.0321265}}

Yes, if you have multiple datasets, the following function should help you to split the residuals apart again. It makes use of FoldPairList, which is a bit obscure but very powerful in some situations:

repeatedTake[list_List, lengths : {__Integer}] /; Length[list] >= Total[lengths] :=
  FoldPairList[TakeDrop, list, lengths];

(*Example usage *)
repeatedTake[Range[20], {3, 5, 10, 2}]

Out[23]= {{1, 2, 3}, {4, 5, 6, 7, 8}, {9, 10, 11, 12, 13, 14, 15, 16, 17, 18}, {19, 20}}

Essentially, this function takes a number of elements from a list and then passes the rest on to the next iteration at which point a different number of elements is extracted again. So you’d use:

repeatedTake[fit["FitResiduals"], Length /@ {Abs360, Abs380, ... (* more datasets *)}]

As for your second question:

In addition, to associate x coordinates (given by the data vector Xdata) to each residue vector, I use Timeseries like this

res360 = TimeSeries[residu360, {Xdata}] 

But isn’t there another way of associating x-coordinates?

The typical way to do this would be:

res360 = Transpose[{Xdata, residu360}]

which will give you a list of pairs res360 = {{x1, res1}, {x2, res2}, ...}. This can then be easily plotted with ListPlot. There’s nothing wrong with the Timeseries method, though. You can use Normal to convert the Timeseries to a list of pairs.

Dear Sjoerd,
Thank you for your reply and your great help.
I’m going to try to play with “repeatedTake” to see how it works.

Hélène