ggplot2圆形数据密度图

5
我有一个数据集,其中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 -- 即12月31日后的第一天是1月1日。 我知道包提供了此功能,但我尝试使用调用时没有成功。 我特别想使用,因为我想能够使用分面、调用等。 另外,为了澄清,我希望得到类似的东西 -- 我不是在寻找像Circular density plot using ggplot2所示的极坐标图。

这是一个非常棒的例子,可能会很有用,试图将其显示为圆形热力图而不是密度。链接 - JasonAizkalns
1个回答

7
为了消除边缘效应,您可以将数据复制三次,创建密度估计,然后仅显示中间数据的密度。这将确保从一侧到另一侧密度函数的“环绕”连续性。
下面是一个示例,比较原始图与新版本。我使用了“调整”参数来设置两个图之间的相同带宽。还请注意,在圆形化版本中,如果您希望密度总和为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: https://dev59.com/5YHba4cB1Zd3GeqPXux9#24986121
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")

enter image description here


解决了我的问题 - 几乎是违反直觉的简单。 - mbarete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接