是否可以在R上创建此图?

时间:2019-06-12 19:09:33

标签: histogram kernel-density density-plot

我对R真的很陌生,我正在寻找创建与所附图相似的图。我尝试使用ggplot和基础程序创建密度图。

我使用了代码ggplot(data, aes(x = Freq)) + geom_density(),但是输出不正确。我在每个数字点而不是整体曲线上都出现尖峰。每行是一个介于1到7之间的数据点,一个特征的频率分布如下:

1:500,2:550 3:700 4:1000 5:900 6:835:7:550

因此,我有5035行,因为一行等于一个分数。

非常感谢您的帮助。

这是我希望剧情的样子。 (请注意,我将在以后添加其他特征,我现在只想添加一行)。

enter image description here

1 个答案:

答案 0 :(得分:0)

这里发生了一些事情,首先是生成数据的摘要统计信息。您只需要以适当的方式调用meansd即可从数据中获取均值和标准差。您尚未显示数据,因此在这里很难提出很多建议。

就绘制这些摘要统计信息而言,您可以轻松地从原始论文中复制该图,但是这很糟糕,我建议您不要这样做。更强的线条意味着更重要,需要对所有内容进行双重标记,对y轴贴错标签,所有这些都需要绘制漂亮的平滑参数曲线,从而给人以错误的信心印象。我只扫描了纸张,但是对于某种类型的多层次模型,这种数据正在大声呼喊

我更喜欢“基础”图形,ggplot非常适合用于探索性图形,但是如果您对图形的外观有严格的限制,那么图形会很容易受到干扰。我们从摘要统计信息开始:​​

df <- read.csv(text="
title,              mu, sigma,label, label_x,label_pos
Extraversion,       4.0, 1.08,Extra,    3.85,3
Agreeableness,      5.0, 0.77,Agree,    5.0, 3
Conscientiousness,  4.7, 0.97,Cons,     3.4, 2
Emotional stability,5.3, 0.84,Emot stab,5.9, 4
Intellect,          3.7, 0.86,Intellect,3.7, 3
")

我只是在这里从纸上拉出数字,你必须计算它们。 mu列是变量的平均值,sigma是标准偏差。 label_xlabel_pos用于绘制标签,因此需要手动选择(或者此后可以在类似Inkscape的注释中注释)。 label_x是x轴位置,label_pos代表它相对于xy点的位置(有关pos参数的信息,请参见text

接下来,我们计算一些事情:

lwds <- 1 + seq(3, 1, len=5) ^ 2
label_y <- dnorm(df$label_x, df$mu, df$sigma)

即线宽和标签y位置,我们就可以开始绘制图形了:

# start by setting up plot nicely and setting plot limits
par(bty='l', mar=c(3, 3, 0.5, 0.5), mgp=c(1.8, 0.4, 0), tck=-0.02)
plot.new(); plot.window(c(1, 7), c(0, 0.56), yaxs='i')

# loop over data drawing curves
for (i in 1:nrow(df)) {
    curve(dnorm(x, df$mu[[i]], df$sigma[[i]]), add=T, n=151, lwd=lwds[[i]])
}

# draw labels
text(df$label_x, label_y, df$label, pos=df$label_pos)

# draw axes
axis(1, lwd=0, lwd.ticks=1)
axis(2, lwd=0, lwd.ticks=1)
box(lwd=1)

# finally, title and legend
title(xlab='Level of state', ylab='Probability density')
legend('topleft', legend=df$title, lwd=lwds, bty='n', cex=0.85)

这给了我们类似的东西

replicate original plot

我也采用了更多的现代大写字母,并且将y轴从零开始,因为这些都是概率,所以不能为负

我的偏好是更接近于此:

my version

细线覆盖均值周围的2个标准差(即95%间隔),粗线覆盖1个标准差(68%),点即为均值。区分每个量度并在它们之间进行比较要容易得多,并且不会人为地使“外向性”变得更加突出。的代码与此类似:

par(bty='l', mar=c(3, 8, 0.5, 0.5), mgp=c(1.8, 0.4, 0), tck=-0.02)
plot.new(); plot.window(c(1, 7), c(5.3, 0.7))

# draw quantiles
for (i in 1:nrow(df)) {
    lines(df$mu[[i]] + df$sigma[[i]] * c(-1, 1), rep(i,2), lwd=3)
    lines(df$mu[[i]] + df$sigma[[i]] * c(-2, 2), rep(i,2), lwd=1)
}
# and means
points(df$mu, 1:5, pch=20)

axis(1, lwd=0, lwd.ticks=1)
axis(2, at=1:5, labels=df$title, lwd=0, lwd.ticks=1, las=1)
box()

title(xlab='Level of state')
相关问题