2

我在ggplot2中制作这个点图:

ggplot(mtcars, aes(x = mpg)) + geom_dotplot()

我想在点图顶部显示某种平滑密度拟合到观察到的点。这看起来不对:

ggplot(mtcars, aes(x = mpg)) + geom_dotplot() + geom_density()

我试过stat_smooth()了,但我得到了错误:

> ggplot(mtcars, aes(x = mpg)) + geom_dotplot() + stat_smooth()
stat_bindot: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this.
Error: stat_smooth requires the following missing aesthetics: y

谢谢。

4

2 回答 2

0

函数中的平滑公式stat_smooth需要一个y值,并且由于您没有指定一个值,因此您会看到一个错误。

如果您指定一个值范围,错误将消失,y例如:

ggplot(mtcars, aes(x = hp, y = mpg)) + geom_dotplot() + stat_smooth()

编辑

stat_smooth()与大多数其他功能完美配合。您可能想要的近似值(在 x 上使用 mpg,在 y 上使用模型)将是:

qplot(mpg, row.names(mtcars), data=mtcars, group=1, color=mpg, xlab="Miles Per Gallon", ylab="Model")  + stat_smooth()

这将导致:

在此处输入图像描述

于 2013-04-25T22:07:40.090 回答
0

我自己也遇到了这个问题(尽管我也想按组给我的点上色)。问题是 geom_dotplot 忽略了 y 缩放,只是根据 x 轴和点的宽度来堆叠点。这意味着您自己设置 y 轴,然后调整绘图的纵横比,使点神奇地排列到正确的高度。

这是我写的一个实用函数:

# Function to generate a normal curve
make.normal.density = function( a, mn=median(a), stdev=sd(a), numpts=500 ) {
  x.grid = seq(min(a), max(a), length= numpts)
  dens.all = dnorm(x.grid,mean=mn, sd = stdev)
  data.frame( x = x.grid, y = dens.all )
}


make.densodot.plot = function( X, group = NULL, binwidth, bw = binwidth, normal.density = FALSE ) {
  df = data.frame( X = X )
  if ( !is.null( group ) ) {
    df$group=group
  }

  # Hand-bin our dots
  scl = 1 / binwidth
  mn = round( scl * (min( X ) - binwidth/2 ) ) / scl
  breaks = seq( mn - binwidth/2, max( df$X + binwidth), by=binwidth )
  df = mutate( df, bin = cut( X, breaks=breaks ) )

  mx = max( table(df$bin ) )

  # Get density curve to plot
  if ( normal.density ) {
    dd = make.normal.density( df$X )
  } else {
    dens = density( df$X, bw=bw )
    dd = data.frame( x=dens$x, y=dens$y )
  }
  dmax = max( dd$y )

  # What fraction of density is in tallest histogram bar?
  frac = mx / nrow( df )

  # How high should density line be through the peak (to get relatively same area
  # under density curve (integrate curve over binwidth) vs. histogram bin (# dots in
  # the bin over total number of dots)
  ratio = (binwidth * dmax) / frac

  # Each unit of height is what in terms of dots? (The dots will stack up
  # without regard of y-axis, so we want to fix aspect ratio so the dots
  # correspond to the density line.)
  scaling = binwidth / ( (dmax / ratio) / (mx) )

  y.max = max( dmax, mx * binwidth/scaling )

  if ( is.null( group ) ) {
    plt = ggplot( df )+
      geom_dotplot( aes(x=X), method="histodot",
                    binwidth = binwidth, stackgroups = TRUE)
  } else {
    plt = ggplot( df )+
      geom_dotplot( aes(x=X, fill=group, col=group), method="histodot",
                    binwidth = binwidth, stackgroups = TRUE)
  }
  plt = plt +
    geom_line( data=dd, aes( x = x, y = y ) ) +
    coord_fixed(ratio = scaling, ylim=c(0, y.max ) ) +
    scale_y_continuous(name="", breaks=seq(0,by=binwidth/scaling, length.out=(mx+1)), labels=c(0:mx) )

  plt
}


make.densodot.plot( X = mtcars$mpg, binwidth=3 )
于 2019-06-17T19:55:03.460 回答