Построение кривых линий на полярных картах - PullRequest
0 голосов
/ 07 сентября 2018

Я пытаюсь создать график, который отображает точки, метки и линии, которые соединяют точки с учетом начальной и конечной позиции. Затем преобразуйте его в полярную диаграмму. Я могу построить точки, метки и линии, но моя проблема в том, когда я преобразую свою диаграмму в полярную. Я использовал geom_curve и geom_segment.

При использовании geom_curve я получаю ошибку, потому что geom_curve не реализовано для нелинейных координат. Поэтому самое дальнее, что я могу получить, это: Geom_Curve with No Polar

При использовании geom_segment я приближаю его к желаемому эффекту, но он рисует линии вдоль окружности вихря, что имеет смысл, учитывая то, как я прохожу через координаты. Вот фото: Geom_Segment with Polar

Мне, по сути, нужен 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

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

Как прокомментировали другие, вы можете имитировать желаемые позиции, создаваемые coord_polar(), вычисляя их самостоятельно, в декартовых координатах. I.e.:

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

plot w/o grid lines

Если вам нужны полярные линии сетки, их также можно имитировать, используя 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)

(Примечание: если вы действительно хотите эти линии псевдосетки, нарисуйте их перед другими слоями геом.)

plot w grid lines

0 голосов
/ 07 сентября 2018

Нужно ли все делать в ggplot2?

Если нет, то одним из вариантов будет создание графика с точками (возможно, с использованием ggplot2, или просто графика с прямой сеткой, возможно, даже базовая графика), затем нажмите на соответствующий видовой экран и используйте xsplines, чтобы добавить кривые между точками (см. этот ответ: Есть ли способ создать красивые графы потоков или графики линейных областей в R? для базового примера использования xspline).

Если вы настаиваете на том, чтобы делать все, используя ggplot2, вам, вероятно, потребуется создать собственную функцию geom, которая строит кривые на графике полярных координат.

...