2014-10-28 3 views
2

У меня есть набор данных в R студенческих еженедельных пособий по классам, который выглядит как:Aggregation и расчет процентов по группам

Year ID Class  Allowance 
2013 123 Freshman 100 
2013 234 Freshman 110 
2013 345 Sophomore 150 
2013 456 Sophomore 200 
2013 567 Junior  250 
2014 678 Junior  100 
2014 789 Junior  230 
2014 890 Freshman 110 
2014 891 Freshman 250 
2014 892 Sophomore 220 

Как я могу подвести итоги по группам (год/класс), чтобы получить сумму и % (по группе)? Получение суммы кажется легким с ddply, просто не может получить% от групповой части справа.

Он работает sum:

summary <- ddply(my_data, .(Year, Class), summarize, Sum_Allow=sum(Allowance)) 

Но он не работает за процент от группы части:

summary <- ddply(my_data, .(Year, Class), summarize, Sum_Allow=sum(Allowance), 
       Allow_Pct=Allowance/sum(Allowance)) 

Идеальный результат должен выглядеть следующим образом:

Year  Class Sum_Allow Allow_Pct 
2013 Freshman  210  26% 
2013 Junior  250  31% 
2013 Sophomore  350  43% 
2014 Freshman  360  40% 
2014 Junior  330  36% 
2014 Sophomore  220  24% 

I попробовал ddply из пакета plyr, но, пожалуйста, сообщите мне, каким образом это может сработать.

+0

Вы пытаетесь связать кадры данных с неравным количеством строк. делать 'Sum_allow' и' allow_pct' индивидуально и смотреть на результаты.Вы можете использовать голову или хвост для получения первой или последней строки для каждого процента. – rawr

ответ

2

Вы можете сделать это в два этапа

my_data <- read.table(header = TRUE, 
         text = "Year ID Class  Allowance 
2013 123 Freshman 100 
2013 234 Freshman 110 
2013 345 Sophomore 150 
2013 456 Sophomore 200 
2013 567 Junior  250 
2014 678 Junior  100 
2014 789 Junior  230 
2014 890 Freshman 110 
2014 891 Freshman 250 
2014 892 Sophomore 220") 

library(plyr) 
(summ <- ddply(my_data, .(Year, Class), summarize, Sum_Allow=sum(Allowance))) 

# Year  Class Sum_Allow 
# 1 2013 Freshman  210 
# 2 2013 Junior  250 
# 3 2013 Sophomore  350 
# 4 2014 Freshman  360 
# 5 2014 Junior  330 
# 6 2014 Sophomore  220 

ddply(summ, .(Year), mutate, Allow_pct = Sum_Allow/sum(Sum_Allow) * 100) 

# Year  Class Sum_Allow Allow_pct 
# 1 2013 Freshman  210 25.92593 
# 2 2013 Junior  250 30.86420 
# 3 2013 Sophomore  350 43.20988 
# 4 2014 Freshman  360 39.56044 
# 5 2014 Junior  330 36.26374 
# 6 2014 Sophomore  220 24.17582 

Я не знаю, если это произойдет, для остальных из вас, но когда я запускаю первоначальную попытку, R срабатывает, а не бросает предупреждение. Или, если я пропущу Allow вместо разрешения, он сработает. Я действительно ненавижу это; hadley pls fix

base r forever

+0

Не уверен, какую роль играет * база R * в вашем решении –

+0

@DavidArenburg расстройство plyr, как описано выше – rawr

+0

О, я не получил никаких ошибок с вашим кодом, но 'plyr' в основном является оберткой для базы R , Я не думаю, что есть что-то написанное на C там –

5

Вот возможное решение с использованием data.table пакет (предполагается, что ваши данные называются df)

library(data.table) 
setDT(df)[, list(Sum_Allow = sum(Allowance)), keyby = list(Year, Class)][, 
      Allow_Pct := paste0(round(Sum_Allow/sum(Sum_Allow), 2)*100, "%"), by = Year][] 

# Year  Class Sum_Allow Allow_Pct 
# 1: 2013 Freshman  210  26% 
# 2: 2013 Junior  250  31% 
# 3: 2013 Sophomore  350  43% 
# 4: 2014 Freshman  360  40% 
# 5: 2014 Junior  330  36% 
# 6: 2014 Sophomore  220  24% 

Способствовал @rawr, вот возможная база R решение

df2 <- aggregate(Allowance ~ Class + Year, df, sum) 
transform(df2, Allow_pct = ave(Allowance, Year, FUN = function(x) paste0(round(x/sum(x), 2)*100, "%"))) 
#  Class Year Allowance Allow_pct 
# 1 Freshman 2013  210  26% 
# 2 Junior 2013  250  31% 
# 3 Sophomore 2013  350  43% 
# 4 Freshman 2014  360  40% 
# 5 Junior 2014  330  36% 
# 6 Sophomore 2014  220  24% 
1

Так предполагая то, что вы хочу:

  1. получить сумму столбца пособий во всех группах, определенных по годам и классу, и
  2. взять эту сумму и разделить его на общей сумме в соответствующем году

Тогда это может сделать трюк в dplyr :

library(dplyr) 
my_data <- read.table(header = TRUE, 
         text = 
'Year ID Class  Allowance 
2013 123 Freshman 100 
2013 234 Freshman 110 
2013 345 Sophomore 150 
2013 456 Sophomore 200 
2013 567 Junior  250 
2014 678 Junior  100 
2014 789 Junior  230 
2014 890 Freshman 110 
2014 891 Freshman 250 
2014 892 Sophomore 220') 

summary <- my_data %>% 
    group_by(Year) %>% 
    summarise(Year_Sum_Allow = sum(Allowance)) %>% 
    left_join(x = my_data, y = ., by = 'Year') %>% 
    group_by(Year, Class) %>% 
    summarise(Sum_Allow = sum(Allowance), 
      Allow_Pct = Sum_Allow/first(Year_Sum_Allow)) 

summary 

# Results 
Source: local data frame [6 x 4] 
Groups: Year 

    Year  Class Sum_Allow Allow_Pct 
1 2013 Freshman  210 0.2592593 
2 2013 Junior  250 0.3086420 
3 2013 Sophomore  350 0.4320988 
4 2014 Freshman  360 0.3956044 
5 2014 Junior  330 0.3626374 
6 2014 Sophomore  220 0.2417582 

Если вы не знакомы с dplyr, синтаксис может показаться странным. Предлагаю взглянуть на introduction. Это большая экономия времени.

Редактирование: я должен был добавить, что если вы хотите довольно округленное процентное форматирование в вашем примере вывода, вместо этого вы можете заменить Allow_Pct = paste0(round(Sum_Allow/first(Year_Sum_Allow), 2), '%') в последней строке.

Edit 2: Как jbaums указывает, это может быть упрощена:

my_data %>% 
    group_by(Year, Class) %>% 
    summarise(sum_allow=sum(Allowance)) %>% 
    mutate(pct_allow=sum_allow/sum(sum_allow)) 
+3

Это может быть упрощено: 'my_data%>% group_by (Year, Class)%>% summary (sum_allow = sum (Allowance))%>% mutate (pct_allow = sum_allow/сумма (sum_allow)) '. – jbaums

+0

@ jbaums, интересно, как последний 'mutate' знает, что он должен быть сгруппирован специально« годом », а не указан указанным выше« group_by »или не будет сгруппирован вообще ... –

+2

@DavidArenburg, From the [dplyr vignette] (http://cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html): «Когда вы группируетесь по нескольким переменным, каждая сводка отменяет один уровень группировки. Это упрощает для постепенного свертывания набора данных ». Таким образом, после «подведения итогов» переменная группировки «Класс» очищается, а затем данные группируются «только» на «Год». – Henrik

Смежные вопросы