Peter Flom
Peter Flom

Reputation: 2388

Question about while loops in R

FURTHER UPDATE

There's no input, because the program creates data.

The code below works for the first two patients, but I want to put it in a loop; there will be 200 patients eventually. Sorry about length.

    s <- 42 #SHOULD BE 42
    p <- 30 #SHOULD BE 400
    p1 <- 8 #Should be 8
    m <- 2 #shou;ld be higher
    w <- 2
    #CAPITAL LETTERS are counting versions of the lowercase
    numses <- 12
    mult <- 1
    maxses <- round(mult*numses,0)
    drop = .3; titrate = .2;  complete = .3; noise = .5; other = .1
    dropskip = .3; titrateskip = .2; completeskip = .3; noiseskip = .5; otherskip = .1;
    dropnew = .3; titratenew = .2; completenew = .9; noisenew = .5; othernew = .1;
    name = "Basic";
    pdrop = .1;  ptitrate = .2;  pcomplete =.7; pnoise = .9; pother = 1;

    #  THESE HAVE TO BE ASCENDING.  
    w = 10 
    ######################################################################################################################

    patients <- matrix(nrow = p, ncol = s, "NA") #all patients attendance
    invited  <- matrix(nrow = p, ncol = s, 0)  #number of sessions A or S
    missinrow <- matrix(nrow = p, ncol = s, 0) #number of sessions missed in a row
    insess <- vector("numeric", s) #number of people in a session
    set.seed(83877201)
    addlist <- rpois(s, w)

# Set up waitlist
waitlist <- vector("numeric", s)
waitlist[1] <- addlist[1]
for(i in 2:s)
{
 waitlist[i] <- waitlist[i-1] + addlist[i]
}
for (i in 1:p)
{
    for (j in 1:s)
    {  
    if (i < waitlist[j]) patients[i,j] <- "W"
    }
}


#Assign all patients to classes
classlist <- cut(runif(p), c(0, pdrop, ptitrate, pnoise, pcomplete, 1), labels = c("D", "T", "C", "N", "O"))


#First patient
#first session
{
   invited[1,1] <- 1
   insess[1] <- 1
   if (classlist[1] == "D")
   {
      if (runif(1) < dropnew) {patients[1, 1] <- 'A'} else
      {
        patients[1, 1] <- 'S'
        missinrow[1, 1] <- 1
      }
   }
   if (classlist[1] == "T")
   {
        if (runif(1) < titratenew) {patients[1, 1] <- 'A'} else 
        {
          patients[1, 1] <- 'S'
          missinrow[1, 1] <- 1
        }
    }
    if (classlist[1] == "C")
    {
        if (runif(1) < completenew) {patients[1, 1] <- 'A'} else 
        {
        patients[1, 1] <- 'S'
        missinrow[1, 1] <- 1
        }
    }
    if (classlist[1] == "N")
    {
        if (runif(1) < noisenew) {patients[1, 1] <- 'A'} else 
        {
        patients[1, 1] <- 'S'
        missinrow[1, 1] <- 1
        }
    }
    if (classlist[1] == "O")
    {
    if (runif(1) < othernew) {patients[1, 1] <- 'A'} else 
        {
        patients[1, 1] <- 'S'
        missinrow[1, 1] <- 1
        }
    }
}
#Later sessions
for (j in 2 : s)
{
    if (patients[1,(j-1)] == 'A'|patients[1,(j-1)] == 'S')
    {
       invited[1,j] <- invited[1,(j-1)] + 1
    } else
    {
       invited[1,j] <- invited[1,(j-1)]
    }
       if (invited[1,j] <= maxses & missinrow[1,j] < m)
    {
    # Skip or attend
    # If attended previous session    
        if (patients[1, (j-1)] == 'A')
        {
            if (classlist[1] == "D")
            {if (runif(1) < drop) {patients[1, j] <- 'A'} else
                {
                   patients[1, j] <- 'S'
                   missinrow[1, j] <- 1
                }
            } 
            if (classlist[1] == "T")
            {if (runif(1) < titrate) {patients[1, j] <- 'A'} else
                {
                   patients[1, j] <- 'S'
                   missinrow[1, j] <- 1
                }
            }
            if (classlist[1] == "C")
            {if (runif(1) < complete) {patients[1, j] <- 'A'} else
                {
                   patients[1, j] <- 'S'
                   missinrow[1, j] <- 1
                }
            }
            if (classlist[1] == "N")
            {
               if (runif(1) < noise) {patients[1, j] <- 'A'} else 
               {
                   patients[1, j] <- 'S'
                   missinrow[1, j] <- 1
               }
            }
            if (classlist[1] == "O")
            {
               if (runif(1) < other) {patients[1, j] <- 'A'} else 
               {
                    patients[1, j] <- 'S'
                    missinrow[1, j] <- 1
                }
            }            
        } else
        # If skipped previous session
        if (patients[1, (j-1)] == 'S')
        {
            if (classlist[1] == "D")
            {
               if (runif(1) < drop) {patients[1, j] <- 'A'} else
               {
                  patients[1, j] <- 'S'
                  missinrow[1, j] <- missinrow[1, (j-1)] + 1
               }
            } 
            if (classlist[1] == "T")
            {
               if (runif(1) < titrate) {patients[1, j] <- 'A'} else
               {
                 patients[1, j] <- 'S'
                 missinrow[1, j] <- missinrow[1, (j-1)] + 1
               }
            }
            if (classlist[1] == "C")
            {if (runif(1) < complete) {patients[1, j] <- 'A'} else
                {
                   patients[1, j] <- 'S'
                   missinrow[1, j] <- missinrow[1, (j-1)] + 1
                }
            }
            if (classlist[1] == "N")
            {if (runif(1) < noise) {patients[1, j] <- 'A'} else 
                {
                   patients[1, j] <- 'S'
                   missinrow[1, j] <- missinrow[1, (j-1)] + 1
                }
            }
            if (classlist[1] == "O")
            {
               if (runif(1) < other) {patients[1, j] <- 'A'} else 
               {
                    patients[1, j] <- 'S'
                    missinrow[1, j] <- missinrow[1, (j-1)] + 1
               }
            }            
        }
    } else {patients[1,j] <- 'D'}   
    # check for number of attended or missed sessions
    if (patients[1,(j-1)] == 'A' | patients[1,(j-1)] == 'S')
    {
        insess[j] <- 1
    }   else
    {
        insess[j] <- 0
    }
}


#Second patients
#Patient is waiting and there is space
  #First session
if (insess[1] < maxses & waitlist[1] > 0)  #THIS MAY NEED TO BE A WHILE LOOP, FOR MULTIPLE PATIENTS
{
   invited[2,1] <- 1
   insess[1] <- insess[1] + 1
   if (classlist[2] == "D")
   {
      if (runif(1) < dropnew) {patients[1, 1] <- 'A'} else
      {
        patients[2, 1] <- 'S'
        missinrow[2, 1] <- 1
      }
   }
   if (classlist[2] == "T")
   {
        if (runif(1) < titratenew) {patients[2, 1] <- 'A'} else 
        {
          patients[2, 1] <- 'S'
          missinrow[2, 1] <- 1
        }
    }
    if (classlist[2] == "C")
    {
        if (runif(1) < completenew) {patients[2, 1] <- 'A'} else 
        {
        patients[2, 1] <- 'S'
        missinrow[2, 1] <- 1
        }
    }
    if (classlist[2] == "N")
    {
        if (runif(1) < noisenew) {patients[2, 1] <- 'A'} else 
        {
        patients[2, 1] <- 'S'
        missinrow[2, 1] <- 1
        }
    }
    if (classlist[2] == "O")
    {
    if (runif(1) < othernew) {patients[2, 1] <- 'A'} else 
        {
        patients[2, 1] <- 'S'
        missinrow[2, 1] <- 1
        }
    }
}


  #Later sessions


#Patient invited previous session
for (j in 2 : s)
{
    if (patients[2,(j-1)] == 'A'|patients[2,(j-1)] == 'S')
    {
       invited[2,j] <- invited[2,(j-1)] + 1
    } else
    {
       invited[2,j] <- invited[2,(j-1)]
    } 
       if (invited[2,j] <= maxses & missinrow[2,j] < m)
    {
    # Skip or attend
    # If attended previous session    
        if (patients[2, (j-1)] == 'A')
        {
            if (classlist[2] == "D")
            {if (runif(1) < drop) {patients[2, j] <- 'A'} else
                {
                   patients[2, j] <- 'S'
                   missinrow[2, j] <- 1
                }
            } 
            if (classlist[2] == "T")
            {if (runif(1) < titrate) {patients[2, j] <- 'A'} else
                {
                   patients[2, j] <- 'S'
                   missinrow[2, j] <- 1
                }
            }
            if (classlist[2] == "C")
            {if (runif(1) < complete) {patients[2, j] <- 'A'} else
                {
                   patients[2, j] <- 'S'
                   missinrow[2, j] <- 1
                }
            }
            if (classlist[2] == "N")
            {
               if (runif(1) < noise) {patients[2, j] <- 'A'} else 
               {
                   patients[2, j] <- 'S'
                   missinrow[2, j] <- 1
               }
            }
            if (classlist[2] == "O")
            {
               if (runif(1) < other) {patients[2, j] <- 'A'} else 
               {
                    patients[2, j] <- 'S'
                    missinrow[2, j] <- 1
                }
            }            
        } else
        # If skipped previous session
        if (patients[2, (j-1)] == 'S')
        {
            if (classlist[2] == "D")
            {
               if (runif(1) < drop) {patients[2, j] <- 'A'} else
               {
                  patients[2, j] <- 'S'
                  missinrow[2, j] <- missinrow[2, (j-1)] + 1
               }
            } 
            if (classlist[2] == "T")
            {
               if (runif(1) < titrate) {patients[2, j] <- 'A'} else
               {
                 patients[2, j] <- 'S'
                 missinrow[2, j] <- missinrow[2, (j-1)] + 1
               }
            }
            if (classlist[2] == "C")
            {if (runif(1) < complete) {patients[2, j] <- 'A'} else
                {
                   patients[2, j] <- 'S'
                   missinrow[2, j] <- missinrow[2, (j-1)] + 1
                }
            }
            if (classlist[2] == "N")
            {if (runif(1) < noise) {patients[2, j] <- 'A'} else 
                {
                   patients[2, j] <- 'S'
                   missinrow[2, j] <- missinrow[2, (j-1)] + 1
                }
            }
            if (classlist[2] == "O")
            {
               if (runif(1) < other) {patients[2, j] <- 'A'} else 
               {
                    patients[2, j] <- 'S'
                    missinrow[2, j] <- missinrow[2, (j-1)] + 1
               }
            }            
        }
    } else {patients[2,j] <- 'D'}   
    # check for number of attended or missed sessions
    if (patients[2,(j-1)] == 'A' | patients[2,(j-1)] == 'S')
    {
        insess[j] <- insess[j] + 1
    }   else
    {
        insess[j] <- insess[j]
    }
}

UPDATED with additional information Thanks, Joshua, for your help so far.

Joshua asked for additional information in order to be able to help further.

The overall problem is to create a dataset of patients who attend different sessions of therapy. Whether they attend or not depends on a number of parameters, including whether they attended the previous session (which is in patients), what "class" of patient they are (which is in classlist), how many sessions they have already either attended or skipped (invited) and how many sessions in a row they have missed (missinrow); all of those will vary. If the previous session is less than full, additional patients get assigned to the new session (provided someone is waiting (waitlist).

When I do this one patient at a time, it works well. But when I try to loop over all patients, I run into the

Hello

This is one part of a larger program. I cannot figure out why it doesn't work as I thought it would. The code is

for(i in 2:p)
{  
   while (insess[1] < maxses & waitlist[1] > 0)  
   {
      invited[i,1] <- 1
      waitlist[1] <- waitlist[1] - 1
      insess[1] <- insess[1] + 1
      if (classlist[i] == "D")
      {
         if (runif(1) < dropnew) {patients[i, 1] <- 'A'} else
         {
           patients[i, 1] <- 'S'
           missinrow[i, 1] <- 1
         }
      }
      if (classlist[i] == "T")
      {
           if (runif(1) < titratenew) {patients[i, 1] <- 'A'} else 
           {
             patients[i, 1] <- 'S'
             missinrow[i, 1] <- 1
           }
       }
       if (classlist[i] == "C")
       {
           if (runif(1) < completenew) {patients[i, 1] <- 'A'} else 
           {
           patients[i, 1] <- 'S'
           missinrow[i, 1] <- 1
           }
       }
       if (classlist[i] == "N")
       {
           if (runif(1) < noisenew) {patients[i, 1] <- 'A'} else 
           {
           patients[i, 1] <- 'S'
           missinrow[i, 1] <- 1
           }
       }
       if (classlist[i] == "O")
       {
       if (runif(1) < othernew) {patients[i, 1] <- 'A'} else 
           {
           patients[i, 1] <- 'S'
           missinrow[i, 1] <- 1
           }
       }
   }
}

When I run this, i goes to 30 (which is right), insess[1] goes to 10 (also right), waitlist[1] goes to 0 (also right) but the patients matrix is only updated for i = 2. I also checked that classlist has appropriate values.

I don't see where it is leaving the loop. I think I'm using while incorrectly, but not sure how.

thanks!

Upvotes: 1

Views: 455

Answers (1)

Joshua Ulrich
Joshua Ulrich

Reputation: 176638

You're not resetting insess[1] and waitlist[1] in each iteration of the for loop. When i = 3, insess[1] = 10 and waitlist[1] = 0, so nothing in the while loop is executed.

As as added bonus, here's a more succinct version of your code using the switch function.

for(i in 2:p)
{
   insess[1] <- INITME
   waitlist[1] <- INITMETOO

   while (insess[1] < maxses & waitlist[1] > 0)  
   {
      invited[i,1] <- 1
      waitlist[1] <- waitlist[1] - 1
      insess[1] <- insess[1] + 1

      newswitch <-
        switch(classlist[i],
               D = dropnew,
               T = titratenew,
               C = completenew,
               N = noisenew,
               O = othernew)

      if (runif(1) < newswitch) {
        patients[i, 1] <- 'A'
      } else {
        patients[i, 1] <- 'S'
        missinrow[i, 1] <- 1
      }
   }
}

Upvotes: 5

Related Questions