计算一组特定列的异常值,然后识别具有 >5 列异常值的 ID
Calculate outliers of a group of specific columns then identify ids which have >5 columns with outliers
我正在使用大数据框 (df)。我想根据平均值 + 3 sd 计算特定列子集的异常值。
我首先提取了我想要的列,所以所有列的列名中都有颜色。
colors = colnames(df)[grep('color', colnames(df))]
我不确定我应该如何循环它以使用这个新变量计算所有列的离群值。我的公式是:
# id those with upper outliers
uthr = mean(df$color)+3*sd(df$color)
rm_u_ids = df$id[which(df$color >= uthr)]
# id those with lower outliers
lthr = mean(df$color)-3*sd(df$color)
rm_l_ids = df$id[which(df$color <= lthr)]
# remove those with both upper and lower outliers
rm_ids = sort(c(rm_u_ids, rm_l_ids))
df_2 = df %>% filter(!id %in% rm_ids)
现在,实际问题。
我想使用类似的东西来执行以下操作:
1) 对于 colors
中的每种颜色,识别那些具有异常值的 id,也许将此信息保存在其他地方,
2) 使用该信息(可能在列表或单独的数据框中),识别出现在 5 列或更多列中的 id,或 colors
,
3) 使用此列表对原始数据框进行子集化,以便我们消除那些在 5 个颜色列或更多列中具有异常值的 ID。
这有意义吗?我不确定这个问题是否也推荐使用循环。
谢谢你,如果我让它听起来比应该的更复杂,我很抱歉!
您可以创建一个函数,其中 returns id
的离群值
find_outlier <- function(df, x) {
uthr = mean(x)+3*sd(x)
rm_u_ids = df$id[which(x >= uthr)]
# id those with lower outliers
lthr = mean(x)-3*sd(x)
rm_l_ids = df$id[which(x <= lthr)]
# remove those with both upper and lower outliers
unique(sort(c(rm_u_ids, rm_l_ids)))
}
将它应用于每个 colors
列,用 table
计算它们的计数并删除出现超过 5 次的 id
。
all_ids <- lapply(df[colors], find_outlier, df = df)
temp_tab <- table(unlist(all_ids))
remove_ids <- names(temp_tab[temp_tab >= 5])
subset(df, !id %in% remove_ids)
我假设你的data.frame
只有你想要的数字变量
findOutlierCols = function(color.df){
hasOutliers = function(col){
bds = mean(col) + c(-3,3)*sd(col)
if(any(col <= bds[1]) || any(col >= bds[2])){
return(TRUE)
}else{
return(FALSE)
}
}
apply(color.df, 2, hasOutliers)
}
## make some fake data
set.seed(123)
x = matrix(rnorm(1000), ncol = 10)
color.df = data.frame(x)
colnames(x) = paste0("color.", colors()[1:10])
color.df = apply(color.df, 2, function(col){col+rbinom(100, 5, 0.1)})
boxplot(color.df)
findOutlierCols(color.df)
> findOutlierCols(color.df)
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
除了已经提供的巧妙答案之外,另一种方法是将相关列转换为矩阵并使用一些快速矩阵运算:
df = iris
colors = colnames(iris)[1:4]
m = as.matrix(df[,colors])
# Standardize the numeric values in each column
m = scale(m)
# Apply some outlier definition rules, e.g.
# detect measurements with |Zscore|>3
outliers = abs(m)>3
# detect rows with at least 5 such measurements
outliers = rowSums(outliers)
which(outliers>=5)
我正在使用大数据框 (df)。我想根据平均值 + 3 sd 计算特定列子集的异常值。
我首先提取了我想要的列,所以所有列的列名中都有颜色。
colors = colnames(df)[grep('color', colnames(df))]
我不确定我应该如何循环它以使用这个新变量计算所有列的离群值。我的公式是:
# id those with upper outliers
uthr = mean(df$color)+3*sd(df$color)
rm_u_ids = df$id[which(df$color >= uthr)]
# id those with lower outliers
lthr = mean(df$color)-3*sd(df$color)
rm_l_ids = df$id[which(df$color <= lthr)]
# remove those with both upper and lower outliers
rm_ids = sort(c(rm_u_ids, rm_l_ids))
df_2 = df %>% filter(!id %in% rm_ids)
现在,实际问题。
我想使用类似的东西来执行以下操作:
1) 对于 colors
中的每种颜色,识别那些具有异常值的 id,也许将此信息保存在其他地方,
2) 使用该信息(可能在列表或单独的数据框中),识别出现在 5 列或更多列中的 id,或 colors
,
3) 使用此列表对原始数据框进行子集化,以便我们消除那些在 5 个颜色列或更多列中具有异常值的 ID。
这有意义吗?我不确定这个问题是否也推荐使用循环。
谢谢你,如果我让它听起来比应该的更复杂,我很抱歉!
您可以创建一个函数,其中 returns id
的离群值
find_outlier <- function(df, x) {
uthr = mean(x)+3*sd(x)
rm_u_ids = df$id[which(x >= uthr)]
# id those with lower outliers
lthr = mean(x)-3*sd(x)
rm_l_ids = df$id[which(x <= lthr)]
# remove those with both upper and lower outliers
unique(sort(c(rm_u_ids, rm_l_ids)))
}
将它应用于每个 colors
列,用 table
计算它们的计数并删除出现超过 5 次的 id
。
all_ids <- lapply(df[colors], find_outlier, df = df)
temp_tab <- table(unlist(all_ids))
remove_ids <- names(temp_tab[temp_tab >= 5])
subset(df, !id %in% remove_ids)
我假设你的data.frame
只有你想要的数字变量
findOutlierCols = function(color.df){
hasOutliers = function(col){
bds = mean(col) + c(-3,3)*sd(col)
if(any(col <= bds[1]) || any(col >= bds[2])){
return(TRUE)
}else{
return(FALSE)
}
}
apply(color.df, 2, hasOutliers)
}
## make some fake data
set.seed(123)
x = matrix(rnorm(1000), ncol = 10)
color.df = data.frame(x)
colnames(x) = paste0("color.", colors()[1:10])
color.df = apply(color.df, 2, function(col){col+rbinom(100, 5, 0.1)})
boxplot(color.df)
findOutlierCols(color.df)
> findOutlierCols(color.df)
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
除了已经提供的巧妙答案之外,另一种方法是将相关列转换为矩阵并使用一些快速矩阵运算:
df = iris
colors = colnames(iris)[1:4]
m = as.matrix(df[,colors])
# Standardize the numeric values in each column
m = scale(m)
# Apply some outlier definition rules, e.g.
# detect measurements with |Zscore|>3
outliers = abs(m)>3
# detect rows with at least 5 such measurements
outliers = rowSums(outliers)
which(outliers>=5)