Получить среднее значение для группы с несколькими переменными группирования и исключить значение собственной группы - PullRequest
2 голосов
/ 17 января 2020

Я ищу более быстрый способ вычисления среднего значения для группы с несколькими переменными группирования, исключая при этом значения собственной группы. Мысленный эксперимент будет найти среднее значение (например, цену) для округа из округов в том же штате в том же году, исключая стоимость собственного округа. Вот набор игрушечных данных.

df <- data_frame(
  state = rep(c("AL", "CA"), each = 6),
  county = rep(letters[1:6], each = 2),
  year = rep(c(2011:2012), 6),
  value = sample.int(100, 12)
)

df %>%
  group_by(state, county, year) %>%
  summarise(q = mean(df$value[df$state == state & df$county != county & df$year == year]))

# Groups:   state, county [6]
   state county  year     q
   <chr> <chr>  <int> <dbl>
 1 AL    a       2011  56  
 2 AL    a       2012  46  
 3 AL    b       2011  50.5
 4 AL    b       2012  52  
 5 AL    c       2011  55.5
 6 AL    c       2012  29  
 7 CA    d       2011  52.5
 8 CA    d       2012  32  
 9 CA    e       2011  68.5
10 CA    e       2012  31.5
11 CA    f       2011  32  
12 CA    f       2012  42.5

Приведенный выше код дает мне желаемый результат, но когда я применяю его к большему набору данных (с большим количеством переменных группировки), он становится действительно медленным. Есть ли у вас какие-либо предложения о том, как ускорить это?

Если первоначальный подход неверен, укажите это также.

Ответы [ 2 ]

2 голосов
/ 17 января 2020
library(dplyr)

df %>%
  group_by(state, year) %>%
  mutate(q = (sum(value) - value) / (n()-1))

#> # A tibble: 12 x 5
#> # Groups:   state, year [4]
#>    state county  year value     q
#>    <chr> <chr>  <int> <int> <dbl>
#>  1 AL    a       2011    68  30.5
#>  2 AL    a       2012    63  42  
#>  3 AL    b       2011    53  38  
#>  4 AL    b       2012    56  45.5
#>  5 AL    c       2011     8  60.5
#>  6 AL    c       2012    28  59.5
#>  7 CA    d       2011     7  40  
#>  8 CA    d       2012    69  41  
#>  9 CA    e       2011    39  24  
#> 10 CA    e       2012    79  36  
#> 11 CA    f       2011    41  23  
#> 12 CA    f       2012     3  74

Данные:

#data_frame is deprecate!
df <- tibble(
  state = rep(c("AL", "CA"), each = 6),
  county = rep(letters[1:6], each = 2),
  year = rep(c(2011:2012), 6),
  value = sample.int(100, 12)
)
2 голосов
/ 17 января 2020

Более эффективным подходом будет sum значение после группировки по состоянию, году, вычитание из значения, затем деление n() - 1 наблюдений

library(dplyr)   
library(purrr) 
out2 <- df %>%
          group_split(state, year) %>%
          map_dfr(~ .x %>% 
                 mutate(q = (sum(value) - value)/(n()-1))) %>%
          select(-value) %>%
          arrange(state, county)

-проверка с выходом OP ('out1')

all.equal(out2, out1, check.attributes = FALSE)
#[1] TRUE
...