如何使用geom_boxplot(stat ="identity")模拟带有异常值的geom_boxplot()

Jas*_*lns 7 r ggplot2 plyr dplyr

我想预先计算数据的变量摘要(使用plyr和传递quantile函数),然后用geom_boxplot(stat = "identity").除了它(a)不将异常值绘制为点并且(b)将"胡须"扩展到绘制的数据的最大值和最小值之外,这很有效.

例:

library(plyr)
library(ggplot2)

set.seed(4)
df <- data.frame(fact = sample(letters[1:2], 12, replace = TRUE),
                 val  = c(1:10, 100, 101))
df
#    fact val
# 1     b   1
# 2     a   2
# 3     a   3
# 4     a   4
# 5     b   5
# 6     a   6
# 7     b   7
# 8     b   8
# 9     b   9
# 10    a  10
# 11    b 100
# 12    a 101

by.fact.df <- ddply(df, c("fact"), function(x) quantile(x$val))

by.fact.df
#   fact 0%  25% 50%  75% 100%
# 1    a  2 3.25 5.0 9.00  101
# 2    b  1 5.50 7.5 8.75  100

# What I can do...with faults (a) and (b) above
ggplot(by.fact.df, 
       aes(x = fact, ymin = `0%`, lower = `25%`, middle = `50%`, 
           upper = `75%`,  ymax = `100%`)) +
  geom_boxplot(stat = "identity")

# What I want...
ggplot(df, aes(x = fact, y = val)) +
  geom_boxplot()
Run Code Online (Sandbox Code Playgroud)

我能做什么......有上面提到的错误(a)和(b):

情节01

我想要获得什么,但仍然通过plyr(或其他方法)利用预计算:

情节02

初步想法:也许有一些方法可以在没有异常值的情况下预先计算晶须的真实终点?然后,将异常值的数据子集化并将其传递为geom_point()

动机:在处理大型数据集时,我发现它更快,更实用的杠杆作用plyr,dplyr和/或data.table预先计算的统计数据,然后绘制出来,而不是ggplot2在计算.

UPDATE

我可以通过以下混合dplyrplyr代码提取我需要的内容,但我不确定这是否是最有效的方法:

df %>%
  group_by(fact) %>%
  do(ldply(boxplot.stats(.$val), data.frame))

Source: local data frame [6 x 3]
Groups: fact

  fact   .id X..i..
1    a stats      2
2    a stats      4
3    a stats     10
4    a stats     13
5    a stats     16
6    a     n      9
Run Code Online (Sandbox Code Playgroud)

inf*_*ner 6

这是我的答案,使用内置函数quantileboxplot.stats.

geom_boxplot箱形图的计算方法略有不同boxplot.stats.阅读?geom_boxplot?boxplot.stats理解我的实现如下

#Function to calculate boxplot stats to match ggplot's implemention as in geom_boxplot.
my_boxplot.stats <-function(x){
        quantiles <-quantile(x, c(0, 0.25, 0.5, 0.75, 1))
        labels <-names(quantile(x))
        #replacing the upper whisker to geom_boxplot
        quantiles[5] <-boxplot.stats(x)$stats[5]
        res <-data.frame(rbind(quantiles))
        names(res) <-labels
        res$out <-boxplot.stats(x)$out
        return(res)
    }
Run Code Online (Sandbox Code Playgroud)

代码来计算统计数据并绘制它

library(dplyr)
df %>% group_by(fact) %>% do(my_boxplot.stats(.$val)) %>% 
      ggplot(aes(x=fact, y=out, ymin = `0%`, lower = `25%`, middle = `50%`,
                 upper = `75%`,  ymax = `100%`)) +
      geom_boxplot(stat = "identity") + geom_point()
Run Code Online (Sandbox Code Playgroud)

  • 这是一个比我更好的答案。但是现在,这仅适用于每组只有一个异常值的情况。如果您有多个异常值,您可以在添加异常值之前将结果放入列表 `res &lt;- as.list(quantiles)`。然后你转换成一个`data.frame`。如果您有很多异常值,实际上可能会更好地计算带有主要统计数据的“data.frame”和带有异常值的单独“data.frame”。 (2认同)