【问题标题】:Plotting Curved Lines on Polar Charts在极坐标图上绘制曲线
【发布时间】:2018-09-07 12:49:05
【问题描述】:

我正在尝试创建一个图形,该图形绘制点、标签和连接给定起点和终点位置的点的线。然后将其转换为极坐标图。我可以绘制点、标签和线,但我的问题是当我将图表转换为极坐标时。我用过geom_curve 和geom_segment.

在使用geom_curve 时出现错误,因为geom_curve 未针对非线性坐标实现。因此,我能得到的最远的是:

在使用geom_segment 时,我让它更接近我想要的效果,但它会沿着圆圈的圆周绘制线条,考虑到我通过坐标的方式,这是有道理的。这是一张照片:

我基本上需要一个geom_curve 来表示极坐标,但我一直找不到。我想要圆圈内侧的线条和弯曲的线条,会有一些重叠,但无论如何建议它看起来不错,间距或其他东西会受到欢迎。

数据:

k<-18 
ct<-12
q<-6
x_vector1<-seq(1,k,1) 
x_vector2<-seq(1,3,1) 
x_vector3<-seq(k-2,k,1) 
x_vector<-c(x_vector1,x_vector2,x_vector3)

n<-9 ## sets first level radius 
radius1<-rep(n,k) 
b<-13 ## sets second level radius 
radius2<-rep(b,q) 
radius<-c(radius1,radius2)

name<-c('Alice','Bob','Charlie','D','E','F','G','H','I','J','K','L',
        'M','N','O','Peter','Quin','Roger','Alice2','Bob2','Charlie2',
        'Peter2','Quin2','Roger2') 

dframe<-data.frame(x_vector,radius,name)
dframe$label_radius<-dframe$radius+1 

from<-c('Alice2','Bob','Charlie','D','E','Alice2','Charlie2','Charlie',
        'I','J','K','L','M','N','O','Peter','Quin','Alice') 

to<-c('Alice','Alice','Alice','Alice','Alice','Bob',
      'Bob','Bob','Bob','Charlie','Charlie','Peter',
      'Peter','Quin','Quin','Quin','Roger','Roger') 

amt<-c(3,8,8,8,6,2,2,4,2,4,8,1,10,5,9,5,2,1) 

linethick<-c(0.34,0.91,0.91,0.91,0.68,0.23,0.23,0.45,0.23,0.45,
             0.91,0.11,1.14,0.57,1.02,0.57,0.23,0.11) 

to_x<-c(1,1,1,1,1,2,2,2,2,3,3,16,16,17,17,17,18,18) 

to_rad<-c(9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9) 

from_x<-c(1,2,3,4,5,1,3,3,9,10,11,12,13,14,15,16,17,1) 

from_rad<-c(13,9,9,9,9,13,13,9,9,9,9,9,9,9,9,9,9,9) 

stats<-data.frame(from,to,amt,linethick,to_x,to_rad,from_x,from_rad)


p<-ggplot()+

  geom_point(data=dframe,aes(x=x_vector,y=radius),size=3,shape=19)+
  geom_text(data=dframe,aes(x=x_vector,y=label_radius,label=name))+   
  geom_segment(data=stats,aes(x=from_x,y=from_rad,xend=to_x,yend=to_rad, color=to), ## I need arrows starting at TO and going to FROM. ##
               arrow=arrow(angle=15,ends='first',length=unit(0.03,'npc'), type='closed'))+
     ## transform into polar coordinates   coord_polar(theta='x',start=0,direction=-1)
     ## sets up the scale to display from 0 to 7   scale_y_continuous(limits=c(0,14))+
     ## Used to 'push' the points so all 'k' show up.   expand_limits(x=0) p

【问题讨论】:

  • 请提供您用于生成这些图的数据和代码。
  • 我很抱歉。我完全以为我有。
  • 好多了,但是你的格式很混乱。我已经重新格式化了您的大部分代码,但 ggplot 代码仍然很乱。如果它与问题无关,则不要包含代码,如果是,请不要将其注释掉。
  • 顺便说一句,您的 q 变量丢失了
  • 您可以使用三角函数手动将数据点转换为极坐标,而不是依赖坐标变换。也就是说,让它看起来不错需要一些工作,而且你可能不得不牺牲coord_polar 提供的漂亮的径向网格线。

标签: r ggplot2 line polar-coordinates


【解决方案1】:

正如其他人评论的那样,您可以通过在笛卡尔坐标中自己计算来模仿coord_polar() 产生的所需位置。即:

x = radius * cos(theta)
y = radius * sin(theta)
# where theta is the angle in radians

操作 2 个数据框:

dframe2 <- dframe %>%
  mutate(x_vector = as.integer(factor(x_vector))) %>%
  mutate(theta = x_vector / n_distinct(x_vector) * 2 * pi + pi / 2) %>%
  mutate(x = radius * cos(theta),
         y = radius * sin(theta),
         y.label = label_radius * sin(theta),
         name = as.character(name))

stats2 <- stats %>%
  select(from, to, amt, linethick) %>%
  mutate_at(vars(from, to), as.character) %>%
  left_join(dframe2 %>% select(name, x, y), 
            by = c("from" = "name")) %>%
  rename(x.start = x, y.start = y) %>%
  left_join(dframe2 %>% select(name, x, y),
            by = c("to" = "name")) %>%
  rename(x.end = x, y.end = y)

使用geom_curve() 绘图:

# standardize plot range in all directions
plot.range <- max(abs(c(dframe2$x, dframe2$y, dframe2$y.label))) * 1.1

p <- dframe2 %>%
  ggplot(aes(x = x, y = y)) +
  geom_point() +
  geom_text(aes(y = y.label, label = name)) +

  # use 2 geom_curve() layers with different curvatures, such that all segments align
  # inwards inside the circle
  geom_curve(data = stats2 %>% filter(x.start > 0),
             aes(x = x.start, y = y.start, 
                 xend = x.end, yend = y.end, 
                 color = to),
             curvature = -0.3,
             arrow = arrow(angle=15, ends='first',
                           length=unit(0.03,'npc'),
                           type='closed')) +
  geom_curve(data = stats2 %>% filter(x.start <= 0),
             aes(x = x.start, y = y.start,
                 xend = x.end, yend = y.end,
                 color = to),
             curvature = 0.3,
             arrow = arrow(angle=15, ends='first',
                           length=unit(0.03,'npc'),
                           type='closed')) +
  expand_limits(x = c(-plot.range, plot.range),
                y = c(-plot.range, plot.range)) +
  coord_equal() +
  theme_void()

p

如果您想要极坐标网格线,也可以使用 geom_spoke() 和 ggfortify 包的 geom_circle() 来模仿:

library(ggforce)

p + 

  geom_spoke(data = data.frame(x = 0,
                               y = 0,
                               angle = pi * seq(from = 0, 
                                                to = 2, 
                                                length.out = 9), # number of spokes + 1
                               radius = plot.range),
             aes(x = x, y = y, angle = angle, radius = radius),
             inherit.aes = FALSE, 
             color = "grey") +

  geom_circle(data = data.frame(x0 = 0, 
                                y0 = 0, 
                                r = seq(from = 0, 
                                        to = plot.range, 
                                        length.out = 4)), # number of concentric circles + 1
              aes(x0 = x0, y0 = y0, r = r), 
              inherit.aes = FALSE,
              color = "grey", fill = NA)

(注意:如果您真的想要这些伪网格线,请将它们绘制在 其他几何图层之前。)

【讨论】:

  • 哇。这在很大程度上是有道理的。几个后续问题。在尝试在我的绘图中简单地打印出p 时,我收到一个关于无效图形状态的错误。错误似乎来自.Call.graphics(C_palette2, .Call(C_paletter2, NULL)). 另外,我在情节中没有看到线条美感,也许它太小而无法在这里看到,但它会被改变吗?最后,如果我想手动指定我自己的颜色,我可以在geom 的美学范围内照常在我的曲线和颜色/填充之前这样做吗?
  • 我无法重现错误消息。也许是由于与环境中的其他事物发生冲突。你可以在一个干净的 R 会话中尝试这个吗?至于linethick,我没看到题中用到,所以没碰。 to 值已映射到色标,因此您无需更改 geom_curve(aes(...)) 中的任何内容。如果您希望更改颜色值,您可以将scale_color_manual(values = c("colour1", "colour2", ...)) 添加到p,指定您希望使用的值。
  • 我修复了图形错误。对不起,线厚。我假设在curve 中有一种美学。好吧,我认为答案会比上面的更简单,因此为什么我没有关于着色的问题。我有一个长度为 24(元素数)的色标。假设我可以将其插入point 和“文本”部分是否安全。反正我要试试。
【解决方案2】:

你必须在ggplot2中做所有事情吗?

如果不是,那么一种选择是使用点创建绘图(可能使用 ggplot2,或者只是直网格图形,甚至可能是基础图形),然后推送到适当的视口并使用 xsplines 在点之间添加曲线(有关使用 xspline 的基本示例,请参阅此答案:Is there a way to make nice "flow maps" or "line area" graphs in R?)。

如果您坚持使用 ggplot2 进行所有操作,那么您可能需要创建自己的 geom 函数来绘制极坐标图中的曲线。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    相关资源
    最近更新 更多