Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Repeated measures' analysis for continuous outcome

    Hello dear community,
    I am writing to have your precious help in managing a dataset. Briefly, three groups of patients (normal weight, overweight and pediatric) received three different kinds of pre-oxygenation (through three devices) at random order, each time after retuning to their baseline values of the outcomes. I would like to study for example FeO2 for differences across the tree devices used, but accounting for the fact they are repeated measures for each subject. What is the most useful test to do? I had used a K Wallis since the outcomes (FeO2, ORI and EIT_POST are not normally distributed) but this does not account for the fact that each subject underwent all interventions. I also tried with mixed linear regression but could not find the way to examine the differences "pairwise".
    I am pasting here a part of the dataset with dataex as suggested (I hope I did it right

    Code:
    * Example generated by -dataex-. For more info, type help dataex
    clear
    input int id byte(session device) double(FeO2 ORI) float(EIT_POST group5)
    124  0 .   18   0 52 3
    124  1 3    .   0 43 3
    124  2 3    . .55 52 3
    124  3 3   56 .55 53 3
    124  5 1    .   0 49 3
    124  6 1    .  .4 49 3
    124  7 1 40.5 .37 51 3
    124  9 2    .   0 53 3
    124 10 2    . .48 58 3
    124 11 2   46 .44 58 3
    127  0 . 16.5   0 38 2
    127  1 1    .  .2 27 2
    127  2 1    . .95 28 2
    127  3 1 49.5 .95 27 2
    127  5 3    .   0 37 2
    127  6 3    .   1 36 2
    127  7 3   65   1 35 2
    127  9 2    . .62 31 2
    127 10 2    .   1 31 2
    127 11 2 66.5   1 31 2
    128  0 .   17   0 69 2
    128  1 2    .   0 49 2
    128  2 2    . .85 50 2
    128  3 2   77 .82 51 2
    128  5 1    .   0 53 2
    128  6 1    . .76 49 2
    128  7 1 54.5 .71 51 2
    128  9 3    .   0 53 2
    128 10 3    . .77 63 2
    128 11 3 78.5 .76 66 2
    130  0 . 17.5   0 59 1
    130  1 2    .   0 50 1
    130  2 2    . .54 49 1
    130  3 2 73.5 .65 49 1
    130  5 1    .   0 51 1
    130  6 1    . .48 37 1
    130  7 1 52.5 .54 50 1
    130  9 3    .   0 48 1
    130 10 3    .  .3 51 1
    130 11 3   72 .65 48 1
    131  0 .   18   0 61 3
    131  1 3    . .22 48 3
    131  2 3    . .68 56 3
    131  3 3   72 .82 60 3
    131  5 2    . .25 50 3
    131  6 2    . .45 51 3
    131  7 2   71 .85 50 3
    131  9 1    .  .2 50 3
    131 10 1    .   . 48 3
    131 11 1 55.5 .76 46 3
    224  0 .   19   0 66 3
    224  1 1    .   0 59 3
    224  2 1    . .45 55 3
    224  3 1   27 .61 57 3
    224  5 2    .   0 48 3
    224  6 2    . .54 47 3
    224  7 2   37 .57 44 3
    224  9 3    .   0 52 3
    224 10 3    . .53 54 3
    224 11 3 78.4 .62 54 3
    227  0 .   18   0 65 2
    227  1 1    .   0 42 2
    227  2 1    . .95 43 2
    227  3 1   55 .97 41 2
    227  5 2    .   0 48 2
    227  6 2    . .86 44 2
    227  7 2   50 .88 42 2
    227  9 3    .   0 43 2
    227 10 3    . .86 45 2
    227 11 3   74 .92 40 2
    228  0 . 18.5   0 52 2
    228  1 2    .   0 68 2
    228  2 2    . .84 50 2
    228  3 2   67 .87 52 2
    228  5 1    .   0 54 2
    228  6 1    . .74 47 2
    228  7 1   47 .71 66 2
    228  9 3    .   0 77 2
    228 10 3    . .85 53 2
    228 11 3 76.5 .84 52 2
    229  0 .   18   0 41 2
    229  1 3    .   0 36 2
    229  2 3    . .55 41 2
    229  3 3 77.5 .56 41 2
    229  5 2    .   0 37 2
    229  6 2    . .58 37 2
    229  7 2 77.5 .55 35 2
    229  9 1    .   0 32 2
    229 10 1    . .56 33 2
    229 11 1   50 .56 34 2
    231  0 . 17.5   0 51 1
    231  1 1    . .37 51 1
    231  2 1    . .75 51 1
    231  3 1 51.5 .79 48 1
    231  5 2    .   0 48 1
    231  6 2    . .64 51 1
    231  7 2   77  .6 52 1
    231  9 3    .   0 43 1
    231 10 3    .  .7 48 1
    231 11 3 80.5 .67 53 1
    end
    label values session session
    label def session 0 "Baseline Sitting", modify
    label def session 1 "Baseline Supine", modify
    label def session 2 "At 1.5 min", modify
    label def session 3 "At 3 min", modify
    label def session 5 "Baseline Supine 2", modify
    label def session 6 "After 1.5 min sess 2", modify
    label def session 7 "At 3 min sess 2", modify
    label def session 9 "Baseline Supine sess 3", modify
    label def session 10 "At 1.5 min sess 3", modify
    label def session 11 "At 3 min sess 3", modify
    label values device device
    label def device 1 "Face Mask", modify
    label def device 2 "Ambu", modify
    label def device 3 "Ambu Peep", modify
    label values group5 group5
    label def group5 1 "Normo", modify
    label def group5 2 "Obese", modify
    label def group5 3 "Pediatric", modify
    Many thanks if you can help!
    Anna

  • #2
    you don't show your -mixed- code so I can't be sure but my guess is that you want the postestimation command -pwcompare-; see
    Code:
    help mixed postestimation

    Comment


    • #3
      I have the impression that treatment status (time when outcomes are measured) and device status are convoluted.

      Code:
      gen treat = .
      replace treat = 0 if inlist(session, 1, 5, 9)
      replace treat = 1 if inlist(session, 2, 6, 10)
      replace treat = 2 if inlist(session, 3, 7, 11)
      label define treat 0 "Pre" 1 "1.5mins" 2 "3mins"
      label values treat treat
      tab treat
      Then the mixed command could be something like this. For simplicity, I only compare t0 and t2 as the number of comparisons grows rapidly with more levels.

      Code:
      mixed EIT_POST i.treat##i.device if inlist(treat, 0, 2), vce(robust) || id:
      margins treat#device
      margins device, dydx(treat) pwcompare(pveffects)
      I am unsure why the other two outcomes have so many missing values?

      Best wishes

      (Stata 16.1 MP)

      Comment


      • #4
        Thank you to both for your help.
        @Rich Goldstein: sorry your are right, for example my model would have been
        Code:
        mixed FeO2 i.device if group==1
        In the case of FeO2 it is rather easy, this measure has been taken only at the 3-minute timeline and we can only speculate about the differences due to the device. However, from this regression, how do I get pairwise comparisons between device and device? I tried with margins but I am not sure it si giving me what I look for.

        @Felix Bittman: thanks for your help. The values are right, some of them have been taken only at some timpoints and some of them at all timepoints (it is the design of the study).
        Your help with the code is really welcome
        But how do I report the values of EIT_POST for example at t0, t1 and t2? I need to construct a table and from the mixed reg output I don't have means/SD or median/IQR
        Second problem, how do I report the results graphically?

        Many thaks again for the help and velocity!
        Anna

        Comment


        • #5
          well, again, you are not showing the code you used and I can't comment on the code I can't see

          Comment


          • #6
            Sorry again @Rich, I replied with the code but it was not correctly shown. I am trying again:
            Code:
             mixed feO2 i.device if group5==1 ||id:
            I hope it now understandable
            thank you!
            Anna

            Comment


            • #7
              Originally posted by anna campo View Post
              In the case of FeO2 . . . how do I get pairwise comparisons between device and device?

              . . . how do I report the values of EIT_POST for example at t0, t1 and t2? I need to construct a table and from the mixed reg output . . .

              Second problem, how do I report the results graphically?
              Maybe something along the following lines. Each of your questions is addressed in order following their respective insertions in the code as comments. Begin after the "Begin here" comment.
              Code:
              version 18
              
              clear *
              
              quietly input int id byte(session device) double(FeO2 ORI) float(EIT_POST group5)
              <data snippet redacted for brevity>
              end
              <value labeling redacted for brevity>
              
              *
              * Begin here
              *
              // Begin data management
              rename (id device FeO2 ORI EIT_POST group5) (pid trt feo ori eit grp)
              label variable feo "Fraction expired oxygen"
              label variable ori "Oxygen Reserve Index (ORi)"
              label variable eit "Electrical Impedance Tomography (EIT)"
              
              generate byte ses = 0 + inrange(session, 1, 3) + 2 * inrange(session, 5, 7) + ///
                  3 * inrange(session, 9, 11)
              generate byte tim = 0 + inlist(session, 2, 6, 10) + ///
                  2 * inlist(session, 3, 7, 11)
              drop session
              
              _strip_labels _all
              
              label define Devices 1 "Face Mask" 2 "Ambu®" 3 "Ambu® PEEP Valve"
              label values trt Devices
              
              label define Groups 1 "Normal Adult" 2 "Obese Adult" 3 Pediatric
              label values grp Groups
              
              /* three groups of patients . . . received three different kinds of
                 pre-oxygenation . . . at random order */
              frame copy default Sequences
              frame Sequences {
                  quietly drop if !ses
                  contract pid trt ses, freq(discard)
                  quietly reshape wide trt, i(pid) j(ses)
                  egen str Seq = concat(trt?)
                  label define Williams 1 "123" 2 "132" 3 "231" 4 "213" 5 "312" 6 "321"
                  encode Seq, generate(seq) label(Williams) noextend
                  keep pid seq
              }
              frlink m:1 pid, frame(Sequences)
              frget seq, from(Sequences) // can't use -frval()- as factor variable
              
              order grp seq pid ses tim
              sort pid ses tim
              list grp seq pid ses tim trt feo ori eit if pid == pid[1], noobs sepby(ses)
              // End data management
              
              /* First question: "In the case of FeO2 . . . how do I get pairwise comparisons
                 between device and device?" */
              mixed feo i.grp i.seq##i.trt if tim == 2 || pid: , ///
                  reml dfmethod(kroger) nolrtest nolog
              contrast grp seq trt seq#trt, small
              local df = r(df2)[1, 3]
              margins trt, df(`df') pwcompare(effects) mcompare(noadjust)
              
              /* Second question:  ". . . how do I report the values of EIT_POST for example
                 at t0, t1 and t2? I need to construct a table and from the mixed reg
                 output" */
              mixed eit i.grp i.trt##i.ses##i.tim if ses != 0 || pid: , ///
                  reml dfmethod(kroger) nolrtest nolog
              contrast grp trt ses tim trt#ses trt#tim ses#tim trt#ses#tim, small
              local df = r(df2)[1, 6]
              margins trt#tim, df(`df')
              
              /* "Second problem, how do I report the results graphically?" */
              #delimit ;
              marginsplot ,
                  xdimension(tim) scheme(s2color) title("")
                  plotopts(lcolor(black) mcolor(black) mfcolor(white))
                      plot1opts(msymbol(O) msize(medium))
                      plot2opts(msymbol(T) msize(medlarge))
                      plot3opts(msymbol(S) msize(medium))
                  noci
                  ytitle(AU) ylabel( , angle(horizontal) nogrid)
                  xtitle(Time) xlabel(0 "Baseline" 1 "1½ min" 2 "3 min")
                  legend(off);
              #delimit cr
              
              exit
              A couple of notes:

              1. I've had to do a little data management, because your coding of "session" isn't really usable for the purpose. (I've also shortened the variable names and made their length consistent.)

              2. You mentioned in your original post that there was a washout period between sessions and so I haven't included a variable for carryover, but you could if you wanted to. See Stata's documentation for its pk suite of commands for background on how to generate such a variable.

              3. You mentioned there also that the order of the three devices was randomized, and so that order ought to be included in your regression models. (If this experiment were conducted in the context of a product-development project in industry, its protocol would have called for participants to be formally randomly assigned to treatment sequence using permuted Latin squares in order to achieve balance in this between-subjects factor.) I used Stata's frame commands to create a variable that identifies device sequence for each study participant.


              Complete do-file and resulting log file are attached if you're interested further.
              Attached Files

              Comment


              • #8
                Thank you Joseph Coveney! I am trying to use your do-file but I am not able to use it, possibly because I never used the frames and now I cannot get out of the frame anymore (though trying with Stata manual to drop it and start again but it looks as if I cannot see the results of the code on my Stata and also cannot get out of Stata anymore :/

                Comment

                Working...
                X