1

I have a data frame like this

ID <- c(1)
Rank <- c(1,2,3,1,2)
Val <- c(10,20,30,40,50)

df <- data.frame(ID,Rank,Val)
df

  ID Rank Val
1  1    1  10
2  1    2  20
3  1    3  30
4  1    1  40
5  1    2  50

Within each ID, how to subset the dataframe such that I have two different frames

df1:

  ID Rank Val
1  1    1  10
2  1    2  20
3  1    3  30

df2:

  ID Rank Val
4  1    1  40
5  1    2  50

The total length of each ID could vary. Hence sometimes I could have rank like 1,2,1,2. In this case, the two frames will be (1,2) and (1,2)

Hardik Gupta
  • 4,700
  • 9
  • 41
  • 83
  • 2
    Try with `split` ie. `split(df, cumsum(c(TRUE, diff(df$Rank) < 0)))` – akrun Nov 07 '17 at 18:05
  • yes that works, though it returns a list but that still is good for me – Hardik Gupta Nov 07 '17 at 18:07
  • akrun can you please post this as an answer, I'll accept it – Hardik Gupta Nov 07 '17 at 18:07
  • 1
    A canonical post for the `cumsum(...diff(...) )` idiom: [How to partition a vector into groups of regular, consecutive sequences?](https://stackoverflow.com/questions/5222061/how-to-partition-a-vector-into-groups-of-regular-consecutive-sequences) – Henrik Nov 07 '17 at 18:10

1 Answers1

2

We create the f based on taking the difference between adjacent elements of 'Rank' column, create a logical vector, convert it to numeric with cumsum and split based on that

split(df, cumsum(c(TRUE, diff(df$Rank) < 0)))
akrun
  • 874,273
  • 37
  • 540
  • 662