One of the ways to deal with outliers is to use tukey border values to either set the data outside it to missing or to set it to the border value. For the lower part of the distribution it is defined as $Q1-1.5IQR$ and for the higher part $Q3 + 1.5 IQR$, where Q1 and Q3 are 1st and 3rd quartile values, and IQR is inter-quartile range. The values lower than the first, or higher than the second value should be seto to NA or replaced with these border values. I prefer setting the values to missing if there are not more than 10% of missing values after this transformation.
The other way to deal with the problem is to use $M\pm3SD$. You set all values above and below these values to NA.
Here are two functions in R you can use to do the work for you.
# Function identifies either tukey (tuk) or sd (sd) border values (type),
# and the magnitude of the range (level) - normal tukey range is 1.5IQR,
# and usual range with SD is 3)
GRW <- function(x, type, level){
x <- unlist(x)
if (type == "tuk"){
IQR <- quantile(x,0.75, na.rm = T) - quantile(x,0.25, na.rm=T)
Q1 <- quantile(x, 0.25, na.rm=T) - level*IQR
Q2 <- quantile(x, 0.75, na.rm=T) + level*IQR
names(Q1) <- NULL
names(Q2) <- NULL
return (c(Q1 = Q1, Q2 = Q2))
}
if (type == "sd"){
SD_l <- mean(x, na.rm=T) - level*sd(x, na.rm=T)
SD_h <- mean(x, na.rm=T) + level*sd(x, na.rm=T)
names(SD_l) <- NULL
names(SD_h) <- NULL
return(c(SD_l = SD_l, SD_h = SD_h))
}
}
# Function returns vector with tukey/sd (type) with manually defined
# range (level), only on positive(pos), negative (neg) or both ends (double)
# and it either replaces the outliers with border values (replace = TRUE)
# or sets them to NA (replace = FALSE)
REPL <- function (var, type, level, end, replace) {
# Only positive end
if (end == "pos") {
if (replace == FALSE) {
var[var>GRW(var,type,level)[2]] <- NA
var
}
if (replace == TRUE){
var[var>GRW(var,type,level)[2]] <- GRW(var,type,level)[2]
var
}
}
# Only negative end
if (end == "neg") {
if (replace == FALSE) {
var[var<GRW(var,type,level)[1]] <- NA
var
}
if (replace == TRUE){
var[var<GRW(var,type,level)[1]] <- GRW(var,type,level)[1]
var
}
}
# Double end
if (end == "double"){
if (replace == FALSE) {
var[var<GRW(var,type,level)[1]] <- NA
var[var>GRW(var,type,level)[2]] <- NA
var
}
if (replace == TRUE){
var[var<GRW(var,type,level)[1]] <- GRW(var,type,level)[1]
var[var>GRW(var,type,level)[2]] <- GRW(var,type,level)[2]
var
}
}
var
}
Btw. if you want to check for outliers visually, use the function boxplot(), or in ggplot geom_boxplot()