簡體   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