2017-01-24 4 views
3

Учитывая data_frame df <- data_frame(X = c('A', 'A', 'B', 'B', 'B'), Y = c('M', 'N', 'M', 'M', 'N')), мне нужно придумать data_frame, что говорит нам о том, что 50% от A «s являются M, 50% от A» s являются N, 67% из B «s являются M, и 33% B - N.Более элегантный способ вычисления внутригрупповых пропорций в dplyr?

У меня есть небольшая рутина, которую я использую для этого, но это кажется ужасным.

library(tidyverse) 
df <- data_frame(X = c('A', 'A', 'B', 'B', 'B'), Y = c('M', 'N', 'M', 'M', 'N')) 
# here we go... 
df %>% 
    group_by(X) %>% 
    mutate(n_X = n()) %>% 
    group_by(X, Y) %>% 
    summarise(PERCENT = n()/first(n_X)) 

, который выводит,

Source: local data frame [4 x 3] 
Groups: X [?] 

     X  Y PERCENT 
    <chr> <chr>  <dbl> 
1  A  M 0.5000000 
2  A  N 0.5000000 
3  B  M 0.6666667 
4  B  N 0.3333333 

Есть не лучший способ сделать это? Конечно, я что-то упускаю.

ответ

5

Вы можете использовать prop.table:

df %>% 
    group_by(X, Y) %>% 
    count() %>% 
    mutate(PERCENT = prop.table(n)) 

Результат:

 X  Y  n PERCENT 
    <chr> <chr> <int>  <dbl> 
1  A  M  1 0.5000000 
2  A  N  1 0.5000000 
3  B  M  2 0.6666667 
4  B  N  1 0.3333333 
4

Мы можем попытаться в базе R, используя table и rowSums

new_df <- table(df$X, df$Y) 
new_df/rowSums(new_df) 

#   M   N 
# A 0.5000000 0.5000000 
# B 0.6666667 0.3333333 
2

Может быть, это:

с dplyr

library(dplyr) 
df %>% count(X, Y) %>% 
    mutate(prop = n/sum(n)) 

с base R

tbl <- xtabs(~X+Y, df) 
as.data.frame(tbl/rowSums(tbl), responseName = "prop") 

с data.table

library(data.table) 
DT <- data.table(df)[, .N, by = .(X,Y)] 
setDT(DT)[, prop := N/sum(N), by = 'X'] 
DT 

# X Y N  prop 
#1: A M 1 0.5000000 
#2: A N 1 0.5000000 
#3: B M 2 0.6666667 
#4: B N 1 0.3333333