Стек указывает один над другим

Чтобы предотвратить чрезмерное построение графика, я хотел бы использовать альтернативу джиттеру, который просто накладывает точки один поверх другого вокруг среднего (смещает их по вертикали с помощью приращений заданной величины, а не добавляет случайное значение в качестве джиттера).

Из этого:

example <- data.frame(x=c(1,1,1,2,2,2,2), y=c(1,1,1,2,2,2,2))

qplot(data=example,x=x, y=y)

Что бы я хотел, это примерно так:

example image

Вероятно, это возможно с помощью stat_bindot().

Любые предложения?

Ответ 1

Ни один из встроенных позиций не делает этого, а geom_dotplot не совсем прав, потому что он работает только в одном измерении. Я собрал новую позицию, которая делает правильные вещи, но требует ручной настройки, чтобы все было правильно.

library("proto")
PositionNudge <- proto(ggplot2:::Position, {
  objname <- "nudge"
  adjust <- function(., data) {
    trans_x <- function(x) {
      lx <- length(x)
      if (lx > 1) {
        x + .$width*(seq_len(lx) - ((lx+1)/2))
      } else {
        x
      }
    }
    trans_y <- function(y) {
      ly <- length(y)
      if (ly > 1) {
        y + .$height*(seq_len(ly) - ((ly+1)/2))
      } else {
        y
      }
    }
    ddply(data, .(group), transform_position, trans_x=trans_x, trans_y=trans_y)
  }
})
position_nudge <- function(width = 0, height = 0) {
  PositionNudge$new(width = width, height = height)
}

Я назвал это подталкиванием, потому что другие вещи, которые я, хотя уже, были сделаны (стек, увернуться)

Чтобы использовать его

ggplot(example, aes(x, y)) +
  geom_point(aes(group=interaction(x,y)), size=5, 
             position=position_nudge(height=0.03))

enter image description here

Вы также можете подталкивать в горизонтальном направлении

ggplot(example, aes(x, y)) +
  geom_point(aes(group=interaction(x,y)), size=5, 
             position=position_nudge(width=0.03))

enter image description here

Вы должны указать взаимодействие группы как эстетическое с geom_point, а точная ширина/высота, которые необходимо передать в position_nudge, зависят от размера точек и размера вывода. Например, с выходом 4x6 вам нужно

ggplot(example, aes(x, y)) +
  geom_point(aes(group=interaction(x,y)), size=10, 
                 position=position_nudge(height=0.13))

enter image description here

Значение 0,13 было просто пробным и ошибочным, пока оно не выглядело правильно. Некоторые из кода и вещей, извлеченных из geom_dotplot, вероятно, могут быть повторно использованы здесь, чтобы сделать это более надежным. Кроме того, я не тестировал это с любыми данными, отличными от приведенных example, поэтому он может прервать его несколькими интересными способами. Но это, если не что иное, начало.

Ответ 2

Вдалеке от превосходства @Brian Diggs 'хороший ответ, но быстрая альтернатива, когда я использую данные dodge в объекте, созданном geom_dotplot, для генерации новых значений y. Некоторое ручное tweeking необходимо, чтобы получить масштабирование "dodge".

# create ggplot object with geom_dotplot
g1 <- ggplot(example, aes(x = x, y = y)) +
  geom_dotplot(stackdir = "center")

# grab dodge values from plot object
dodge <- ggplot_build(g1)[["data"]][[1]]$stackpos

# create new y values that are adjusted by 'dodge'
example$y2 <- example$y + dodge * 0.05

# plot using new y values
ggplot(example, aes(x = x, y = y2)) +
  geom_point(size = 5)

enter image description here

# seems to work decently on grouped data as well
df2 <- rbind(example, example)
df2$grp <- rep(c("a", "b"), each = 7)
df2

g2 <- ggplot(df2, aes(x = x, y = y, colour = grp)) +
  geom_dotplot(stackdir = "center", stackgroups = FALSE)

dodge <- ggplot_build(g2)[["data"]][[1]]$stackpos

df2$y2 <- df2$y + dodge * 0.04

ggplot(df2, aes(x = x, y = y2, colour = grp)) +
  geom_point(size = 5, position = position_dodge(width = 0.05))

enter image description here