Подсчитать количество ярлыков на сайте и создать сводную таблицу в R

Ниже приведена часть чего-то похожего на мой набор данных:

require(dplyr)
alldata
site    date    percent_rank    Label
01A  2013-01-01    0.32         Normal
01B  2013-01-01    0.12         Low
01C  2013-01-01    0.76         High
02A  2013-01-01     0           N/A
02B  2013-01-01    0.16         Low
02C  2013-01-01    0.5          Normal
01A  2013-01-02    0.67         Normal
01B  2013-01-02    0.01         Low
01C  2013-01-02    0.92         High

Я назначил каждому проценту_ранка метку на основе значения (от 0 до 0,25 до 0,75 до 1 для трех категорий). Теперь я хотел бы подготовить сводную таблицу в этом формате:

site  Low  Normal  High  Missing
01A   32   47      92    194
01B   232  23      17    93
01C   82   265     12    6

где каждый сайт будет иметь количество вхождений низких, нормальных и высоких значений для всех дат с этой меткой сайта (по одному на каждый день года), а значения N/A будут учитываться как "пропущенные" колонка.

Я пробовал следующее:

alldata <- %>% group_by(site) %>% mutate(length(Label == "Low"))

который возвращает общее значение всех записей, а не количество "Низкий" на сайт, и

alldata <- %>% group_by(site) %>% mutate(length(which(Label == "Low")))

который возвращает значение на несколько тысяч больше, чем общее количество записей. Идея состояла в том, чтобы я повторил эту функцию, чтобы создать четыре новых столбца с четырьмя отдельными строками изменения (по одной для каждой категории), и это привело бы к моей сводной таблице. Я также попробовал некоторые варианты aggregate(), хотя компонент функции был для меня менее понятен для того, что я собираюсь сделать. Кажется, что это должно быть довольно простым делом (а group_by хорошо мне помог при расчете процентного ранга и связанных с ним меток), но я пока не смог найти решение. Любые советы очень ценятся!

3 ответа

Решение

Мы можем использовать dcast от data.tableкоторые также имеют fun.aggregate и очень быстро.

library(data.table)
dcast(setDT(alldata), site~Label, length)

Или используя dplyr/tidyr

library(dplyr)
library(tidyr)
alldata %>%
    group_by(site, Label) %>%
    tally() %>%
    spread(Label, n)

base R вариант будет

 reshape(aggregate(date~site + Label, alldata, length), 
           idvar = "site", timevar="Label", direction="wide")

Есть три способа сделать это в dplyr, Первый является наиболее многословным, а два других используют удобные функции для сокращения кода:

library(reshape2)
library(dplyr)

alldata %>% group_by(site, Label) %>% summarise(n=n()) %>% dcast(site ~ Label)

alldata %>% group_by(site, Label) %>% tally %>% dcast(site ~ Label)

alldata %>% count(site, Label) %>% dcast(site ~ Label)

Чтобы просто создать сводную таблицу, вы можете использовать table:

with(df, table(site, Label, useNA="ifany"))[, c(2,4,1,3)]

     Label
site  Low Normal High N/A
  01A   0      2    0   0
  01B   2      0    0   0
  01C   0      0    2   0
  02A   0      0    0   1
  02B   1      0    0   0
  02C   0      1    0   0

данные

df <- read.table(header=T, text="site    date    percent_rank    Label
01A  2013-01-01    0.32         Normal
01B  2013-01-01    0.12         Low
01C  2013-01-01    0.76         High
02A  2013-01-01     0           N/A
02B  2013-01-01    0.16         Low
02C  2013-01-01    0.5          Normal
01A  2013-01-02    0.67         Normal
01B  2013-01-02    0.01         Low
01C  2013-01-02    0.92         High")
Другие вопросы по тегам