2017-01-24 14 views
-1

Давайте используем набор данных airquality в качестве базы.R reshape2 или dplyr/tidyr: вычисляемые значения процентов от общего количества

myaqm <- melt(airquality, id=c("Month", "Day"), na.rm = TRUE) 

Это дает мне упрощение моего реального набора данных. До сих пор, я сделал это:

myaqm_dcast <- dcast(myaqm, Day+variable~Month, value.var = "value", sum, margins=c("Day", "variable", "Month")) 

Который дает мне это:

> head(myaqm_dcast, n=10) 
    Day variable  5  6  7  8  9 (all) 
1 1 Ozone 41.0 0.0 135.0 39.0 96.0 311.0 
2 1 Solar.R 190.0 286.0 269.0 83.0 167.0 995.0 
3 1  Wind 7.4 8.6 4.1 6.9 6.9 33.9 
4 1  Temp 67.0 78.0 84.0 81.0 91.0 401.0 
5 1 (all) 305.4 372.6 492.1 209.9 360.9 1740.9 
6 2 Ozone 36.0 0.0 49.0 9.0 78.0 172.0 
7 2 Solar.R 118.0 287.0 248.0 24.0 197.0 874.0 
8 2  Wind 8.0 9.7 9.2 13.8 5.1 45.8 
9 2  Temp 72.0 74.0 85.0 81.0 92.0 404.0 
10 2 (all) 234.0 370.7 391.2 127.8 372.1 1495.8 

Однако я пытаюсь создать дополнительный variables'-процентном из-days'-подытог для каждого текущего столбца. Поэтому моя цель - это что-то вроде:

Day  variable  5  5(day %)  6  6(day %)  7  7(day %)  8  8(day %)  9  9(day %)  (all)  (all)(day %) 
1  Ozone  41  13.4%  0  0.0%  135  27.4%  39  18.6%  96  26.6%  311  17.9% 
1  Solar.R  190  62.2%  286  76.8%  269  54.7%  83  39.5%  167  46.3%  995  57.2% 
1  Wind  7.4  2.4%  8.6  2.3%  4.1  0.8%  6.9  3.3%  6.9  1.9%  33.9  1.9% 
1  Temp  67  21.9%  78  20.9%  84  17.1%  81  38.6%  91  25.2%  401  23.0% 
1  (all)  305.4  100.0%  372.6  100.0%  492.1  100.0%  209.9  100.0%  360.9  100.0%  1740.9  100.0% 
2  Ozone  36  15.4%  0  0.0%  49  12.5%  9  7.0%  78  21.0%  172  11.5% 
2  Solar.R  118  50.4%  287  77.4%  248  63.4%  24  18.8%  197  52.9%  874  58.4% 
2  Wind  8  3.4%  9.7  2.6%  9.2  2.4%  13.8  10.8%  5.1  1.4%  45.8  3.1% 
2  Temp  72  30.8%  74  20.0%  85  21.7%  81  63.4%  92  24.7%  404  27.0% 
2  (all)  234  100.0%  370.7  100.0%  391.2  100.0%  127.8  100.0%  372.1  100.0%  1495.8  100.0% 

Извините за страшное форматирование! Но, как вы можете надеяться, новые дополнительные столбцы дают процент каждой переменной за этот день и этот месяц.

Я нашел другого помощника по переполнению стека, предлагая использовать tidyr и dplyr, но я просто не мог приспособить их пример к моим потребностям. Кто-нибудь, пожалуйста, покажите мне, что делать?

ответ

3

Я написал функцию процента и использовал это с dplyr. Затем я присоединяюсь к колонкам вместе.

pct <- function(x) {x/sum(x)} 

df <- myaqm_dcast %>% 
    filter(variable != "(all)") %>% 
    group_by(Day) %>% 
    mutate_each(funs(pct), 3:8) %>% 
    inner_join(myaqm_dcast, by = c("Day", "variable")) 

Edit: Вы можете изменить процентную функцию для печати, однако вам необходимо (* 100, вставить символ%).

Редактировать 2: Если вы можете жить без (всех) строк, я отфильтровал его. Вы всегда можете рассчитать суммы столбцов, используя функцию summaryise().

+1

Это было бы правильным ответом, если бы нужно было разделить каждый столбец на столбец 8 - но это не вопрос. Для каждого столбца вам нужно перебрать все пять строк и разделить на '(all)'. Поэтому сначала вы должны расплавиться по столбцам 5, 6, 7, 8, 9, (все), а затем разделите по строке 'all' –

+0

Спасибо the_darkside. Ответ Райана, похоже, работает, поскольку я получаю шесть новых столбцов с десятичными знаками, которые соответствуют процентам в моем примере (спасибо Райан!), Однако мне бы хотелось, чтобы вы подробно объяснили свое объяснение.
Единственное, что я хочу добавить, что я должен был использовать вместо:
проц <- функция (х) {х/сумма (х) * 2}
, как я считаю, что включение (все) в сумме было то, что десятичные знаки были половиной того, что они должны были быть.
Примечание: ненадолго удерживая прием ответа на случай, если вы хотите добавить что-то дополнительное. –

+1

Это потому, что решение Райана добавляет значения для каждой из 4 переменных вместе с строкой '(all)', что означает, что сумма делится на два раза больше, чем она должна быть.Вместо умножения на 2 в функции 'pct' вы можете вставить' slice (-n()) 'в строке перед' mutate_each'. – user127649

1

Зачем вам переделывать данные? Dataframe myaqm отвечает требованиям tidy data (каждый столбец является переменной, каждая строка является наблюдением). Вы можете сделать свои расчеты в этом формате:

library(dplyr) 
myaqm %>% 
    group_by(Day, variable) %>% 
    mutate(all = sum(value), 
    perc = paste0(round(100 * value/all, 2), "%") 

Даже для создания графиков этого формат лучше подходит, чем реконструированные один (например, с помощью ggplot.).

Если действительно необходимо вы можете изменить с tidyr/dplyr:

... 
gather(key, val, -c(Month:variable, all)) %>% 
unite(temp, Month, key) %>% 
spread(temp, val) 
+0

Спасибо за вашу помощь, но похоже, что ваши проценты основаны на сумме всех месяцев для данного дня и данной переменной, а не на сумме переменных за данный день в данном месяце. На ваш вопрос: «Зачем вам изменять ваши данные?» позвольте мне перефразировать клиента и сказать: «Потому что я плачу вам, чтобы отдать его мне в таком формате». В очередной раз благодарим за помощь! –

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

  • Нет связанных вопросов^_^