简体   繁体   English

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

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

I am trying to use ggplot to draw a radar-chart following the guidelines from the Grammar of Graphics. 我正在尝试使用ggplot按照图形语法的指导绘制雷达图。 I am aware of the ggradar package but based on the grammar it looks like coord_polar should be enough here. 我知道ggradar包,但基于语法,看起来coord_polar应该足够了。 This is the pseudo-code from the grammar: 这是语法中的伪代码:

在此输入图像描述

So I thought something like this may work, however, the contour of the area chart is curved as if I used geom_line : 所以我觉得这样的东西可能会起作用,但是,区域图的轮廓是弯曲的,好像我使用了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()

在此输入图像描述

While I understand why geom_line draws arcs once in coord_polar , my understanding of the explanation from the Grammar of Graphics is that there may be an element/geom area that could plot straight lines: 虽然我明白为什么geom_line在绘制弧形一次coord_polar ,我从图形的语法解释的理解是,有可能是一个元素/ GEOM area ,可以绘制直线:

here is one technical detail concerning the shape of Figure 9.29. 这是关于图9.29形状的一个技术细节。 Why is the outer edge of the area graphic a set of straight lines instead of arcs? 为什么该区域的外边缘图形是一组直线而不是弧线? The answer has to do with what is being measured. 答案与被测量的内容有关。 Since region is a categorical variable, the line segments linking regions are not in a metric region of the graph. 由于区域是分类变量,因此链接区域的线段不在图表的度量区域中。 That is, the segments of the domain between regions are not measurable and thus the straight lines or edges linking them are arbitrary and perhaps not subject to geometric transformation. 也就是说,区域之间的域的片段是不可测量的,因此连接它们的直线或边缘是任意的并且可能不经历几何变换。 There is one other problem with the grammatical specification of this figure. 该图的语法规范还有另一个问题。 Can you spot it? 你能发现它吗? Undo the polar trans- formation and think about the domain of the plot. 撤消极地变换并思考情节的领域。 We cheated. 我们骗了。

For completeness, this question derives from this other question I asked about plotting in polar system. 为了完整起见,这个问题来源于我在极地系统中绘制的另一个问题。

tl;dr we can write a function to solve this problem. tl; dr我们可以编写一个函数来解决这个问题。

Indeed, ggplot uses a process called data munching for non-linear coordinate systems to draw lines. 实际上,ggplot使用一种称为数据咀嚼的过程来为非线性坐标系绘制线条。 It basically breaks up a straight line in many pieces, and applies the coordinate transformation on the individual pieces instead of merely the start- and endpoints of lines. 它基本上分解了许多部分的直线,并在各个部分上应用坐标变换,而不仅仅是线的起点和终点。

If we look at the panel drawing code of for example GeomArea$draw_group : 如果我们查看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)))
}

We can see that a coord_munch is applied to the data before it is passed to polygonGrob , which is the grid package function that matters for drawing the data. 我们可以看到coord_munch在传递给polygonGrob之前应用于数据, polygonGrob是绘制数据的网格包函数。 This happens in almost any line-based geom for which I've checked this. 这种情况发生在我检查过的几乎任何基于行的geom中。

Subsequently, we would like to know what is going on in coord_munch : 随后,我们想知道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)
}

We find the logic I mentioned earlier that non-linear coordinate systems break up lines in many pieces, which is handled by ggplot2:::munch_data . 我们发现前面提到的逻辑非线性坐标系在许多部分中分解线,由ggplot2:::munch_data处理。

It would seem to me that we can trick ggplot into transforming straight lines, by somehow setting the output of coord$is_linear() to always be true. 在我看来,我们可以通过某种方式将coord$is_linear()的输出设置为true来欺骗ggplot转换为直线。

Lucky for us, we wouldn't have to get our hands dirty by doing some deep ggproto based stuff if we just override the is_linear() function to return TRUE : 幸运的是,如果我们只是覆盖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})
}

So now we can plot away with straight lines in polar coordinates: 所以现在我们可以用极坐标中的直线绘制:

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

在此输入图像描述

Now to be fair, I don't know what the unintended consequences are for this change. 现在公平地说,我不知道这种变化会产生什么样的意外后果。 At least now we know why ggplot behaves this way, and what we can do to avoid it. 至少现在我们知道为什么ggplot会这样做,以及我们可以做些什么来避免它。

EDIT: Unfortunately, I don't know of an easy/elegant way to connect the points across the axis limits but you could try code like this: 编辑:不幸的是,我不知道一个简单/优雅的方式来连接轴限制点,但你可以尝试这样的代码:

# 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()

在此输入图像描述

Some discussion about polar coordinates and crossing the boundary, including my own attempt at solving that problem, can be seen here geom_path() refuses to cross over the 0/360 line in coord_polar() 关于极坐标和跨越边界的一些讨论,包括我自己尝试解决这个问题,可以在这里看到geom_path()拒绝coord_polar()中越过0/360行

EDIT2: EDIT2:

I'm mistaken, it seems quite trivial anyway. 我错了,无论如何它似乎相当微不足道。 Assume dd is your original tibble: 假设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