我想将矩阵的每一列绘制成一个箱线图,然后将每个箱图中的异常值标记为它们在矩阵中所属的行名称。举个例子:
vv=matrix(c(1,2,3,4,8,15,30),nrow=7,ncol=4,byrow=F)
rownames(vv)=c("one","two","three","four","five","six","seven")
boxplot(vv)
我想将每个图中的异常值(在本例中为30)标记为它所属的行名,因此在这种情况下30属于第7行。有一种简单的方法可以做到这一点吗?我已经看到类似的问题,但似乎没有一个按照我想要的方式工作。
答案 0 :(得分:8)
有一种简单的方法。请注意,以下行中的Boxplot中的b是大写字母。
library(car)
Boxplot(y ~ x, id.method="y")
答案 1 :(得分:5)
或者,您可以使用{car}包中的“Boxplot”功能为您标记异常值。
答案 2 :(得分:4)
在给出的示例中,它有点无聊,因为它们都是同一行。但这是代码:
bxpdat <- boxplot(vv)
text(bxpdat$group, # the x locations
bxpdat$out, # the y values
rownames(vv)[which(vv == bxpdat$out, arr.ind=TRUE)[, 1]], # the labels
pos = 4)
这将选择具有等于boxplot
结果中的“out”列表(即异常值)的值的rownames。 Boxplot调用并返回boxplot.stats
的值。看看:
str(bxpdat)
答案 3 :(得分:4)
@Ddin的解决方案适用于单个boxplot,但对于具有重复值的任何内容都会失败,例如我创建的数据集:
#Create data
set.seed(1)
basenums <- c(1,2,3,4,8,15,30)
vv=matrix(c(basenums, sample(basenums), 1-basenums,
c(0, 29, 30, 31, 32, 33, 60)),nrow=7,ncol=4,byrow=F)
dimnames(vv)=list(c("one","two","three","four","five","six","seven"), 1:4)
在这个数据集上,@ DWin的解决方案给出了:
这是错误的,因为在第4个例子中,最小值和最大值不可能在同一行。
这个解决方案是可怕的(我希望可以简化),但有效。
#Reshape data
vv_dat <- as.data.frame(vv)
vv_dat$row <- row.names(vv_dat)
library(reshape2)
new_vv <- melt(vv_dat, id.vars="row")
#Get boxplot data
bxpdat <- as.data.frame(boxplot(value~variable, data=new_vv)[c("out", "group")])
#Get matches with boxplot data
text_guide <- do.call(rbind, apply(bxpdat, 1,
function(x) new_vv[new_vv$value==x[1]&new_vv$variable==x[2], ]))
#Add labels
with(text_guide, text(x=as.numeric(variable)+0.2, y=value, labels=row))
答案 4 :(得分:0)
或者您只需运行this blog post中的代码:
source("https://raw.githubusercontent.com/talgalili/R-code-snippets/master/boxplot.with.outlier.label.r") # Load the function
set.seed(6484)
y <- rnorm(20)
x1 <- sample(letters[1:2], 20,T)
lab_y <- sample(letters, 20)
# plot a boxplot with interactions:
boxplot.with.outlier.label(y~x1, lab_y)
(处理多个彼此接近的异常值)
答案 5 :(得分:0)
@塞巴斯蒂安-C 这是对DWin解决方案的略微修改,似乎更具普遍性
bx1<-boxplot(pb,las=2,cex.axis=.8)
if(length(bx1$out)!=0){
## get the row of each outlier
out.rows<-sapply(1:length(bx1$out),function(i) which(vv[,bx1$group[i]]==bx1$out[i]))
text(bx1$group,bx1$out,
rownames(vv)[out.rows],
pos=4
)
}