ggplot2 — изменить geom_density2d, чтобы принимать веса в качестве параметра?

Это мой первый пост в R-сообществе, так что извините, если глупо. Я хотел бы использовать функции geom_density2d и stat_density2d в ggplot2 для построения оценок плотности ядра, но проблема в том, что они не могут обрабатывать взвешенные данные. Насколько я понимаю, эти две функции вызывают функцию kde2d из пакета MASS для оценки плотности ядра. И kde2d не принимает веса данных в качестве параметра.

Теперь я нашел эту измененную версию kde2d http://www.inside-r.org/node/226757, который принимает веса в качестве параметра и основан на исходном коде kde2d. Код этой функции:

  kde2d.weighted <- function (x, y, w, h, n = 25, lims = c(range(x), range(y))) {
  nx <- length(x)
  if (length(y) != nx) 
    stop("data vectors must be the same length")
  if (length(w) != nx & length(w) != 1)
    stop("weight vectors must be 1 or length of data")
  gx <- seq(lims[1], lims[2], length = n) # gridpoints x
  gy <- seq(lims[3], lims[4], length = n) # gridpoints y
  if (missing(h)) 
    h <- c(bandwidth.nrd(x), bandwidth.nrd(y));
  if (missing(w)) 
    w <- numeric(nx)+1;
  h <- h/4
  ax <- outer(gx, x, "-")/h[1] # distance of each point to each grid point in x-direction
  ay <- outer(gy, y, "-")/h[2] # distance of each point to each grid point in y-direction
  z <- (matrix(rep(w,n), nrow=n, ncol=nx, byrow=TRUE)*matrix(dnorm(ax), n, nx)) %*% t(matrix(dnorm(ay), n, nx))/(sum(w) * h[1] * h[2]) # z is the density
  return(list(x = gx, y = gy, z = z))
}

Я хотел бы, чтобы функции geom_density2d и stat_density2d вызывали kd2d.weighted вместо kde2d и тем самым заставляли их принимать взвешенные данные.

Я никогда не менял какие-либо функции в существующих пакетах R, поэтому мой вопрос: как это сделать проще всего?


person AntonvSchantz    schedule 13.06.2014    source источник


Ответы (1)


На самом деле вы можете передать свои собственные данные плотности в geom_contour, что, вероятно, будет самым простым. Давайте начнем с примера набора данных, добавив веса к данным гейзера.

library("MASS")
data(geyser, "MASS")
geyserw <- transform(geyser,
   weight = sample(1:5, nrow(geyser), replace=T)
)

Теперь мы используем вашу взвешенную функцию для расчета плотности и превращаем ее в data.frame.

dens <- kde2d.weighted(geyserw$duration, geyserw$waiting, geyserw$weight)
dfdens <- data.frame(expand.grid(x=dens$x, y=dens$y), z=as.vector(dens$z))

Теперь наносим данные

ggplot(geyserw, aes(x = duration, y = waiting)) +
    geom_point() + xlim(0.5, 6) + ylim(40, 110)
    geom_contour(aes(x=x, y=y, z=z), data= dfdens)

И это должно сделать это

результирующая взвешенная плотность

person MrFlick    schedule 13.06.2014
comment
Спасибо! Как раз то, что я искал. Однако можно ли сделать заполненный контурный график, используя этот geom_contour? - person AntonvSchantz; 14.06.2014
comment
Переименуйте вес в вес в geyserw data.frame и все работает отлично. - person Victor Barreto; 04.05.2021