Рассчитать выбросы группы указанных столбцов c, а затем идентифицировать идентификаторы, которые имеют> 5 столбцов с выбросами - PullRequest
0 голосов
/ 31 марта 2020

Я работаю с большим фреймом данных (df). Я хотел бы рассчитать выбросы для определенного c подмножества столбцов на основе среднего значения + 3 SD.

Сначала я извлек нужные столбцы, поэтому все имена столбцов окрашены в цвет.

colors = colnames(df)[grep('color', colnames(df))]

Я не уверен, как мне тогда go сделать цикл, чтобы вычислить выбросы по всем столбцам, используя эту новую переменную. У меня была формула:

# 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, идентифицируйте эти идентификаторы с выбросами, возможно, сохраните эту информацию в другом месте, 2) используя эту информацию (возможно, в списке или отдельном фрейме данных), идентифицируйте идентификаторы, появившиеся в 5 или более столбцах, или colors, 3) подставьте в исходный фрейм данных этот список, чтобы мы исключили эти идентификаторы с выбросами в 5 или более цветовых столбцах.

Имеет ли это смысл ? Я не уверен, что al oop также рекомендуется для этой проблемы.

Спасибо и извините, если я сделал это звучит более сложно, чем должно быть!

Ответы [ 3 ]

2 голосов
/ 31 марта 2020

Альтернативой умным ответам, уже предоставленным, является преобразование соответствующих столбцов в матрицу и использование некоторых быстрых матричных операций:

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)
1 голос
/ 31 марта 2020

Я собираюсь предположить, что ваш data.frame имеет только те цифры c переменных, которые вы хотите

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)

enter image description here

> findOutlierCols(color.df)
   X1    X2    X3    X4    X5    X6    X7    X8    X9   X10 
 TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE 
1 голос
/ 31 марта 2020

Вы можете создать функцию, которая возвращает 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 и удалите id '. с, которые встречаются более 5 раз.

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)
...