繁体   English   中英

如何使用极坐标在ggplot中绘制雷达图?

[英]How to draw a radar plot in ggplot using polar coordinates?

我正在尝试使用ggplot按照图形语法的指导绘制雷达图。 我知道ggradar包,但基于语法,看起来coord_polar应该足够了。 这是语法中的伪代码:

在此输入图像描述

所以我觉得这样的东西可能会起作用,但是,区域图的轮廓是弯曲的,好像我使用了geom_line

library(tidyverse)
dd <- tibble(category = c('A', 'B', 'C'), value = c(2, 7, 4))
ggplot(dd, aes(x = category, y = value, group=1)) +
  coord_polar(theta = 'x') +
  geom_area(color = 'blue', alpha = .00001) +
  geom_point()

在此输入图像描述

虽然我明白为什么geom_line在绘制弧形一次coord_polar ,我从图形的语法解释的理解是,有可能是一个元素/ GEOM area ,可以绘制直线:

这是关于图9.29形状的一个技术细节。 为什么该区域的外边缘图形是一组直线而不是弧线? 答案与被测量的内容有关。 由于区域是分类变量,因此链接区域的线段不在图表的度量区域中。 也就是说,区域之间的域的片段是不可测量的,因此连接它们的直线或边缘是任意的并且可能不经历几何变换。 该图的语法规范还有另一个问题。 你能发现它吗? 撤消极地变换并思考情节的领域。 我们骗了。

为了完整起见,这个问题来源于我在极地系统中绘制的另一个问题。

tl; dr我们可以编写一个函数来解决这个问题。

实际上,ggplot使用一种称为数据咀嚼的过程来为非线性坐标系绘制线条。 它基本上分解了许多部分的直线,并在各个部分上应用坐标变换,而不仅仅是线的起点和终点。

如果我们查看GeomArea$draw_group的面板绘图代码:

    function (data, panel_params, coord, na.rm = FALSE) 
{
    ...other_code...
    positions <- new_data_frame(list(x = c(data$x, rev(data$x)), 
        y = c(data$ymax, rev(data$ymin)), id = c(ids, rev(ids))))
    munched <- coord_munch(coord, positions, panel_params)
    ggname("geom_ribbon", polygonGrob(munched$x, munched$y, id = munched$id, 
        default.units = "native", gp = gpar(fill = alpha(aes$fill, 
            aes$alpha), col = aes$colour, lwd = aes$size * .pt, 
            lty = aes$linetype)))
}

我们可以看到coord_munch在传递给polygonGrob之前应用于数据, polygonGrob是绘制数据的网格包函数。 这种情况发生在我检查过的几乎任何基于行的geom中。

随后,我们想知道coord_munch发生了coord_munch

function (coord, data, range, segment_length = 0.01) 
{
    if (coord$is_linear()) 
        return(coord$transform(data, range))
    ...other_code...
    munched <- munch_data(data, dist, segment_length)
    coord$transform(munched, range)
}

我们发现前面提到的逻辑非线性坐标系在许多部分中分解线,由ggplot2:::munch_data处理。

在我看来,我们可以通过某种方式将coord$is_linear()的输出设置为true来欺骗ggplot转换为直线。

幸运的是,如果我们只是覆盖is_linear()函数返回TRUE ,我们就不必通过做一些基于ggproto的深层东西来弄脏手:

# Almost identical to coord_polar()
coord_straightpolar <- function(theta = 'x', start = 0, direction = 1, clip = "on") {
  theta <- match.arg(theta, c("x", "y"))
  r <- if (theta == "x") 
    "y"
  else "x"
  ggproto(NULL, CoordPolar, theta = theta, r = r, start = start,
          direction = sign(direction), clip = clip,
          # This is the different bit
          is_linear = function(){TRUE})
}

所以现在我们可以用极坐标中的直线绘制:

ggplot(dd, aes(x = category, y = value, group=1)) +
  coord_straightpolar(theta = 'x') +
  geom_area(color = 'blue', alpha = .00001) +
  geom_point()

在此输入图像描述

现在公平地说,我不知道这种变化会产生什么样的意外后果。 至少现在我们知道为什么ggplot会这样做,以及我们可以做些什么来避免它。

编辑:不幸的是,我不知道一个简单/优雅的方式来连接轴限制点,但你可以尝试这样的代码:

# Refactoring the data
dd <- data.frame(category = c(1,2,3,4), value = c(2, 7, 4, 2))

ggplot(dd, aes(x = category, y = value, group=1)) +
  coord_straightpolar(theta = 'x') +
  geom_path(color = 'blue') +
  scale_x_continuous(limits = c(1,4), breaks = 1:3, labels = LETTERS[1:3]) +
  scale_y_continuous(limits = c(0, NA)) +
  geom_point()

在此输入图像描述

关于极坐标和跨越边界的一些讨论,包括我自己尝试解决这个问题,可以在这里看到geom_path()拒绝coord_polar()中越过0/360行

EDIT2:

我错了,无论如何它似乎相当微不足道。 假设dd是你原来的tibble:

ggplot(dd, aes(x = category, y = value, group=1)) +
  coord_straightpolar(theta = 'x') +
  geom_polygon(color = 'blue', alpha = 0.0001) +
  scale_y_continuous(limits = c(0, NA)) +
  geom_point()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM