[R] loop function within a loop

William Dunlap wdunlap at tibco.com
Wed Oct 12 21:55:15 CEST 2011


Is this the result you are after, where the event number
(within a group) are sorted according to the event/prev_event
pairs (prev_event in a row matches event of the previous row)?

> ave(d, d$group,  FUN=function(z) z[ match(tsort(z$prev_event, z$event)[-1], z$event), ])
   event prev_event group
1    845          0  5360
2    234        845  5360
3    993        234  5360
4    153        993  5360
5    926        153  5360
6    848        926  5360
7    234          0  8765
8    968        234  8765
9    545        968  8765
10   625        111  3334
11   713        625  3334
12   227        713  3334
13   181        227  3334
14   744        181  3334
15   913          0  2329
16   355        913  2329
17   761        355  2329
18   324        761  2329
19   119        324  2329
20   372        119  2329
21   890        372  2329
22   189        890  2329
23   719        189  2329
24   266        719  2329

'tsort' is a topological sorting function, like
the Unix tsort.  It is overkill for this application
(and probably could be faster and do some more
error checking) but I had it hanging around:

tsort <- function (before, after) 
{
    # topological sort: Kahn's 1962 algorithm, from Wikipedia 
    # before and after should be equal-length vectors of the
    # same type.
    L <- before[0]
    S <- setdiff(before, after)
    while (length(S) > 0) {
        n <- S[1]
        S <- S[-1]
        L[length(L) + 1] <- n
        m <- after[e <- before == n]
        after <- after[!e]
        before <- before[!e]
        S <- c(S, m[!is.element(m, after)])
    }
    if (length(after) > 0) {
        stop("Graph contains a cycle")
    }
    else {
        L
    }
}

Your data was

d <- data.frame(
  event = c(845, 926, 993, 234, 848, 153, 234, 968, 545, 625, 744, 181, 
    713, 227, 913, 372, 719, 119, 761, 890, 266, 324, 189, 355),
  prev_event = c(0, 153, 234, 845, 926, 993, 0, 234, 968, 111, 181, 227, 625, 
    713, 0, 119, 189, 324, 355, 372, 719, 761, 890, 913),
  group = c(5360, 5360, 5360, 5360, 5360, 5360, 8765, 8765, 8765, 3334, 
    3334, 3334, 3334, 3334, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 
    2329, 2329, 2329))

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com 

> -----Original Message-----
> From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf Of Sally Zhen
> Sent: Wednesday, October 12, 2011 7:56 AM
> To: r-help at r-project.org
> Subject: [R] loop function within a loop
> 
> Hi all,
> 
> I'm working on a loop function for a large dataset which contains 1000
> different groups. I would like to reconstruct the order of events within
> each group by using a loop function in R. (Currently the order of events are
> based on the ascending order of prev_event within the group)
> 
> 
> A demo data frame:
> 
> event       prev_event   group
> 845          0               5360
> 926          153            5360
> 993          234            5360
> 234          845            5360
> 848          926            5360
> 153          993            5360
> 234          0               8765
> 968          234            8765
> 545          968            8765
> 625          111            3334
> 744          181            3334
> 181          227            3334
> 713          625            3334
> 227          713            3334
> 913          0               2329
> 372          119            2329
> 719          189            2329
> 119          324            2329
> 761          355            2329
> 890          372            2329
> 266          719            2329
> 324          761            2329
> 189          890            2329
> 355          913            2329
> 
> 
> Below is what I have written:
> 
> ordering <- vector("list", length(unique(mydata$group)))
> for (j in 1:length(unique(mydata$group))){
> group.j <- mydata[mydata$group == unique(mydata$group)[j], ]
> ordering.j <- c()
> ordering.j[1] <- ifelse(group.j[1, ]$prev_event == 0, group.j[1, ]$event,
> group.j[1, ]$prev_event)
> for (i in 2:nrow(group.j)){
> ordering.j[i] <- group.j[group.j$prev_event == ordering.j[i-1], ]$event}
> ordering[j] <- ordering.j}
> ordering
> 
> What I got is:
> Error in ordering.j[i] <- group.j[group.j$prev_event == ordering.j[i -  :
>   replacement has length zero
> > ordering
> [[1]]
> NULL
> 
> [[2]]
> NULL
> 
> [[3]]
> NULL
> 
> 
> However, when I accidentally put a typo in the loop function, instead of
> ordering.j[i] <- group.j[group.j$prev_event == ordering.j[i-1], ]$event},
> I put
> ordering.j[i] <- group.j[group.j$prev_event == ordering.j[i-1],
> ]$prev_event},
> The output is a list of 1000 entries, each with the first event within the
> group, and I received the following warning messages:
> [[1]]
> [1] 1.000680e+17
> 
> [[2]]
> [1] 1.001390e+17
> 
> [[3]]
> [1] 1.001450e+17
> 
> 49: In ordering[j] <- ordering.j :
>   number of items to replace is not a multiple of replacement length
> 50: In ordering.j[i] <- group.j[group.j$prev_event ==  ... :
>   number of items to replace is not a multiple of replacement length
> 
> 
> Why is this happening, and how can I fix it? Any pointer will be greatly
> appreciated!
> 
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list