Simple way to delete dataframe rows robust to instances where no rows match deletion criteria
r
Solution
You've stumbled on to a common issue with using `which`. Use `!=` instead.
new_data <- data[data$Treatment!="G4",]
The problem is that `which` returns `integer(0)` if all the elements are `FALSE`. This would still be an issue even if `which` returned `0` because subsetting by zero also returns `integer(0)`:
R> # subsetting by zero (positive or negative)
R> (1:3)[0] # same as (1:3)[-0]
integer(0)
You will also run into issues if you subset by `NA`:
R> # subsetting by NA
R> (1:3)[NA]
[1] NA NA NA
Problem
One common task in data manipulation in R is subseting a dataframe by removing rows that match a certain criteria. However, the simple way to do this in R seems logically inconsistent and even dangerous to the unexperienced (like myself). Lets say we have a data frame and we want to exclude rows that belong to the "G1" treatment: ``` Treatment=c("G1","G1","G1","G1","G1","G1","G2","G2","G2","G2","G2", "G2","G3","G3","G3","G3","G3","G3") Vals=c(runif(6),runif(6)+0.9,runif(6)-0.3) data=data.frame(Treatment) data=cbind(data, Vals) ``` As expected, the code below removes the dataframe rows that match the criteria of the first line ``` to_del=which(data$Treatment=="G1") new_data=data[-to_del,] new_data ``` However, contrary to expected, using this approach if the 'which' command does not find ANY matching row this code removes all rows instead of leaving them all alone ``` to_del=which(data$Treatment=="G4") new_data=data[-to_del,] new_data ``` The code above results in a data frame with no rows left, which makes no sense (i.e., since R found no rows that match my criteria for deletion, it deleted all rows). My work-around does the job but I would imagine there is a simpler way to do this without all of these conditional statements ``` ###WORKAROUND to_del=which(data$Treatment=="G4") #no G4 treatment in this particular data frame if (length(to_del)>0){ new_data=data[-to_del,] }else{ new_data=data } new_data ``` Does anyone have a simple way to do this that works even when no rows match specified criteria?