[R] [FORGED] Newbie Question on R versus Matlab/Octave versus C

Alan Feuerbacher @|@n|00 @end|ng |rom comc@@t@net
Sat Feb 2 19:29:29 CET 2019


On 1/29/2019 11:50 PM, Jeff Newmiller wrote:
> On Tue, 29 Jan 2019, Alan Feuerbacher wrote:
> 
>> After my failed attempt at using Octave, I realized that most likely 
>> the main contributing factor was that I was not able to figure out an 
>> efficient data structure to model one person. But C lent itself 
>> perfectly to my idea of how to go about programming my simulation. So 
>> here's a simplified pseudocode sort of example of what I did:
> 
> Don't model one person... model an array of people.
> 
>> To model a single reproducing woman I used this C construct:
>>
>> typedef struct woman {
>>  int isAlive;
>>  int isPregnant;
>>  double age;
>>  . . .
>> } WOMAN;
> 
> # e.g.
> Nwomen <- 100
> women <- data.frame( isAlive = rep( TRUE, Nwomen )
>                     , isPregnant = rep( FALSE, Nwomen )
>                     , age = rep( 20, Nwomen )
>                     )
> 
>> Then I allocated memory for a big array of these things, using the C 
>> malloc() function, which gave me the equivalent of this statement:
>>
>> WOMAN women[NWOMEN];  /* An array of NWOMEN woman-structs */
>>
>> After some initialization I set up two loops:
>>
>> for( j=0; j<numberOfYears; j++) {
>>  for(i=1; i< numberOfWomen; i++) {
>>    updateWomen();
>>  }
>> }
> 
> for ( j in seq.int( numberOfYears ) {
>    # let vectorized data storage automatically handle the other for loop
>    women <- updateWomen( women )
> }
> 
>> The function updateWomen() figures out things like whether the woman 
>> becomes pregnant or gives birth on a given day, dies, etc.
> 
> You can use your "fixed size" allocation strategy with flags indicating 
> whether specific rows are in use, or you can only work with valid rows 
> and add rows as needed for children... best to compute a logical vector 
> that identifies all of the birthing mothers as a subset of the data 
> frame, and build a set of children rows using the birthing mothers data 
> frame as input, and then rbind the new rows to the updated women 
> dataframe as appropriate. The most clear approach for individual 
> decision calculations is the use of the vectorized "ifelse" function, 
> though under certain circumstances putting an indexed subset on the left 
> side of an assignment can modify memory "in place" (the 
> functional-programming restriction against this is probably a foreign 
> idea to a dyed-in-the-wool C programmer, but R usually prevents you from 
> modifying the variable that was input to a function, automatically 
> making a local copy of the input as needed in order to prevent such 
> backwash into the caller's context).

Hi Jeff,

I'm well along in implementing your suggestions, but I don't understand 
the last paragraph. Here is part of the experimenting I've done so far:

*=======*=======*=======*=======*=======*=======*
updatePerson <- function() {
   ifelse( women$isAlive,
     {
# Check whether to kill off this person, if she's pregnant whether
# to give birth, whether to make her pregnant again.
       women$age = women$age + timeStep
# Check if the person has reached maxAge
     }
   )
}

calculatePopulation <- function() {
   lastDate = 0
   jd = 0
   while( jd < maxDate ) {
     for( i in seq_len( nWomen ) ) {
       updatePerson();
     }
     todaysDateInt = floor(jd/dpy)
     NAlive[todaysDateInt] = nWomen - nDead
# Do various other things
     todaysDate = todaysDate + timeStep
     jd = jd + timeStep
   }
}

nWomen <- 5
numberOfYears <- 30
women <- data.frame( isAlive = rep_len( TRUE, nWomen )
                    , isPregnant = rep_len( FALSE, nWomen )
                    , nChildren = rep_len( 0L, nWomen )
                    , ageInt = rep_len( 0L, nWomen )
                    , age = rep_len( 0, nWomen )
                    , dateOfPregnancy = rep_len( 0, nWomen )
                    , endDateLastPregnancy = rep_len( 0.0, nWomen )
                    , minBirthAge = rep_len( 0, nWomen )
                    , maxBirthAge = rep_len( 0, nWomen )
                    )

# . . .

   calculatePopulation()

*=======*=======*=======*=======*=======*=======*

The above code (in its complete form) executes without errors. I don't 
understand at least two things:

In the updatePerson function, in the ifelse statement, how do I change 
the appropriate values in the women dataframe?

I don't understand most of your last paragraph at all.

Thanks so much for your help in learning R!

Alan

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus



More information about the R-help mailing list