Skip to content

Have a function like the "_n_" in R ? (Automatic count function )

12 messages · Nash, Henrique Dallazuanna, David Winsemius +6 more

#
Have the counter function in R ?

if we use the software SAS

/*** SAS Code **************************/
data tmp(drop= i);
retain seed x 0;
do i = 1 to 5;
	call ranuni(seed,x);
	output;
end;
run;

data new;
counter=_n_;  ***** this keyword _n_ ****;
set tmp;
run;

/*
_n_ (Automatic variables)
are created automatically by the DATA step or by DATA step statements.
*/

/*** Output ********************************
counter	     seed             x
1	584043288	         0.27197
2	935902963	         0.43581
3	301879523	         0.14057
4	753212598	         0.35074
5	1607264573	0.74844

********************************************/

Have a function like the "_n_" in R ?


--
Nash - morrison at ibms.sinica.edu.tw
#
The _n_ construct in SAS is most analogous to that of row names in R,  
accessible (and modifiable)  via the row.names() function:

DF <- structure(list(Month = structure(c(2L, 2L, 2L, 2L, 1L, 1L, 1L,
1L, 3L, 3L, 3L, 3L, 3L), .Label = c("Aug", "July", "Sept"), class =  
"factor"),
     Week = 27:39, Estpassage = c(665L, 2232L, 9241L, 28464L,
     41049L, 82216L, 230411L, 358541L, 747839L, 459682L, 609567L,
     979475L, 837189L), MedFL = c(34L, 35L, 35L, 35L, 35L, 35L,
     35L, 35L, 35L, 36L, 36L, 36L, 36L)), .Names = c("Month",
"Week", "Estpassage", "MedFL"), class = "data.frame", row.names = c(NA,
-13L))

DF$counter <- row.names(DF)

 > DF
    Month Week Estpassage MedFL counter
1   July   27        665    34       1
2   July   28       2232    35       2
3   July   29       9241    35       3
4   July   30      28464    35       4
5    Aug   31      41049    35       5
6    Aug   32      82216    35       6
7    Aug   33     230411    35       7
8    Aug   34     358541    35       8
9   Sept   35     747839    35       9
10  Sept   36     459682    36      10
11  Sept   37     609567    36      11
12  Sept   38     979475    36      12
13  Sept   39     837189    36      13

Row names, however, not guaranteed to be integer, although if not  
specified at time of creation a dataframe will have its row names set  
to an ascending series of integer type. Another function that would  
provide similar utility for vectors might be seq_along().\, but in the  
case of dataframes, it may confuse the beginning R user because it  
will return a column oriented ascending sequence.

 > seq_along(DF)
[1] 1 2 3 4 5
#
And for completeness here's a function that returns the next integer
on each call.

n <- (function(){
  i <- 0
  function() {
    i <<- i + 1
    i
  }
})()
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6


;)

Hadley
On Wed, Feb 25, 2009 at 8:27 AM, David Winsemius <dwinsemius at comcast.net> wrote:

  
    
#
hadley wickham wrote:
actually, you do not need the external function to have the functionality:

    n = local({
        i = 0
        function() (i <<- i + 1)[1] })

    n()
    # 1
    n()
    # 2

vQ
#
On Wed, Feb 25, 2009 at 8:41 AM, Wacek Kusnierczyk
<Waclaw.Marcin.Kusnierczyk at idi.ntnu.no> wrote:
Yes, I'm just using the function as a way of creating an environment.
The function method is a little more flexible if you want multiple
independent counters though.

Hadley
#
On Wed, Feb 25, 2009 at 3:30 PM, hadley wickham <h.wickham at gmail.com> wrote:
*headache*!
I can't wrap my head around this one - too strange code!
Could someone please give a hint on what's going on?
How does"i<<- i+1" modify i permanently, seeing as i is defined as 0
to start with?

/Gustaf
#
On Wed, 25 Feb 2009, Gustaf Rydevik wrote:

            
i is not _defined_ as zero. It is initially _assigned_ the value of zero 
and is subsequently assigned other values.

As for the details of what goes here, see

 	An Introduction to R
 	Section 10.7 Scope

and study the open.acount()  example there.

HTH,

Chuck
Charles C. Berry                            (858) 534-2098
                                             Dept of Family/Preventive Medicine
E mailto:cberry at tajo.ucsd.edu	            UC San Diego
http://famprevmed.ucsd.edu/faculty/cberry/  La Jolla, San Diego 92093-0901
#
hadley wickham wrote:
not as it stands above, because you immediately apply your function and
lose grip of it -- so it's just as do-once a solution as that with
local.  but clearly, to have multiple independent counters, you'd need
two nested functions, as in this generalized version:

    make.counter =
        function(value)
            function(increment)
                (value <<- value + increment)[1]

    counters =
        lapply(rep(0, 3), make.counter)
    mapply(
        function(counter, increment)
            counter(increment),
        counters, 1)
    # 1 1 1

which is what you presumably had in mind, roughly.

vQ
#
On Wed, Feb 25, 2009 at 4:43 PM, Charles C. Berry <cberry at tajo.ucsd.edu> wrote:
Thank you - I think I finally understood how that code got parsed.
Does the text below describe things correctly?
First, Hadley defines a function that returns another function, like this:

function(){
 i <- 0
 function() {
   i <<- i + 1
   i
 }
}

Since the returned function is defined in a local environment , R
returns the function together with that local environment, and lexical
scoping can work it's magic
Finally Hadley evaluates the above defined function-returning
function, and stores the returned function in n.

n<-function(){
 i <- 0
 function() {
   i <<- i + 1
   i
 }
}()

*Phew*
That wasn't too difficult after all :-)

/Gustaf
#
If you are in the context of a data frame (which is closest to the 
concept
of a "data set" in SAS), the 1:nrow(df) is closest to what you may look
for.

For instance:

data(iris)
.n. <- 1:nrow(iris)

You may notice that this number is not very idiomatic in R.

If you have something like:

if(_N_ > 50) then output;

in R you can simply put

iris[-(1:50),]

without using an explicit counter variable.

In the context of a matrix, the row() and col() functions may do what
you want.



Am 25.02.2009 um 15:34 schrieb justin bem: