Вычислите среднее значение для последовательности строк, затем удалите все, что больше 2SD среднего значения в R - PullRequest
2 голосов
/ 25 марта 2020

У меня большой набор данных из более чем 10000 строк: df:

  User              duration

  amy                582         
  amy                27
  amy                592
  amy                16
  amy                250
  tom                33
  tom                10
  tom                40
  tom                100

Желаемый вывод:

User               duration

amy                 582
amy                 592
amy                 250
tom                 33
tom                 10
tom                 40

По существу, это будет удалять любые выбросы, которые являются 2SD от каждого уникального значения пользователя. Код будет принимать среднее значение для каждого уникального пользователя, определять его среднее значение и стандартное отклонение, а затем удалять значения, которые> 2SD от среднего значения.

dput:

structure(list(User = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L), .Label = c("amy", "tom"), class = "factor"), duration = c(582L, 
27L, 592L, 16L, 250L, 33L, 10L, 40L, 100L)), class = "data.frame", row.names = c(NA, 
-9L))

Это то, что я пробовал:

first define average and standard deviation


      ave = ave(df$duration)
      sd =  sd(df$duration)

И затем установить какой-то параметр для этого:

     for i in df {
     remove all if > 2*sd}

Я не уверен и хотел бы некоторые предложения.

Ответы [ 4 ]

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

Мы можем использовать dplyr, что было бы очень кратко при использовании с between

library(dplyr)
df %>% 
   group_by(User) %>%
   filter(between(duration, mean(duration) -  sd(duration), 
                           mean(duration) +   sd(duration)))
2 голосов
/ 25 марта 2020

Вы можете использовать scale(), чтобы найти оценку z и сохранить абсолютные значения менее 2:

library(dplyr)

df %>%
  group_by(User) %>%
  filter(abs(scale(duration)) < 2)

# A tibble: 9 x 2
# Groups:   User [2]
  User  duration
  <fct>    <int>
1 amy        582
2 amy         27
3 amy        592
4 amy         16
5 amy        250
6 tom         33
7 tom         10
8 tom         40
9 tom        100
2 голосов
/ 25 марта 2020

Вот подход data.table, который может быть быстрее для многих строк.

library(data.table)
df <- structure(list(User = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L), .Label = c("amy", "tom"), class = "factor"), duration = c(50000, 
582, 27, 592, 16, 250, 33, 10, 40, 100)), row.names = c(NA, -10L
), class = "data.frame")
df
   User duration
1   amy    50000
2   amy      582
3   amy       27
4   amy      592
5   amy       16
6   amy      250
7   tom       33
8   tom       10
9   tom       40
10  tom      100

Код

setDT(df)[,.SD[duration <= mean(duration) + (2 * sd(duration)) &
               duration >= mean(duration) - (2 * sd(duration)),]
          ,by=User]
   User duration
1:  amy      582
2:  amy       27
3:  amy      592
4:  amy       16
5:  amy      250
6:  tom       33
7:  tom       10
8:  tom       40
9:  tom      100
1 голос
/ 25 марта 2020

Мы можем попробовать использовать функции mutate и filter в dplyr

library(dplyr)
df %>% group_by(User) %>% mutate(ave_plus2sd=ave(duration)+2*sd(duration)) %>% 
filter(duration < ave_plus2sd) 

Это даст вам следующий вывод, который позволяет сравнивать каждую запись со средним + 2 * SD для пользователя.

# Groups:   User [2]
  User  duration ave_plus2sd
  <fct>    <int>       <dbl>
1 amy        582        861.
2 amy         27        861.
3 amy        592        861.
4 amy         16        861.
5 amy        250        861.
6 tom         33        122.
7 tom         10        122.
8 tom         40        122.
9 tom        100        122.

Мы можем дополнительно добавить %>% select (User,duration), чтобы выбрать интересующие вас столбцы пользователя и продолжительность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...