nathan
nathan

Reputation: 191

Get the next row after a specific one in R?

Rank   Values
1      e
2      er
3      gr
4      ie
5      wv
1      iop
1      ni
2      ot
3      kr
4      lw

I have a column "rank" in a data frame and I want add get the rows that are 1 and check to see if they have a 2 after. How can I do this within a for loop? I know this can be done with an if statement I am just not sure how to grab the correct rows? I need to basically delete the rows that are ranked 1 and do not have a following rank 2.

Example Output:

Rank   NewCol
1      e       
2      er
3      gr
4      ie
5      wv
1      ni
2      ot
3      kr
4      lw

(Got rid of iop since its rank is 1 with no following 2)

Upvotes: 1

Views: 1563

Answers (4)

pietrodito
pietrodito

Reputation: 2090

Loop Style

We will go through the data frame and note which rows we need to delete in a vector.

An exemple data frame

  (df <- data.frame(
    Rank = c(1,2,3,1,2,1,1,2,1,1,1,2,3),
    Values = letters[1:13]
  ))

Here is the code

  rows.to.delete <- c()
  for( i in seq_along(df$Rank) ) {
    if(df[i + 1, "Rank"] == 1 & df[i, "Rank"] == 1){
      rows.to.delete <- c(rows.to.delete, i)
    }
  }

  df[-rows.to.delete,]

Bracket style

  df[ ! (df$Rank == 1 & df$Rank[-1] == 1), ]

This is way much concise but not as expressive...

About that, read the following post on Medium

Upvotes: 1

akrun
akrun

Reputation: 886968

We can use tidyverse as well

library(tidyverse)
df1 %>% 
  filter(!(Rank ==1 & lead(Rank, default = last(Rank)) != 2))
#   Rank Values
#1    1      e
#2    2     er
#3    3     gr
#4    4     ie
#5    5     wv
#6    1     ni
#7    2     ot
#8    3     kr
#9    4     lw

Upvotes: 1

Saurabh Chauhan
Saurabh Chauhan

Reputation: 3211

As you are looking for the loop:

data=c()
for(i in 1:nrow(df)){
 if(i!=nrow(df)){
    if(df$Rank[i]==1 & df$Rank[i+1]!=2){
     # Ignore the iteration if it doesn't have a following rank 2
    }
    else{
    data=rbind(data,df[i,]) # Else rbind the data to data.frame
    }  
  }
  else{
   data=rbind(data,df[i,])   
  } 
}

Output:

     Rank Values
 1    1      e
 2    2     er
 3    3     gr
 4    4     ie
 5    5     wv
 7    1     ni
 8    2     ot
 9    3     kr
10    4     lw

Upvotes: 1

s_baldur
s_baldur

Reputation: 33498

data[!(data$Rank == 1 & c(data$Rank[-1], 0) != 2), ]
   Rank Values
1     1      e
2     2     er
3     3     gr
4     4     ie
5     5     wv
7     1     ni
8     2     ot
9     3     kr
10    4     lw

Or using data.table:

setDT(data)[!(Rank == 1 & shift(Rank, fill = 0, type = "lead") != 2)]

where

data <- structure(list(Rank = c(1L, 2L, 3L, 4L, 5L, 1L, 1L, 2L, 3L, 4L
), Values = c("e", "er", "gr", "ie", "wv", "iop", "ni", "ot", 
"kr", "lw")), row.names = c(NA, -10L), class = "data.frame")

Upvotes: 2

Related Questions