ggplot2 плотность круговых данных

У меня есть набор данных, где x представляет день года (скажем, дни рождения), и я хочу создать для этого график плотности. Кроме того, поскольку у меня есть некоторая групповая информация (скажем, мальчики или девочки), я хочу использовать возможности ggplot2 для построения графика плотности.

Поначалу достаточно просто:

require(ggplot2); require(dplyr)
bdays <- data.frame(gender = sample(c('M', 'F'), 100, replace = T), bday = sample(1:365, 100, replace = T))
bdays %>% ggplot(aes(x = bday)) + geom_density(aes(color = factor(gender)))

Однако это дает плохую оценку из-за краевых эффектов. Я хочу применить тот факт, что я могу использовать круговые координаты, чтобы 365 + 1 = 1 -- один день после 31 декабря был 1 января. Я знаю, что пакет circular предоставляет эту функциональность, но мне не удалось реализовать ее с помощью вызова stat_function(). Мне особенно полезно использовать ggplot2, потому что я хочу иметь возможность использовать фасеты, aes вызовы и т. д.

Кроме того, для пояснения, я хотел бы что-то похожее на geom_density -- я не ищу полярный график, подобный показанному на: Круговой график плотности с использованием ggplot2.


person mbarete    schedule 28.03.2016    source источник
comment
Это действительно аккуратный пример, который может быть полезен и пытается показать это как круговую тепловую карту, а не плотность.   -  person JasonAizkalns    schedule 28.03.2016


Ответы (1)


Чтобы удалить краевые эффекты, вы можете сложить три копии данных, создать оценку плотности, а затем показать плотность только для средней копии данных. Это будет гарантировать непрерывность функции плотности «обертывания» от одного края до другого.

Ниже приведен пример сравнения исходного графика с новой версией. Я использовал параметр adjust, чтобы установить одинаковую пропускную способность между двумя графиками. Также обратите внимание, что в циркулярной версии вам нужно будет перенормировать плотности, если вы хотите, чтобы они добавлялись к 1:

set.seed(105)
bdays <- data.frame(gender = sample(c('M', 'F'), 100, replace = T), bday = sample(1:365, 100, replace = T))

# Stack three copies of the data, with adjusted values of bday
bdays = bind_rows(bdays, bdays, bdays)
bdays$bday = bdays$bday + rep(c(0,365,365*2),each=100)

# Function to adjust bandwidth of density plot
# Source: http://stackoverflow.com/a/24986121/496488
bw = function(b,x) b/bw.nrd0(x)

# New "circularized" version of plot
bdays %>% ggplot(aes(x = bday)) + 
  geom_density(aes(color = factor(gender)), adjust=bw(10, bdays$bday[1:100])) +
  coord_cartesian(xlim=c(365, 365+365+1), expand=0) +
  scale_x_continuous(breaks=seq(366+89, 366+365, 90), labels=seq(366+89, 366+365, 90)-365) +
  scale_y_continuous(limits=c(0,0.0016))
  ggtitle("Circularized")

# Original plot
ggplot(bdays[1:100,], aes(x = bday)) + 
  geom_density(aes(color = factor(gender)), adjust=bw(30, bdays$bday[1:100])) +
  scale_x_continuous(breaks=seq(90,360,90), expand=c(0,0)) +
  ggtitle("Not Circularized")

введите здесь описание изображения

person eipi10    schedule 28.03.2016
comment
Решает мою проблему - почти интуитивно просто. - person mbarete; 28.03.2016