L Tyrone
L Tyrone

Reputation: 6860

Efficiently derive bins based on condition in R

I need to create bins for every completed rotation e.g. 360° and bins will be of varying lengths. I have created a for loop but with 100,000+ rows it is slow. I tried to implement using dplyr and/or other non-loop methods but am unclear where and how to declare the cutoffs. None of the examples I found for either dplyr or cut() seemed to address my problem.

Sample data:

x <- c(seq(90, .5, length.out = 3),
       seq(359.5, .2, length.out = 5),
       seq(358.9, .8, length.out = 8),
       seq(359.2, .3, length.out = 11),
       seq(358.3, .1, length.out = 15))

df <- data.frame(x)
df$bin <- NA
df[1,2] <- 1

For loop:

for(i in 2:nrow(df)) {

  if(df[i,1] < df[i-1,1]) {

    df[i,2] <- df[i-1,2]

  } else {

    df[i,2] <- df[i-1,2] + 1

  }

}

How are the results in df$bin achieved without using a loop?

Upvotes: 1

Views: 62

Answers (1)

lroha
lroha

Reputation: 34376

It looks like you could do:

df$binnew <- cumsum(c(1, diff(df$x) > 0))

Compare:

           x bin binnew
1   90.00000   1      1
2   45.25000   1      1
3    0.50000   1      1
4  359.50000   2      2
5  269.67500   2      2
6  179.85000   2      2
7   90.02500   2      2
8    0.20000   2      2
9  358.90000   3      3
10 307.74286   3      3
11 256.58571   3      3
12 205.42857   3      3
13 154.27143   3      3
14 103.11429   3      3
15  51.95714   3      3
16   0.80000   3      3
17 359.20000   4      4
18 323.31000   4      4
19 287.42000   4      4
20 251.53000   4      4
21 215.64000   4      4
22 179.75000   4      4
23 143.86000   4      4
24 107.97000   4      4
25  72.08000   4      4
26  36.19000   4      4
27   0.30000   4      4
28 358.30000   5      5
29 332.71429   5      5
30 307.12857   5      5
31 281.54286   5      5
32 255.95714   5      5
33 230.37143   5      5
34 204.78571   5      5
35 179.20000   5      5
36 153.61429   5      5
37 128.02857   5      5
38 102.44286   5      5
39  76.85714   5      5
40  51.27143   5      5
41  25.68571   5      5
42   0.10000   5      5

Upvotes: 2

Related Questions