在一张图中绘制多个箱线图
Posted
技术标签:
【中文标题】在一张图中绘制多个箱线图【英文标题】:Plot multiple boxplot in one graph 【发布时间】:2013-01-14 07:04:07 【问题描述】:我将数据保存为一个包含 12 列的 .csv
文件。第 2 到 11 列(标记为 F1, F2, ..., F11
)是 features
。 Column one
包含label
这些功能good
或bad
。
我想针对label
绘制所有这 11 个功能的boxplot
,但用good
或bad
分隔。到目前为止我的代码是:
qplot(Label, F1, data=testData, geom = "boxplot", fill=Label,
binwidth=0.5, main="Test") + xlab("Label") + ylab("Features")
但是,这仅显示F1
与label
。
我的问题是:如何在一张带有一些dodge position
的图中显示F2, F3, ..., F11
和label
?我已经对特征进行了标准化,因此它们在 [0 1] 范围内的比例相同。
测试数据可以在here找到。我手绘了一些东西来解释这个问题(见下文)。
【问题讨论】:
(+1) 您的帖子包含所有内容,但格式不完全。我想那是反对票。请学习使用 SO 格式化选项!它会对你有很大帮助。此外,您应该使用dput(testData)
并将输出粘贴到此处,而不是发布到 CSV 的链接,以便人们可以直接在他们的系统上复制/粘贴。
非常感谢,阿伦。我将尝试格式化我未来的帖子。我试图粘贴数据,但发现它包含这么多数字。但我应该创建一个较小的玩具问题。
【参考方案1】:
在绘图之前,您应该通过融合数据来获取特定格式的数据(请参阅下文了解融合数据的外观)。否则,您所做的似乎还可以。
require(reshape2)
df <- read.csv("TestData.csv", header=T)
# melting by "Label". `melt is from the reshape2 package.
# do ?melt to see what other things it can do (you will surely need it)
df.m <- melt(df, id.var = "Label")
> df.m # pasting some rows of the melted data.frame
# Label variable value
# 1 Good F1 0.64778924
# 2 Good F1 0.54608791
# 3 Good F1 0.46134200
# 4 Good F1 0.79421221
# 5 Good F1 0.56919951
# 6 Good F1 0.73568570
# 7 Good F1 0.65094207
# 8 Good F1 0.45749702
# 9 Good F1 0.80861929
# 10 Good F1 0.67310067
# 11 Good F1 0.68781739
# 12 Good F1 0.47009455
# 13 Good F1 0.95859182
# 14 Good F1 1.00000000
# 15 Good F1 0.46908343
# 16 Bad F1 0.57875528
# 17 Bad F1 0.28938046
# 18 Bad F1 0.68511766
require(ggplot2)
ggplot(data = df.m, aes(x=variable, y=value)) + geom_boxplot(aes(fill=Label))
编辑:我知道您可能需要分面。这也是它的一个实现:
p <- ggplot(data = df.m, aes(x=variable, y=value)) +
geom_boxplot(aes(fill=Label))
p + facet_wrap( ~ variable, scales="free")
编辑2:如何添加x-labels
、y-labels
、title
、更改legend heading
、添加jitter
?
p <- ggplot(data = df.m, aes(x=variable, y=value))
p <- p + geom_boxplot(aes(fill=Label))
p <- p + geom_jitter()
p <- p + facet_wrap( ~ variable, scales="free")
p <- p + xlab("x-axis") + ylab("y-axis") + ggtitle("Title")
p <- p + guides(fill=guide_legend(title="Legend_Title"))
p
编辑3:如何将geom_point()
点对齐到箱线图的中心?可以使用position_dodge
来完成。这应该可以。
require(ggplot2)
p <- ggplot(data = df.m, aes(x=variable, y=value))
p <- p + geom_boxplot(aes(fill = Label))
# if you want color for points replace group with colour=Label
p <- p + geom_point(aes(y=value, group=Label), position = position_dodge(width=0.75))
p <- p + facet_wrap( ~ variable, scales="free")
p <- p + xlab("x-axis") + ylab("y-axis") + ggtitle("Title")
p <- p + guides(fill=guide_legend(title="Legend_Title"))
p
【讨论】:
另一个问题:如何使用这种方法更改x标签和y标签?例如,不使用“值”和“变量”。非常感谢。 scale_x_discrete(name="xxx") + scale_y_continuous(name="yyy") 我想知道如何在箱线图上添加“添加原始数据点”。我想使用 geom_point() 或 geom_jitter();但是,正如我尝试的那样,这些点重叠在一起,不能分为两组,即这里的好或坏。 非常感谢您的帮助。最后一点,我想在箱线图上叠加原始数据点。我尝试了 geom_point() 或 geom_jitter()。例如,当我使用 geom_point() 时,来自“好”和“坏”数据集的数据点重叠在一起,并显示在上面显示的橙色和蓝色框的中间。但是,我希望原始点沿每个框的中线(晶须)单独叠加。很抱歉再次打扰您,但请帮我看看这个问题。再次非常感谢。 1.刚刚注意到这个 lne p 【参考方案2】:使用基础图形,我们可以使用at =
来控制盒子的位置,结合boxwex =
来控制盒子的宽度。第一个boxplot
语句创建一个空白图。然后在以下两个语句中添加 2 个跟踪。
请注意,在下文中,我们使用df[,-1]
从要绘制的值中排除第一(id)列。对于不同的数据框,可能需要将其更改为包含您要绘制的数据的列的子集。
boxplot(df[,-1], boxfill = NA, border = NA) #invisible boxes - only axes and plot area
boxplot(df[df$id=="Good", -1], xaxt = "n", add = TRUE, boxfill="red",
boxwex=0.25, at = 1:ncol(df[,-1]) - 0.15) #shift these left by -0.15
boxplot(df[df$id=="Bad", -1], xaxt = "n", add = TRUE, boxfill="blue",
boxwex=0.25, at = 1:ncol(df[,-1]) + 0.15) #shift to the right by +0.15
一些虚拟数据:
df <- data.frame(
id = c(rep("Good",200), rep("Bad", 200)),
F1 = c(rnorm(200,10,2), rnorm(200,8,1)),
F2 = c(rnorm(200,7,1), rnorm(200,6,1)),
F3 = c(rnorm(200,6,2), rnorm(200,9,3)),
F4 = c(rnorm(200,12,3), rnorm(200,8,2)))
【讨论】:
【参考方案3】:由于您没有提到绘图包,我建议在这里使用Lattice
版本(我认为 ggplot2 的答案比 lattice 的答案更多,至少因为我在这里是这样)。
## reshaping the data( similar to the other answer)
library(reshape2)
dat.m <- melt(TestData,id.vars='Label')
library(lattice)
bwplot(value~Label |variable, ## see the powerful conditional formula
data=dat.m,
between=list(y=1),
main="Bad or Good")
【讨论】:
另一个问题:如何使用这种方法改变x标签和y标签? @SamoJerom 您添加例如:ylab="value"
, xlab="treatment"
到 bwplot 语句
@agstudy 我想知道如何在箱线图上添加“添加原始数据点”。我想使用 geom_point() 或 geom_jitter();但是,正如我尝试的那样,这些点重叠在一起,不能分为两组,即这里的好或坏。【参考方案4】:
格子图的ggplot版本:
library(reshape2)
library(ggplot2)
df <- read.csv("TestData.csv", header=T)
df.m <- melt(df, id.var = "Label")
ggplot(data = df.m, aes(x=Label, y=value)) +
geom_boxplot() + facet_wrap(~variable,ncol = 4)
剧情:
【讨论】:
【参考方案5】:我知道这是一个较老的问题,但它也是我的一个问题,虽然接受的答案有效,但有一种方法可以做类似的事情 而无需 使用额外的软件包,如ggplot 或格子。箱线图重叠而不是并排显示并不是很好,但是:
boxplot(data1[,1:4])
boxplot(data2[,1:4],add=TRUE,border="red")
这会放入两组箱线图,第二组的轮廓(无填充)为红色,并且异常值也为红色。好消息是,它适用于两个不同的数据帧,而不是试图重塑它们。快速而肮脏的方式。
【讨论】:
【参考方案6】:在基础 R 中,可以使用带有交互的公式接口 (:
) 来实现此目的。
df <- read.csv("~/Desktop/TestData.csv")
df <- data.frame(stack(df[,-1]), Label=df$Label) # reshape to long format
boxplot(values ~ Label:ind, data=df, col=c("red", "limegreen"), las=2)
【讨论】:
有办法刻面箱线图吗?以上是关于在一张图中绘制多个箱线图的主要内容,如果未能解决你的问题,请参考以下文章