ggplot geom_tile 在 ggplotly 中失真
ggplot geom_tile is distorted in ggplotly
我正在尝试将使用 ggplot
构建的 geom_tile
地块转换为 ggplotly
。但是,瓷砖在情节中扭曲了。 geom_raster
.
也会出现同样的问题
展示:
library(ggplot2)
library(plotly)
set.seed(1)
n <- 10
X <- data.frame(xcoord = sample(1:10, n, replace = TRUE),
ycoord = sample(1:10, n, replace = TRUE),
value = runif(n))
gg <- ggplot(X) + geom_tile(aes(x = xcoord, y = ycoord, fill = value))
ggplotly(gg)
查看绘图代码 here (excerpt below),似乎栅格仅针对数据集中可用的任何 x 和 y 值定义 - 无论中间发生什么,都在其余的绘图代码中.
geom2trace.GeomTile <- function(data, params, p) {
x <- sort(unique(data[["x"]]))
y <- sort(unique(data[["y"]]))
# make sure we're dealing with a complete grid
g <- expand.grid(x = x, y = y)
g$order <- seq_len(nrow(g))
g <- merge(g, data, by = c("x", "y"), all.x = TRUE)
g <- g[order(g$order), ]
...
对于示例数据,此代码生成以下数据,其中灰色区域为 NA,空白区域只是未定义。所有 distortions/stretching 都发生在未定义的区域。
ggplot(g, aes(x = x, y = y, fill = value)) + geom_tile()
有了这个,一种可能的解决方法(在 plotly 包之外)是手动确保在整个 x/y 范围内有 (NA) 数据可用,因此 expand.grid 生成足够密集的网格当情节被翻译成 plotly.
set.seed(1)
X1 <- data.frame(xcoord = c(sample(1:10, n, replace = TRUE), 1:10),
ycoord = c(sample(1:10, n, replace = TRUE), 1:10),
value = c(runif(n), rep(NA, 10)))
gg1 <- ggplot(X1) + geom_tile(aes(x = xcoord, y = ycoord, fill = value))
ggplotly(gg1)
更新
虽然上面的例子表明数据集中的任何 x 和 y 都有一个单一的值就足够了,但我还将添加一个可以说更清晰的解决方案,正如 Waldi 所建议的在评论中。通过(自动)提前生成完整的网格,可以减少对情节翻译怪癖的依赖。对于不为1的网格间距,当然需要调整顺序。
# X: original dataframe as defined in the question
X2 <- tidyr::expand_grid(
xcoord = seq(min(X$xcoord), max(X$xcoord)),
ycoord = seq(min(X$ycoord),max(X$ycoord))
) %>%
dplyr::left_join(X, by=c('xcoord','ycoord'))
gg2 <- ggplot(X2) + geom_tile(aes(x = xcoord, y = ycoord, fill = value))
ggplotly(gg2)
我正在尝试将使用 ggplot
构建的 geom_tile
地块转换为 ggplotly
。但是,瓷砖在情节中扭曲了。 geom_raster
.
展示:
library(ggplot2)
library(plotly)
set.seed(1)
n <- 10
X <- data.frame(xcoord = sample(1:10, n, replace = TRUE),
ycoord = sample(1:10, n, replace = TRUE),
value = runif(n))
gg <- ggplot(X) + geom_tile(aes(x = xcoord, y = ycoord, fill = value))
ggplotly(gg)
查看绘图代码 here (excerpt below),似乎栅格仅针对数据集中可用的任何 x 和 y 值定义 - 无论中间发生什么,都在其余的绘图代码中.
geom2trace.GeomTile <- function(data, params, p) {
x <- sort(unique(data[["x"]]))
y <- sort(unique(data[["y"]]))
# make sure we're dealing with a complete grid
g <- expand.grid(x = x, y = y)
g$order <- seq_len(nrow(g))
g <- merge(g, data, by = c("x", "y"), all.x = TRUE)
g <- g[order(g$order), ]
...
对于示例数据,此代码生成以下数据,其中灰色区域为 NA,空白区域只是未定义。所有 distortions/stretching 都发生在未定义的区域。
ggplot(g, aes(x = x, y = y, fill = value)) + geom_tile()
有了这个,一种可能的解决方法(在 plotly 包之外)是手动确保在整个 x/y 范围内有 (NA) 数据可用,因此 expand.grid 生成足够密集的网格当情节被翻译成 plotly.
set.seed(1)
X1 <- data.frame(xcoord = c(sample(1:10, n, replace = TRUE), 1:10),
ycoord = c(sample(1:10, n, replace = TRUE), 1:10),
value = c(runif(n), rep(NA, 10)))
gg1 <- ggplot(X1) + geom_tile(aes(x = xcoord, y = ycoord, fill = value))
ggplotly(gg1)
更新
虽然上面的例子表明数据集中的任何 x 和 y 都有一个单一的值就足够了,但我还将添加一个可以说更清晰的解决方案,正如 Waldi 所建议的在评论中。通过(自动)提前生成完整的网格,可以减少对情节翻译怪癖的依赖。对于不为1的网格间距,当然需要调整顺序。
# X: original dataframe as defined in the question
X2 <- tidyr::expand_grid(
xcoord = seq(min(X$xcoord), max(X$xcoord)),
ycoord = seq(min(X$ycoord),max(X$ycoord))
) %>%
dplyr::left_join(X, by=c('xcoord','ycoord'))
gg2 <- ggplot(X2) + geom_tile(aes(x = xcoord, y = ycoord, fill = value))
ggplotly(gg2)