Хорошо - часть 1 (и стараемся по возможности избегать циклов):
Вот некоторые тестовые данные:
test_data=data.frame(
group=c(rep("a",100),rep("b",100)),
value=rnorm(200)
)
Мы найдем группы:
groups=levels(test_data[,1]) # or unique(test_data[,1]) if it isn't a factor
И мы рассчитаем пределы выбросов (здесь я указываю только 1 SD) - извините за l oop, но это только по группам, а не по данным:
outlier_sds=1
outlier_limits=sapply(groups,function(g) {
m=mean(test_data[test_data[,1]==g,2])
s=sd(test_data[test_data[,1]==g,2])
return(c(m-outlier_sds*s,m+outlier_sds*s))
})
Таким образом, мы можем определить пределы для каждой строки test_data
:
test_data_limits=outlier_limits[,test_data[,1]]
И использовать это для определения выбросов:
outliers=test_data[,2]<test_data_limits[1,] | test_data[,2]>test_data_limits[2,]
(или, комбинируя эти последние шаги):
outliers=test_data[,2]<outlier_limits[1,test_data[,1]] | test_data[,2]>outlier_limits[2,test_data[,1]]
Наконец:
test_data_without_outliers=test_data[!outliers,]
РЕДАКТИРОВАТЬ: теперь часть 2 (примените часть 1 с помощью al oop ко всем столбцам данных):
Некоторые тесты данные с более чем одним столбцом значений:
test_data2=data.frame(
group=c(rep("a",100),rep("b",100)),
value1=rnorm(200),
value2=2*rnorm(200),
value3=3*rnorm(200)
)
Объедините все шаги части 1 в новую функцию find_outliers
, которая возвращает логический вектор, указывающий, является ли какое-либо значение выбросом для соответствующего столбца и группы :
find_outliers = function(values,n_sds,groups) {
group_names=levels(groups)
outlier_limits=sapply(group_names,function(g) {
m=mean(values[groups==g])
s=sd(values[groups==g])
return(c(m-n_sds*s,m+n_sds*s))
})
return(values < outlier_limits[1,groups] | values > outlier_limits[2,groups])
}
А затем примените эту функцию к каждому из столбцов данных:
test_groups=test_data2[,1]
test_data_outliers=apply(test_data2[,-1],2,function(d) find_outliers(values=d,n_sds=1,groups=test_groups))
rowSums
из test_data_outliers
указывает, сколько времени Каждая строка считается «выбросом» в различных столбцах по отношению к своей собственной группе:
rowSums(test_data_outliers)