【问题标题】:How to draw a point in polar coordinates with negative r?如何在极坐标中用负 r 绘制一个点?
【发布时间】:2019-07-15 01:45:21
【问题描述】:

我正在尝试在极坐标 (r, theta) 中绘制两个点,其中 r 是距中心的距离,而 theta 是角度。

当前的解决方案不起作用,因为我没有唯一的轴“原点”。使用coord_plane时,y的原点是圆心,但x的原点似乎是每个半径的中心。

我想要做的是在一个系统中绘制,其中下例中的两个点相对于原点对称。

library(ggplot2)
ggplot(data.frame(r = c(-100, 100) , theta = c(1, 1)),
       aes(x = r, y= theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y',
              direction = -1,
              start = -pi/2) +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi'))

更新:

虽然coord_polar 创建的系统可能不是“直的”极坐标系统,但这里引用了图形语法的一段话,部分解释了 coord_polar 的行为,以及我必须这样做的原因修复y的限制:

我们可以将极坐标视为所有其他方式的例外 在这个系统中处理秤。也就是说,我们可以解释 angular 值绝对为弧度。如果我们所有的 图形是数学或工程应用,涉及 弧度。然而,我们选择不这样做,以便我们可以隐藏 进行坐标转换时的缩放细节。这使它 例如,用极坐标表示一年的时间很容易。在 极坐标转换,因此,我们将 0 弧度与 以数据单位(度、弧度、比例、 等)和最大的2S弧度。循环参数,一起 在 scale 函数中使用 min 和 max 参数允许我们创建 如果我们愿意,可以使用不止一次旋转的极坐标图。

【问题讨论】:

  • 我认为这里的关键(并用于两个答案)是将 "negative r" 转换为 "positive r, pi 弧度周围圆”。有了这个,解决方案是调整数据,在这一点上绘制它会自行解决。
  • @r2evans 我的问题是该解决方案如何“扩展到”其他操作。例如,在极坐标中绘制直线方程。
  • 我理解您的担忧,我认为这就是它的外观和行为方式,所以我认为它是正确的。从概念上讲,“1 at 45deg”和“-1 at 225deg”之间的区别是什么?他们不是(手工)绘制到极坐标图上的同一个地方吗?
  • @r2evans 我不确定我是否明白你的意思,但关于“正确性”:我在对 antoine-sac 的回复的评论中引用了来自图形语法的一段话,它解释了默认行为,即诚然,在数学意义上不是“正确的”,但作者为这种约定提供了充分的理由。对我来说,一个副作用是我在极坐标中有一个直线方程,并且该方程的绘制不正确(并且“不正确”是指不在正常的极坐标系中)。
  • @r2evans 这正是我所做的,推导出在极坐标中看起来像直线的方程,它不适用于coord_polar,因为那不是极坐标系。对于您的另一点:geom_line 看起来像coord_polar 中的弧线对我来说完全有意义。但是,我认为我实际上发现了与 geom_area 呈现方式的语法不一致:即使在极坐标中,几何图形也应保持轮廓线笔直。

标签: r ggplot2


【解决方案1】:

我不完全了解您的最终目标是什么,但问题可能是如果您希望r 表示到原点的距离,那么它不能为负数。 ggplot2 对 coord_polar() 所做的只是使整个笛卡尔平面按照极坐标变形。这导致“零”实际上是“径向”坐标的下限。如果您手动更改其限制,您可以清楚地看到它:

library(ggplot2)
ggplot(data.frame(r = c(-100, 100) , theta = c(1, 1)),
       aes(x = r, y= theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y',
              direction = -1,
              start = -pi/2) +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi')) +
  scale_x_continuous(limits = c(-200, NA))

我不知道您所说的“关于原点对称”的确切含义,但是这样可以吗?

library(ggplot2)
ggplot(data.frame(r = c(100, 100) , theta = c(1, 1 + pi)),
       aes(x = r, y= theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y',
              direction = -1,
              start = -pi/2) +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi')) +
  scale_x_continuous(limits = c(0, NA))

reprex package (v0.3.0) 于 2019 年 7 月 16 日创建

【讨论】:

  • 感谢您的回答。图片 2 实际上是我正在寻找的,如果飞机是“实际”极地飞机,你会得到什么。我的最终目标是在极平面上绘制一条直线 - 但首先我需要弄清楚如何绘制一个点......
  • @Dambo 如果最终结果是一条直线,请考虑通用注释,例如使用cowplot (cran.r-project.org/web/packages/cowplot/vignettes/…) - 只需创建一条线作为第二个绘图并叠加。为此目的可能是一个直接的黑客攻击。
  • @Tjebo 很遗憾不是我的选择,我需要在极坐标中画线。
【解决方案2】:

将 Elio Campitelli 的答案改编为一个函数,您可以使用以下内容:

plot_polar_signed <- function(r, theta) {
  data2 <- data.frame(r2 = abs(r),
             theta2 = theta + ifelse(r < 0, pi, 0))
  ggplot(data2, aes(x = r2, y = theta2)) +
    geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
    coord_polar(theta = 'y',
                direction = -1,
                start = -pi/2) +
    scale_y_continuous(limits = c(0, 2*pi),
                       breaks = c(0, pi/2, pi, 3*pi/2 ),
                       labels = c('0', 'pi/2', 'pi', '3/2pi'))

}

plot_polar_signed(r = c(-100, 100), theta = c(1, 1))

【讨论】:

  • 不知何故我没有看到您的答案并发布了相同的内容--'
【解决方案3】:

带有r &lt; 0 的点没有在极坐标中定义,因为r 是到中心的距离。否则,即使强制 theta 位于 (0, 2pi) 中,r != 0 的每个点也会有 2 组坐标。

因此,您实际上是在尝试在扩展极坐标系中进行绘图,其中允许负 r 并且 (r, theta)(-r, theta + pi) 是相同的点。

我建议使用从您的系统到标准极坐标的映射。

canonical <- function(r, theta) {
  if (r >= 0) {
    c(r = r, theta = theta %% (2*pi))
  } else {
    c(r = -r, theta = (theta + pi) %% (2*pi))
  }
}

或更短且矢量化:

canonical <- function(r, theta) {
  list(r = abs(r), 
       theta = (theta + ifelse(r < 0, pi, 0)) %% (2 * pi))
}

这将保持有效的极坐标不变(除非将 theta 带入 (0, 2pi),如果它还没有)并将带有 r &lt; 0 的点转换为有效的极坐标。

canonical(1, 0)
# untouched 

canonical(-1, 0)
# becomes (1, pi)

优点是转换后可以使用ggplot中的所有标准极坐标函数。

library(ggplot2)

df <- data.frame(r = c(-100, -50, 0, 50, 100) , theta = rep(1, 5))
df_polar <- as.data.frame(canonical(df$r, df$theta))

ggplot(df_polar,
       aes(x = r, y = theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y') +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi'))

同样的另一个选择是将极坐标转换为笛卡尔坐标,以便于绘制直线。映射是x = r*cos(theta)y=r*sin(theta),有趣的是,它对负r 也有效,因为cos(theta+pi) = -cos(theta)sin 相同。

【讨论】:

  • 这种方法的一个问题是我无法在极坐标中绘制直线,因为r 被绘制成负数。该方程在其他软件中可以很好地绘制 - 我会考虑 - 极坐标系。这是他们绘制负 r 的 wolfram 的链接:mathworld.wolfram.com/PolarCoordinates.html
  • 你有没有考虑过从极坐标转换为笛卡尔坐标,用 ggplot 画线很容易?
  • 是的,但我真的是想能够在极坐标中绘图。但是,我查阅了图形语法,它说“我们可以将极坐标视为该系统中处理所有其他比例的方式的例外。也就是说,我们可以将角度值绝对解释为弧度。如果我们所有的图形都是涉及弧度的数学或工程应用程序。但是,我们选择不这样做,以便我们可以在进行坐标转换时隐藏缩放细节”(第 205 页) - 所以我猜极坐标系统在ggplot2
猜你喜欢
  • 1970-01-01
  • 2016-09-26
  • 1970-01-01
  • 1970-01-01
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 2017-05-03
  • 1970-01-01
相关资源
最近更新 更多