在解释详情之前,这是我的数据:
set.seed (1234)
datas <- data.frame (Indv = 1:20, Xvar = rnorm (20, 50, 10),
Yvar = rnorm (20, 30,5), Yvar1 = rnorm (20, 10, 2),
Yvar2 = rnorm (20, 5, 1), Yvar3 = rnorm (20, 100, 20),
Yvar4 = rnorm (20, 15, 3))
我想准备一个图形(Metroglymph),它基本上是点图,但是(Xvar和Yvar)点(尖峰(线))从缩放到其余变量(Yvar1,Yvar2,Yvar3,Yvar4)的点开始。 每个尖峰都是有序的,最好是彩色编码。
require(ggplot2)
ggplot(datas, aes(x=Xvar, y=Yvar)) +
geom_point(shape=1, size = 10) + theme_bw()
答案 0 :(得分:8)
以下是一种可能对您有所帮助的方法。它使用ggplot2中的stat_spoke()
。每个y变量都会在4个单独的stat_spoke
调用中映射到辐条半径。
plot_1 = ggplot(datas, aes(x=Xvar, y=Yvar)) +
stat_spoke(aes(angle=(1/8)*pi, radius=Yvar1), colour="#E41A1C",size=1) +
stat_spoke(aes(angle=(3/8)*pi, radius=Yvar2), colour="#377EB8",size=1) +
stat_spoke(aes(angle=(5/8)*pi, radius=Yvar3), colour="#4DAF4A",size=1) +
stat_spoke(aes(angle=(7/8)*pi, radius=Yvar4), colour="#984EA3",size=1) +
geom_point(shape=1, size = 10)
ggsave("plot_1.png", plot_1)
根据您的数据和具体需求,转换变量以使它们更适合绘图可能是有意义的。
normalize = function(x) {
new_x = (x - mean(x)) / sd(x)
new_x = new_x + abs(min(new_x))
return(new_x)
}
plot_2 = ggplot(datas, aes(x=Xvar, y=Yvar)) +
stat_spoke(aes(angle=(1/8)*pi, radius=normalize(Yvar1)), colour="#E41A1C", size=1) +
stat_spoke(aes(angle=(3/8)*pi, radius=normalize(Yvar2)), colour="#377EB8", size=1) +
stat_spoke(aes(angle=(5/8)*pi, radius=normalize(Yvar3)), colour="#4DAF4A", size=1) +
stat_spoke(aes(angle=(7/8)*pi, radius=normalize(Yvar4)), colour="#984EA3", size=1) +
geom_point(shape=1, size = 10)
ggsave("plot_2.png", plot_2)
重要警告:对于相同的轮辐半径值,如果线条更垂直,绘制线条的幅度将更大,如果线条更加水平,则线条幅度更小。这是因为x的范围大约是数据集y的两倍范围。随着x-y轴比的变化,绘制的角度也会变形。添加coord_equal(ratio=1)
解决了这个问题,但可能会引入其他问题。
这很有趣,也很有教育意义。输入重复代码可能会更加节省时间!如果有人可以提供改进此代码的建议,请发表评论。
library(reshape2)
dat2 = melt(datas, id.vars=c("Indv", "Xvar", "Yvar"),
variable.name="spoke_var", value.name="spoke_value")
# Apply normalization in a loop. Can plyr do this more gracefully?.
for (var_name in levels(dat2$spoke_var)) {
select_rows = dat2$spoke_var == var_name
norm_dat = normalize(dat2[select_rows, "spoke_value"])
dat2[select_rows, "spoke_value"] = norm_dat
}
# Pick an angle for each Yvar, then add angle column to dat2.
tmp = data.frame(spoke_var=unique(dat2$spoke_var))
tmp$spoke_angle = seq(from=pi/8, by=pi/4, length.out=nrow(tmp))
dat2 = merge(dat2, tmp)
plot_4 = ggplot(dat2, aes(x=Xvar, y=Yvar)) +
stat_spoke(data=dat2, size=1,
aes(colour=spoke_var, angle=spoke_angle, radius=spoke_value)) +
geom_point(data=datas, aes(x=Xvar, y=Yvar), shape=1, size=7) +
coord_equal(ratio=1) +
scale_colour_brewer(palette="Set1")
答案 1 :(得分:2)
这是更多手动方法:
set.seed (1234)
datas <- data.frame (Indv = 1:20, Xvar = rnorm (20, 50, 10),
Yvar = rnorm (20, 30,5), Yvar1 = rnorm (20, 10, 2),
Yvar2 = rnorm (20, 5, 1), Yvar3 = rnorm (20, 100, 20),
Yvar4 = rnorm (20, 15, 3))
datas$SYvar1 <- 2 + scale (datas$Yvar1)
datas$SYvar2 <- 2 + scale (datas$Yvar2)
datas$SYvar3 <- 2 + scale (datas$Yvar3)
datas$SYvar4 <- 2 + scale (datas$Yvar4)
require(ggplot2)
p <- ggplot(datas, aes(x=Xvar, y=Yvar)) +
geom_point(size = 10, pch = 19, col = "yellow2")
p + geom_segment(aes(x = Xvar, y = Yvar, xend = Xvar + SYvar1,
yend = Yvar), col = "red4", size = 1) +
geom_segment(aes(x = Xvar, y = Yvar, xend = Xvar,
yend = Yvar + SYvar2), col = "green4", size = 1) +
geom_segment(aes(x = Xvar, y = Yvar, xend = Xvar-2.5,
yend = Yvar + SYvar3), col = "darkblue", size = 1) +
geom_segment(aes(x = Xvar, y = Yvar, xend =
Xvar - SYvar4, yend = Yvar ), col = "red", size = 1) +
theme_bw()