Skip to content

algorithm help

6 messages · (Ted Harding), William Dunlap, array chip +1 more

#
On 06-Jan-11 22:16:38, array chip wrote:
The basic information you need can be got using rle() ("run length
encoding"). See '?rle'. In your example:

  rle(dat$a)
  # Run Length Encoding
  #   lengths: int [1:8] 2 4 2 2 1 4 4 1
  #   values : num [1:8] 0 1 0 1 0 1 0 1
  ## Note: F -> 0, T -> 1

The following has a somewhat twisted logic at the end, and may
be flawed, but you can probably adapt it!

  L <- rle(dat$a)$lengths
  V <- rle(dat$a)$values
  pos <- c(1,cumsum(L))
  V1 <- c(-1,V)
  1+pos[V1==0]
  # [1]  3  9 12 20
  ## Positions in the series dat$a where each run of "T" (i.e. 1)
  ##   starts

Hoping this helps,
Ted.

--------------------------------------------------------------------
E-Mail: (Ted Harding) <ted.harding at wlandres.net>
Fax-to-email: +44 (0)870 094 0861
Date: 06-Jan-11                                       Time: 22:57:44
------------------------------ XFMail ------------------------------
#
You need to be more careful about the first
and last rows in the dataset.  I think yours
only works when a starts with 0 and ends with 1.

  > f.fragment(c(1,1,0,0), c(11,12,13,14))
       stretch start end no.of.1s
  [1,]       1    NA  12        2
  > f.fragment(c(1,1,0,1), c(11,12,13,14))
       stretch start end no.of.1s
  [1,]       1    14  12        2
  [2,]       1    14  14        1
  > f.fragment(c(0,1,0,1), c(11,12,13,14))
       stretch start end no.of.1s
  [1,]       1    12  12        1
  [2,]       2    14  14        1
  > f.fragment(c(0,1,0,0), c(11,12,13,14))
       stretch start end no.of.1s
  [1,]       1    12  12        1
  [2,]       2    NA  12        1
  > f.fragment(c(1,1,1,1), c(11,12,13,14))
       stretch end no.of.1s
  [1,]       1  14        4
  [2,]       0  14        4
  > f.fragment(c(0,0,0,0), c(11,12,13,14))
       stretch start
  [1,]       1    NA

The following does better.  It keeps things as
logical vectors as long as possible, which tends
to work better when dealing with runs.
  f <- function(a, b) {
       isFirstIn1Run <- c(TRUE, a[-1] != a[-length(a)]) & a==1
       isLastIn1Run <- c(a[-1] != a[-length(a)], TRUE) & a==1
       data.frame(stretch=seq_len(sum(isFirstIn1Run)),
                  start = b[isFirstIn1Run],
                  end = b[isLastIn1Run],
                  no.of.1s = which(isLastIn1Run) - which(isFirstIn1Run)
+ 1)
  }
  > f(c(1,1,0,0), c(11,12,13,14))
    stretch start end no.of.1s
  1       1    11  12        2
  > f(c(1,1,0,1), c(11,12,13,14))
    stretch start end no.of.1s
  1       1    11  12        2
  2       2    14  14        1
  > f(c(0,1,0,1), c(11,12,13,14))
    stretch start end no.of.1s
  1       1    12  12        1
  2       2    14  14        1
  > f(c(0,1,0,0), c(11,12,13,14))
    stretch start end no.of.1s
  1       1    12  12        1
  > f(c(1,1,1,1), c(11,12,13,14))
    stretch start end no.of.1s
  1       1    11  14        4
  > f(c(0,0,0,0), c(11,12,13,14))
  [1] stretch  start    end      no.of.1s
  <0 rows> (or 0-length row.names)

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com
#
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 01/06/2011 11:57 PM, (Ted Harding) wrote:
A different approach would be to use the diff() function:

Where
[1]  0  1  0  0  0 -1  0  1  0 -1  1  0  0  0 -1  0  0  0  1

is not equal 0, the value is changing from 0 to 1 or one to 0.
The indices of the first new value can be found by:
[1]  3  7  9 11 12 16 20

where it is changing from 0 to 1 is at
[1]  3  9 12 20

where it is changing from 1 to 0 is at
[1]  7 11 16

By taking into consideration if the first value and the last values are
0 or 1, you can calculate the length.


Cheers,

Rainer
- -- 
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation
Biology, UCT), Dipl. Phys. (Germany)

Centre of Excellence for Invasion Biology
Natural Sciences Building
Office Suite 2039
Stellenbosch University
Main Campus, Merriman Avenue
Stellenbosch
South Africa

Tel:        +33 - (0)9 53 10 27 44
Cell:       +27 - (0)8 39 47 90 42
Fax (SA):   +27 - (0)8 65 16 27 82
Fax (D) :   +49 - (0)3 21 21 25 22 44
Fax (FR):   +33 - (0)9 58 10 27 44
email:      Rainer at krugs.de

Skype:      RMkrug
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk0m1dMACgkQoYgNqgF2egoQbACcCB3iFQ6SKYfL4KVX8AMAN9Gp
1awAn0Z+8KXnOmwCLu61gihc8xZIT++j
=O+xA
-----END PGP SIGNATURE-----