Как говорит Юлиус, проблема в том, что hexGrob
не получает информацию о размерах бункера, а догадывается по различиям, которые находит внутри фасета.
Очевидно, имеет смысл передать dx
и dy
hexGrob
- отсутствие ширины и высоты шестиугольника похоже на указание круга по центру без указания радиуса.
Обходной путь:
Стратегия resolution
работает, если фасет содержит два соседних шестиугольника, которые различаются как по x, так и по y. Итак, в качестве обходного пути я создам вручную data.frame, содержащий координаты x и y центров ячеек, а также фактор для фасетирования и подсчетов:
Помимо указанных в вопросе библиотек мне понадобится
library (reshape2)
а также bindata$factor
действительно должен быть фактором:
bindata$factor <- as.factor (bindata$factor)
Теперь рассчитаем основную сетку шестиугольника.
h <- hexbin (bindata, xbins = 5, IDs = TRUE,
xbnds = range (bindata$x),
ybnds = range (bindata$y))
Далее нам нужно посчитать количество в зависимости от bindata$factor
counts <- hexTapply (h, bindata$factor, table)
counts <- t (simplify2array (counts))
counts <- melt (counts)
colnames (counts) <- c ("ID", "factor", "counts")
Поскольку у нас есть идентификаторы ячеек, мы можем объединить этот data.frame с соответствующими координатами:
hexdf <- data.frame (hcell2xy (h), ID = h@cell)
hexdf <- merge (counts, hexdf)
Вот как выглядит data.frame:
> head (hexdf)
ID factor counts x y
1 3 e 0 -0.3681728 -1.914359
2 3 s 0 -0.3681728 -1.914359
3 3 y 0 -0.3681728 -1.914359
4 3 r 0 -0.3681728 -1.914359
5 3 p 0 -0.3681728 -1.914359
6 3 o 0 -0.3681728 -1.914359
ggplot
ting (используйте команду ниже), это дает правильные размеры бункера, но фигура имеет немного странный вид: рисуются шестиугольники с нулевым счетом, но только там, где этот бин заполнен каким-либо другим фасетом. Чтобы подавить прорисовку, мы можем установить там счетчики на NA
и сделать na.value
полностью прозрачным (по умолчанию серый50):
hexdf$counts [hexdf$counts == 0] <- NA
ggplot(hexdf, aes(x=x, y=y, fill = counts)) +
geom_hex(stat="identity") +
facet_wrap(~factor) +
coord_equal () +
scale_fill_continuous (low = "grey80", high = "#000040", na.value = "#00000000")
дает цифру вверху сообщения.
Эта стратегия работает до тех пор, пока значения ширины бинов верны без фасетирования. Если ширина бинов установлена очень малой, resolution
может по-прежнему давать слишком большие dx
и dy
. В этом случае мы можем предоставить hexGrob
две соседние ячейки (но различающиеся как по x, так и по y) с NA
счетчиками для каждого аспекта.
dummy <- hgridcent (xbins = 5,
xbnds = range (bindata$x),
ybnds = range (bindata$y),
shape = 1)
dummy <- data.frame (ID = 0,
factor = rep (levels (bindata$factor), each = 2),
counts = NA,
x = rep (dummy$x [1] + c (0, dummy$dx/2),
nlevels (bindata$factor)),
y = rep (dummy$y [1] + c (0, dummy$dy ),
nlevels (bindata$factor)))
Дополнительным преимуществом этого подхода является то, что мы можем удалить все строки с нулевым счетчиком уже в counts
, в этом случае уменьшив размер hexdf
примерно на 3/4 (122 строки вместо 520):
counts <- counts [counts$counts > 0 ,]
hexdf <- data.frame (hcell2xy (h), ID = h@cell)
hexdf <- merge (counts, hexdf)
hexdf <- rbind (hexdf, dummy)
Сюжет выглядит точно так же, как указано выше, но вы можете визуализировать разницу, поскольку na.value
не полностью прозрачен.
подробнее о проблеме
Проблема не является уникальной для фасетирования, но возникает всегда, если занято слишком мало интервалов, так что никакие диагонально смежные интервалы не заполняются.
Вот ряд более минимальных данных, которые показывают проблему:
Сначала я отслеживаю hexBin
, чтобы получить все координаты центра той же гексагональной сетки, что и ggplot2:::hexBin
, и объект, возвращенный hexbin
:
trace (ggplot2:::hexBin, exit = quote ({trace.grid <<- as.data.frame (hgridcent (xbins = xbins, xbnds = xbnds, ybnds = ybnds, shape = ybins/xbins) [1:2]); trace.h <<- hb}))
Настройте очень небольшой набор данных:
df <- data.frame (x = 3 : 1, y = 1 : 3)
И сюжет:
p <- ggplot(df, aes(x=x, y=y)) + geom_hex(binwidth=c(1, 1)) +
coord_fixed (xlim = c (0, 4), ylim = c (0,4))
p # needed for the tracing to occur
p + geom_point (data = trace.grid, size = 4) +
geom_point (data = df, col = "red") # data pts
str (trace.h)
Formal class 'hexbin' [package "hexbin"] with 16 slots
..@ cell : int [1:3] 3 5 7
..@ count : int [1:3] 1 1 1
..@ xcm : num [1:3] 3 2 1
..@ ycm : num [1:3] 1 2 3
..@ xbins : num 2
..@ shape : num 1
..@ xbnds : num [1:2] 1 3
..@ ybnds : num [1:2] 1 3
..@ dimen : num [1:2] 4 3
..@ n : int 3
..@ ncells: int 3
..@ call : language hexbin(x = x, y = y, xbins = xbins, shape = ybins/xbins, xbnds = xbnds, ybnds = ybnds)
..@ xlab : chr "x"
..@ ylab : chr "y"
..@ cID : NULL
..@ cAtt : int(0)
Я повторяю сюжет, опуская точку данных 2:
p <- ggplot(df [-2,], aes(x=x, y=y)) + geom_hex(binwidth=c(1, 1)) + coord_fixed (xlim = c (0, 4), ylim = c (0,4))
p
p + geom_point (data = trace.grid, size = 4) + geom_point (data = df, col = "red")
str (trace.h)
Formal class 'hexbin' [package "hexbin"] with 16 slots
..@ cell : int [1:2] 3 7
..@ count : int [1:2] 1 1
..@ xcm : num [1:2] 3 1
..@ ycm : num [1:2] 1 3
..@ xbins : num 2
..@ shape : num 1
..@ xbnds : num [1:2] 1 3
..@ ybnds : num [1:2] 1 3
..@ dimen : num [1:2] 4 3
..@ n : int 2
..@ ncells: int 2
..@ call : language hexbin(x = x, y = y, xbins = xbins, shape = ybins/xbins, xbnds = xbnds, ybnds = ybnds)
..@ xlab : chr "x"
..@ ylab : chr "y"
..@ cID : NULL
..@ cAtt : int(0)
обратите внимание, что результаты из hexbin
находятся в той же сетке (номера ячеек не изменились, просто ячейка 5 больше не заполнена и, следовательно, не указана), размеры и диапазоны сетки не изменились. Но нарисованные шестиугольники кардинально изменились.
Также обратите внимание, что hgridcent
забывает вернуть координаты центра первой ячейки (внизу слева).
Хотя он заселяется:
df <- data.frame (x = 1 : 3, y = 1 : 3)
p <- ggplot(df, aes(x=x, y=y)) + geom_hex(binwidth=c(0.5, 0.8)) +
coord_fixed (xlim = c (0, 4), ylim = c (0,4))
p # needed for the tracing to occur
p + geom_point (data = trace.grid, size = 4) +
geom_point (data = df, col = "red") + # data pts
geom_point (data = as.data.frame (hcell2xy (trace.h)), shape = 1, size = 6)
Здесь отображение шестиугольников не может быть правильным - они не принадлежат одной шестиугольной сетке.
person
cbeleites unhappy with SX
schedule
29.01.2013
+ stat_binhex(binwidth = c(0.5, 0.5))
вместоgeom_hex()
, но при добавлении фасетирования это, кажется, игнорируется. Интересно, что это работает, когда бункеры прямоугольныеqplot(x,y, data = bindata, geom = "bin2d", binwidth = c(0.5, 0.5), facets=~factor)
- person orizon   schedule 24.01.2013