R control over number of consecutive NA values per row of data frame

Viewed 54

There are similarly worded questions, but not quite what I'm looking to do.

I have a data frame where I'd like to remove rows that have n number of consecutive NA values.

1   Manhattan   NA      2300    NA      2275    2300    
2   Manhattan   2999    2975    NA      NA      2995    
3   Manhattan   NA      NA      NA      NA      4400    
4   Manhattan   6725    6500    6750    6995    6800    
5   Brooklyn    2000    1995    1975    2000    1999    
6   Bronx       1200    3200    NA      NA      NA

I have some working code that removes n number of total NA values, but would like to tweak it for consecutive.

delete.na <- function(df, n=0) {
  df[rowSums(is.na(df)) <= n,]
}
df <- delete.na(df,3)

So, in this case after removing rows with 3 consecutive NA values I would have:

1   Manhattan   NA      2300    NA      2275    2300    
2   Manhattan   2999    2975    NA      NA      2995    
4   Manhattan   6725    6500    6750    6995    6800    
5   Brooklyn    2000    1995    1975    2000    1999    
1 Answers

One option is to loop over the rows, check with rle to return the list of values and lengths of adjacent elements that are same (here it is the logical vector (is.na - i.e. TRUE - for NA and FALSE for non-NA), as the 'values' are logical, use that to subset the 'lengths', check if it is all less than 3 and use that as row index to subset rows

df[apply(df, 1, function(x) all(with(rle(is.na(x)), lengths[values]) <3)),]
#     city col1 col2 col3 col4 col5
#1 Manhattan   NA 2300   NA 2275 2300
#2 Manhattan 2999 2975   NA   NA 2995
#4 Manhattan 6725 6500 6750 6995 6800
#5  Brooklyn 2000 1995 1975 2000 1999

data

df <- structure(list(city = c("Manhattan", "Manhattan", "Manhattan", 
"Manhattan", "Brooklyn", "Bronx"), col1 = c(NA, 2999L, NA, 6725L, 
2000L, 1200L), col2 = c(2300L, 2975L, NA, 6500L, 1995L, 3200L
), col3 = c(NA, NA, NA, 6750L, 1975L, NA), col4 = c(2275L, NA, 
NA, 6995L, 2000L, NA), col5 = c(2300L, 2995L, 4400L, 6800L, 1999L, 
NA)), class = "data.frame", row.names = c("1", "2", "3", "4", 
"5", "6"))
Related