如何将多边形和线段的直线与极坐标合并

如何将多边形和线段的直线与极坐标合并

本文介绍了R:如何将多边形和线段的直线与极坐标合并?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我在6个方向上有一些长度的线性数据.我想以风玫瑰"风格制作图表.

Let's say I have linear data in 6 directions with some lengths. I want to make chart in style of "wind rose".

###create sample data
a <- c(1,2,3,4,5,6) #directions
perc <- c(0.15,0.05,0.3,0.15,0.05,0.3) #percentual lengths
lab <- c("A", "B", "C", "D", "E", "F") #labels of directions
data <- data.frame(a,perc,lab)

我用ggplot2尝试了两个变体,分别使用coord_polarcoord_radar(受 Erwan Le Pennec的文章:从平行图到雷达图).每个部分是正确的,部分是错误的(根据我的期望):

I have tried two variants with ggplot2, using coord_polar and coord_radar (inspired by an article from Erwan Le Pennec: From Parallel Plot to Radar Plot). Each one is partly correct and partly wrong (from view of my expectation):

#similar parameters in both variants:
chart_stuff <- list(
  geom_polygon(aes(x=a, y=perc, col = 1), fill=NA,show.legend = F),
  geom_segment(aes(x=as.factor(a), yend=perc, xend=as.factor(a), y=0), size=2),
  scale_x_discrete(labels=data$lab),
  scale_y_continuous(labels = scales::percent, limits = c(0,0.31)),
  theme_light(),
  theme(axis.title = element_blank())
  )

#chart1
ggplot(data) +
  chart_stuff+
  coord_polar(start=(-pi/6))+
  ggtitle("coord_polar: wrong polygon, good segments")

#chart2
#coord_radar function with modified start parameter:
coord_radar <- function (theta = "x", start = -pi/6, direction = 1) {
  theta <- match.arg(theta, c("x", "y"))
  r <- if (theta == "x") "y" else "x"
  ggproto("CordRadar", CoordPolar, theta = theta, r = r, start = start,
          direction = sign(direction),
          is_linear = function(coord) TRUE)
}

ggplot(data) +
  chart_stuff+
  coord_radar()+
  ggtitle("coord_radar: good polygon, wrong segments")

输出:

所以我想要一幅图像,该图像具有多边形边界的直线和代表方向的段(以百分比的长度表示).我猜可能是将离散比例与连续比例混合在一起会导致错误,但我无法解决.有什么主意吗?

So I want one image with straight lines of polygon border and segments representing directions (in length of percentage). I guess error might be in mixing discrete scale with continuous but I can't solve it. Any idea?

推荐答案

说明

在GeomSegment的draw_panel函数中,坐标系是否是线性的会影响如何绘制面板:

Explanation

In GeomSegment's draw_panel function, whether the coordinate system is linear or not affects how the panel is drawn:

> GeomSegment$draw_panel
<ggproto method>
  <Wrapper function>
    function (...)
f(...)

  <Inner function (f)>
    function (data, panel_params, coord, arrow = NULL, arrow.fill = NULL,
    lineend = "butt", linejoin = "round", na.rm = FALSE)
{
    data <- remove_missing(data, na.rm = na.rm, c("x", "y", "xend",
        "yend", "linetype", "size", "shape"), name = "geom_segment")
    if (empty(data))
        return(zeroGrob())
    if (coord$is_linear()) {
        coord <- coord$transform(data, panel_params)
        arrow.fill <- arrow.fill %||% coord$colour
        return(segmentsGrob(coord$x, coord$y, coord$xend, coord$yend,
            default.units = "native", gp = gpar(col = alpha(coord$colour,
                coord$alpha), fill = alpha(arrow.fill, coord$alpha),
                lwd = coord$size * .pt, lty = coord$linetype,
                lineend = lineend, linejoin = linejoin), arrow = arrow))
    }
    data$group <- 1:nrow(data)
    starts <- subset(data, select = c(-xend, -yend))
    ends <- plyr::rename(subset(data, select = c(-x, -y)), c(xend = "x",
        yend = "y"), warn_missing = FALSE)
    pieces <- rbind(starts, ends)
    pieces <- pieces[order(pieces$group), ]
    GeomPath$draw_panel(pieces, panel_params, coord, arrow = arrow,
        lineend = lineend)
}

coord_polar不是线性的,因为默认情况下CoordPolar$is_linear()的计算结果为FALSE,因此根据GeomPath$draw_panel(...)绘制geom_segment.

coord_polar is not linear, because by default CoordPolar$is_linear() evaluates to FALSE, so geom_segment is drawn based on GeomPath$draw_panel(...).

coord_radar是线性的,因为is_linear = function(coord) TRUE包含在其定义中,所以geom_segment是使用segmentsGrob(...)绘制的.

coord_radar, on the other hand, is linear, because is_linear = function(coord) TRUE is included in its definition, so geom_segment is drawn using segmentsGrob(...).

我们可以定义自己的GeomSegment版本,无论坐标系是否为线性,它都使用draw_panel的前一个选项:

We can define our own version of GeomSegment, which uses the former option for draw_panel regardless whether the coordinate system is linear:

GeomSegment2 <- ggproto("GeomSegment2",
                        GeomSegment,
                        draw_panel = function (data, panel_params, coord, arrow = NULL,
                                               arrow.fill = NULL, lineend = "butt",
                                               linejoin = "round", na.rm = FALSE) {
                          data <- remove_missing(data, na.rm = na.rm,
                                                 c("x", "y", "xend", "yend", "linetype",
                                                   "size", "shape"),
                                                 name = "geom_segment")
                          if (ggplot2:::empty(data))
                            return(zeroGrob())
                          # remove option for linear coordinate system
                          data$group <- 1:nrow(data)
                          starts <- subset(data, select = c(-xend, -yend))
                          ends <- plyr::rename(subset(data, select = c(-x, -y)),
                                               c(xend = "x", yend = "y"),
                                               warn_missing = FALSE)
                          pieces <- rbind(starts, ends)
                          pieces <- pieces[order(pieces$group), ]
                          GeomPath$draw_panel(pieces, panel_params, coord, arrow = arrow,
                                              lineend = lineend)
                        })

geom_segment2 <- function (mapping = NULL, data = NULL, stat = "identity", position = "identity",
                           ..., arrow = NULL, arrow.fill = NULL, lineend = "butt",
                           linejoin = "round", na.rm = FALSE, show.legend = NA,
                           inherit.aes = TRUE) {
  layer(data = data, mapping = mapping, stat = stat, geom = GeomSegment2,
        position = position, show.legend = show.legend, inherit.aes = inherit.aes,
        params = list(arrow = arrow, arrow.fill = arrow.fill,
                      lineend = lineend, linejoin = linejoin, na.rm = na.rm,
                      ...))
}

尝试一下:

chart_stuff <- list(
  geom_polygon(aes(x=a, y=perc, col = 1), fill=NA,show.legend = F),
  # geom_segment2 instead of geom_segment
  geom_segment2(aes(x=as.factor(a), yend=perc, xend=as.factor(a), y=0), size=2),
  scale_x_discrete(labels=data$lab),
  scale_y_continuous(labels = scales::percent, limits = c(0,0.31)),
  theme_light(),
  theme(axis.title = element_blank())
)

ggplot(data) +
  chart_stuff+
  coord_radar()+
  ggtitle("coord_radar: good polygon, good segments")

这篇关于R:如何将多边形和线段的直线与极坐标合并?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 12:44