programing

dplyr을 사용한 상대 빈도/비율

sourcejob 2023. 6. 13. 22:14
반응형

dplyr을 사용한 상대 빈도/비율

각 그룹 내에서 서로 다른 값의 비율을 계산하려고 합니다.예를 들어, 다음을 사용합니다.mtcars데이터, 암(자동/수동)에 의한 기어 수의 상대 주파수를 어떻게 계산합니까?dplyr?

library(dplyr)
data(mtcars)
mtcars <- tbl_df(mtcars)

# count frequency
mtcars %>%
  group_by(am, gear) %>%
  summarise(n = n())

# am gear  n
#  0    3 15 
#  0    4  4 
#  1    4  8  
#  1    5  5 

달성하고자 하는 목표:

am gear  n rel.freq
 0    3 15      0.7894737
 0    4  4      0.2105263
 1    4  8      0.6153846
 1    5  5      0.3846154

사용해 보십시오.

mtcars %>%
  group_by(am, gear) %>%
  summarise(n = n()) %>%
  mutate(freq = n / sum(n))

#   am gear  n      freq
# 1  0    3 15 0.7894737
# 2  0    4  4 0.2105263
# 3  1    4  8 0.6153846
# 4  1    5  5 0.3846154

dplyrvignet에서:

여러 변수로 그룹화하면 각 요약이 그룹화의 한 수준에서 벗겨집니다.따라서 데이터 세트를 점진적으로 롤업하기가 쉽습니다.

그러므로, 그 후에.summarise지정된 마지막 그룹화 변수group_by'기어'가 벗겨집니다.에서mutate단계에서 데이터는 나머지 그룹화 변수(여기서 'am')별로 그룹화됩니다.각 단계에서 그룹화를 확인할 수 있습니다.groups.

필링의 결과는 물론 그룹화 변수의 순서에 따라 달라집니다.group_by호출합니다. 다음 단계를 수행할 수 있습니다.group_by(am)코드를 보다 명확하게 표시합니다.

라운딩과 프레이팅은 @Tyler Lincer의 멋진 답변을 참고하시기 바랍니다.

사용할 수 있습니다.count()그러나 버전에 따라 다른 동작을 갖는 함수dplyr:

  • dplyr 0.7.1: 그룹화되지 않은 테이블을 반환합니다. 다음 기준으로 다시 그룹화해야 합니다.am

  • dplyr < 0.7.1: 그룹화된 테이블을 반환하므로 다시 그룹화할 필요가 없습니다.ungroup()추후의 조작을 위하여.

dplyr 0.7.1

mtcars %>%
  count(am, gear) %>%
  group_by(am) %>%
  mutate(freq = n / sum(n))

dplyr < 0.7.1

mtcars %>%
  count(am, gear) %>%
  mutate(freq = n / sum(n))

그러면 그룹화된 테이블이 생성됩니다. 추가 분석에 사용하려면 그룹화된 속성을 제거하는 것이 유용할 수 있습니다.ungroup().

@헨릭은 열 문자가 더 이상 숫자가 아니라 요청한 내용과 일치하기 때문에 유용성에 더 좋습니다.

mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n()) %>%
  mutate(rel.freq = paste0(round(100 * n/sum(n), 0), "%"))

##   am gear  n rel.freq
## 1  0    3 15      79%
## 2  0    4  4      21%
## 3  1    4  8      62%
## 4  1    5  5      38%

스페이스맨이 요청했기 때문에 편집 :-)

as.rel_freq <- function(x, rel_freq_col = "rel.freq", ...) {
    class(x) <- c("rel_freq", class(x))
    attributes(x)[["rel_freq_col"]] <- rel_freq_col
    x
}

print.rel_freq <- function(x, ...) {
    freq_col <- attributes(x)[["rel_freq_col"]]
    x[[freq_col]] <- paste0(round(100 * x[[freq_col]], 0), "%")   
    class(x) <- class(x)[!class(x)%in% "rel_freq"]
    print(x)
}

mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n()) %>%
  mutate(rel.freq = n/sum(n)) %>%
  as.rel_freq()

## Source: local data frame [4 x 4]
## Groups: am
## 
##   am gear  n rel.freq
## 1  0    3 15      79%
## 2  0    4  4      21%
## 3  1    4  8      62%
## 4  1    5  5      38%

많은 답변에도 불구하고, 다음과 같은 방법을 사용합니다.prop.table'dplyr' 또는 'data.table'과 함께 사용할 수 있습니다.

'dplyr' v. >= 1.1.0 이후 우리는 다음을 사용할 수 있습니다..by에 있어서의 논쟁.mutate:

library(dplyr)

mtcars %>%
  count(am, gear) %>% 
  mutate(freq = prop.table(n), .by = am)

#>   am gear  n      freq
#> 1  0    3 15 0.7894737
#> 2  0    4  4 0.2105263
#> 3  1    4  8 0.6153846
#> 4  1    5  5 0.3846154

dplyr v. < 1.1.0> 이전의 한 가지 접근 방식은 다음과 같습니다.

mtcars %>%
  group_by(am, gear) %>% 
  tally() %>% 
  mutate(freq = prop.table(n))

#> # A tibble: 4 × 4
#> # Groups:   am [2]
#>      am  gear     n  freq
#>   <dbl> <dbl> <int> <dbl>
#> 1     0     3    15 0.789
#> 2     0     4     4 0.211
#> 3     1     4     8 0.615
#> 4     1     5     5 0.385

'data.table'을 사용하면 다음을 수행할 수 있습니다.

library(data.table)
cars_dt <- as.data.table(mtcars)
cars_dt[, .(n = .N), keyby = .(am, gear)][, freq := prop.table(n), by = "am"][]

#>    am gear  n      freq
#> 1:  0    3 15 0.7894737
#> 2:  0    4  4 0.2105263
#> 3:  1    4  8 0.6153846
#> 4:  1    5  5 0.3846154

repref v2.0.2를 사용하여 2022-10-22에 생성됨

이 반복 작업을 위해 작은 함수를 작성했습니다.

count_pct <- function(df) {
  return(
    df %>%
      tally %>% 
      mutate(n_pct = 100*n/sum(n))
  )
}

그런 다음 다음과 같이 사용할 수 있습니다.

mtcars %>% 
  group_by(cyl) %>% 
  count_pct

반환되는 항목:

# A tibble: 3 x 3
    cyl     n n_pct
  <dbl> <int> <dbl>
1     4    11  34.4
2     6     7  21.9
3     8    14  43.8

이 인기 있는 질문의 완전성을 위해 버전 1.0.0 이후dplyrparameter .groups는 그룹화 구조를 제어합니다.summarise 뒤에 합니다.group_by 도움말을 요약합니다.

와 함께.groups = "drop_last",summarise그룹화의 마지막 수준을 삭제합니다.이것은 버전 1.0.0 이전에 얻은 유일한 결과입니다.

library(dplyr)
library(scales)

original <- mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n()) %>%
  mutate(rel.freq =  scales::percent(n/sum(n), accuracy = 0.1))
#> `summarise()` regrouping output by 'am' (override with `.groups` argument)

original
#> # A tibble: 4 x 4
#> # Groups:   am [2]
#>      am  gear     n rel.freq
#>   <dbl> <dbl> <int> <chr>   
#> 1     0     3    15 78.9%   
#> 2     0     4     4 21.1%   
#> 3     1     4     8 61.5%   
#> 4     1     5     5 38.5%

new_drop_last <- mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n(), .groups = "drop_last") %>%
  mutate(rel.freq =  scales::percent(n/sum(n), accuracy = 0.1))

dplyr::all_equal(original, new_drop_last)
#> [1] TRUE

와 함께.groups = "drop"모든 그룹화 수준이 삭제됩니다.결과는 이전의 흔적이 없는 독립적인 경골로 바뀝니다.group_by

# .groups = "drop"
new_drop <- mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n(), .groups = "drop") %>%
  mutate(rel.freq =  scales::percent(n/sum(n), accuracy = 0.1))

new_drop
#> # A tibble: 4 x 4
#>      am  gear     n rel.freq
#>   <dbl> <dbl> <int> <chr>   
#> 1     0     3    15 46.9%   
#> 2     0     4     4 12.5%   
#> 3     1     4     8 25.0%   
#> 4     1     5     5 15.6%

한다면.groups = "keep"이 mtcarsdata와 동일한 그룹 구조(이 경우 mtcars). summarise는 서사용변제않습니다거에 하지 않습니다.group_by.

마막으로와 함께..groups = "rowwise"각 행은 고유한 그룹입니다.은 이 에서 "하는 것과 .

# .groups = "keep"
new_keep <- mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n(), .groups = "keep") %>%
  mutate(rel.freq =  scales::percent(n/sum(n), accuracy = 0.1))

new_keep
#> # A tibble: 4 x 4
#> # Groups:   am, gear [4]
#>      am  gear     n rel.freq
#>   <dbl> <dbl> <int> <chr>   
#> 1     0     3    15 100.0%  
#> 2     0     4     4 100.0%  
#> 3     1     4     8 100.0%  
#> 4     1     5     5 100.0%

# .groups = "rowwise"
new_rowwise <- mtcars %>%
  group_by (am, gear) %>%
  summarise (n=n(), .groups = "rowwise") %>%
  mutate(rel.freq =  scales::percent(n/sum(n), accuracy = 0.1))

dplyr::all_equal(new_keep, new_rowwise)
#> [1] TRUE

관심을 가질 수 있는 또 다른 점은 때때로 적용한 후에group_by그리고.summarise요약 행이 도움이 될 수 있습니다.

# create a subtotal line to help readability
subtotal_am <- mtcars %>%
  group_by (am) %>% 
  summarise (n=n()) %>%
  mutate(gear = NA, rel.freq = 1)
#> `summarise()` ungrouping output (override with `.groups` argument)

mtcars %>% group_by (am, gear) %>%
  summarise (n=n()) %>% 
  mutate(rel.freq = n/sum(n)) %>%
  bind_rows(subtotal_am) %>%
  arrange(am, gear) %>%
  mutate(rel.freq =  scales::percent(rel.freq, accuracy = 0.1))
#> `summarise()` regrouping output by 'am' (override with `.groups` argument)
#> # A tibble: 6 x 4
#> # Groups:   am [2]
#>      am  gear     n rel.freq
#>   <dbl> <dbl> <int> <chr>   
#> 1     0     3    15 78.9%   
#> 2     0     4     4 21.1%   
#> 3     0    NA    19 100.0%  
#> 4     1     4     8 61.5%   
#> 5     1     5     5 38.5%   
#> 6     1    NA    13 100.0%

reprex 패키지(v0.3.0)에 의해 2020-11-09에 생성되었습니다.

이 답변이 유용하기를 바랍니다.

Henrik의 솔루션을 구현하는 일반적인 기능은 다음과 같습니다.dplyr0.7.1.

freq_table <- function(x, 
                       group_var, 
                       prop_var) {
  group_var <- enquo(group_var)
  prop_var  <- enquo(prop_var)
  x %>% 
    group_by(!!group_var, !!prop_var) %>% 
    summarise(n = n()) %>% 
    mutate(freq = n /sum(n)) %>% 
    ungroup
}

또한 (pesky group_by.groups 주위를 둘러보세요).

mtcars %>% 
  count(am, gear) %>% 
  add_count(am, wt = n, name = "nn") %>% 
  mutate(proportion = n / nn)

에 다은음사기용한본다니입 R변답음다를 사용한 R.aggregate그리고.ave:

df1 <- with(mtcars, aggregate(list(n = mpg), list(am = am, gear = gear), length))
df1$prop <- with(df1, n/ave(n, am, FUN = sum))
#Also with prop.table
#df1$prop <- with(df1, ave(n, am, FUN = prop.table))
df1

#  am gear  n      prop
#1  0    3 15 0.7894737
#2  0    4  4 0.2105263
#3  1    4  8 0.6153846
#4  1    5  5 0.3846154 

우리는 또한 사용할 수 있습니다.prop.table그러나 출력이 다르게 표시됩니다.

prop.table(table(mtcars$am, mtcars$gear), 1)
   
#            3         4         5
#  0 0.7894737 0.2105263 0.0000000
#  1 0.0000000 0.6153846 0.3846154

이 대답은 마티푸의 대답을 바탕으로 한 것입니다.

먼저 scipen 옵션을 사용하여 freq 열이 과학적 표기 열로 반환되지 않도록 수정했습니다.

그런 다음 답에 100을 곱하여 소수가 아닌 백분율을 얻어서 freq 열을 백분율로 읽기 쉽게 만듭니다.

getOption("scipen") 
options("scipen"=10) 
mtcars %>%
count(am, gear) %>% 
mutate(freq = (n / sum(n)) * 100)

언급URL : https://stackoverflow.com/questions/24576515/relative-frequencies-proportions-with-dplyr

반응형