如何在ggplot中制作像甜甜圈一样的循环彩色图例?

问题描述 投票:3回答:1

上下文

我有一些看起来像这样的数据:

val = 0:100
sample_data = data.frame(
    t=val, 
    px=cos(2*pi*val/100), 
    py=sin(2*pi*val/100), 
    v_angle = (val*360/100 + 90) %% 360
)

我在这里描述圆周运动,我想绘制一个根据角度改变颜色的图表。

但是,由于方向是周期性的,所以我希望使用一个类似甜甜圈形状的图例,使其完美地循环,以便0360相同。/

现在,我的图看起来像这样:

direction_labeller <- function(x){
  ifelse(
    x %% 45 == 0, 
    c('E','NE','N','NW','W','SW','S','SE')[1+as.integer(x/45)], 
    ''
  )
}

# from cetcolor::cet_pal(8, 'c2s')
colors=c("#2E22EA","#9E3DFB","#F86BE2","#FCCE7B","#C4E416","#4BBA0F","#447D87","#2C24E9")

ggplot(sample_data) + 
  geom_path(aes(x=px, y=py, color=v_angle)) + 
  scale_color_gradientn(
    colors=colors,
    breaks=seq(0,315,45),
    label=direction_labeller,
    limits=c(0,359)
  )

enter image description here

我的最终目标是能够使用颜色描述我拥有的其他数据的速度,因为在彼此非常接近的路径上方向可能不同。

或者,我仅根据基本方向和基本方向之间的45度角对方向进行了分箱,这是最终结果

direction_categorize <- function(angles){
  factor(
    case_when(
      is.na(angles) ~ as.character(NA),
      between(angles,-22.5,22.5) ~ 'E',
      between(angles,22.5,67.5) ~ 'NE',
      between(angles,67.5,112.5) ~ 'N',
      between(angles,112.5,157.5) ~ 'NW',
      between(angles, 157.5, 202.5) ~ 'W',
      between(angles, 202.5, 247.5) ~ 'SW',
      between(angles, 247.5, 292.5) ~ 'S',
      between(angles, 292.5, 337.5) ~ 'SE',
      TRUE ~ 'E'
    ),
    levels=c('N','NW','W','SW','S','SE','E','NE')
  )
}

sample_data$direction = direction_categorize(sample_data$v_angle)
ggplot(sample_data) + 
  geom_path(aes(x=px, y=py, color=direction, group=1)) + 
  scale_color_manual(
    values=colors
  )

enter image description here

我对此的主要问题是,边界附近的摆动非常分散注意力,因为在颜色之间来回移动看起来像一系列不连续。

r ggplot2 legend
1个回答
0
投票

所以,对我来说,最简单的方法是通过创建一个单独的甜甜圈图,并使用gridExtra作为图例>

library(tidyverse)
library(gridExtra)

val = 0:100
sample_data = data.frame(t=val, px=cos(2*pi*val/100), py=sin(2*pi*val/100), v_angle = (val*360/100 + 90) %% 360)

direction_labeller <- function(x){
  ifelse(x %% 45 == 0, c('E','NE','N','NW','W','SW','S','SE')[1+(as.integer(x/45) %% 8)], '')
}

# from cetcolor::cet_pal(8, 'c2s')
my_colors=c("#2E22EA","#9E3DFB","#F86BE2","#FCCE7B","#C4E416","#4BBA0F","#447D87","#2C24E9")

(sample_plot1 = ggplot(sample_data) + 
  geom_path(aes(x=px, y=py, color=v_angle)) + 
  scale_color_gradientn(
    colors=my_colors,
    breaks=seq(0,315,45),
    label=direction_labeller,
    limits=c(0,359)
  )
)


hues_df = data.frame(degree = 0:359) %>%
  mutate(
    label=direction_labeller(degree+90 %% 360),
    colors = colorRampPalette(my_colors)(360)
  )

(color_compass = ggplot(hues_df) + 
  geom_rect(
    aes(ymin=3,ymax=4, xmin=degree-0.5,xmax=degree+0.5,color=colors,fill=colors)
  ) + coord_polar(direction=-1, start=0) +
  scale_color_identity() + 
  scale_fill_identity() +
  guides(fill=FALSE,color=FALSE) + 
  theme_void() + 
  ylim(c(1,4.5)) + 
  geom_text(
    aes(x=degree,y=4.5,label=label) 
  ) 
)

grid.arrange(sample_plot1 + guides(color=FALSE), color_compass, ncol=2, widths = c(4,1))

上面的比率是可调的,但是上面的含义很简单。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.