(上下文:我正在使用 soc.ca 包并希望说明整体 MCA 结果与每个特定于类的结果之间的角度差异。)
我有一个斜率对的数据框,我希望说明它们与 x = 0 和 y = 0 的轴有何不同。这在静止图像中可以正常工作。但是,理想情况下,我想使用 gganimate 来说明从这些轴旋转的每一对斜坡。
为了做到这一点,我想我需要使用 geom_abline。这很好地说明了不同斜率之间的差异,但不适用于这些斜率与 x = 0 和 y = 0 之间的差异。
我的数据目前具有以下形状:
# set seed
set.seed(24601)
# load packages
library(tidyverse)
library(gganimate)
# generate vector of slopes
slopes <-
runif(12,
-2,
2)
# generate vector of cases i'm cycling through
cases <-
c(rep("a", 2),
rep("b", 2),
rep("c", 2),
rep("d", 2),
rep("e", 2),
rep("f", 2)
)
# generate vector of primary or secondary axes
axes <-
(rep(c("primary",
"secondary"),
6))
# generate vector of zeroes
zeroes <-
rep(0, 12)
# combine into a data frame
df <-
data.frame(slopes,
cases,
axes,
zeroes)
静止图像可以如下生成
ggplot(df) +
geom_abline(aes(slope = slopes,
linetype = axes,
intercept = 0)) +
geom_hline(yintercept = 0) +
geom_vline(xintercept = 0) +
facet_wrap(~ cases)
而动画目前如下:
ggplot(df) +
geom_abline(aes(intercept = zeroes,
slope = slopes,
linetype = axes)) +
transition_states(cases) +
scale_x_continuous(limits = c(-1, 1)) +
scale_y_continuous(limits = c(-1, 1))
我理想中想要的是轴在每个阶段之间“捕捉”回 x = 0 和 y = 0。但是,为了做到这一点,我需要 geom_abline 的斜率在相关情况下为无穷大。
非常欢迎任何有关如何执行此操作的建议!
mhovd 向我展示了 geom_spoke,它解决了我遇到的问题。他们在动画方面遇到了一些问题,我想我已经设法解决了:下面是我对他们代码的调整,使轴以我希望的方式旋转。
library(tidyverse)
library(gganimate)
# Seed
set.seed(24601)
# Given the following slopes
# nb I diverge from the helpful solution here
# by having the x and y slopes as separate variables
x_slopes <-
runif(6,
-2,
2)
y_slopes <-
runif(6,
-2,
2)
# What are the angles?
df = data.frame(
x = 0, # Draw from zero
y = 0, # Draw from zero
angle_1 = atan(x_slopes), # generate primary axis slopes
angle_2 = atan(y_slopes) + pi/2, # generate secondary axis slopes
radius = 5, # Make sufficiently long lines
cases =c("a", "b", "c", "d", "e", "f")
) %>%
mutate( angle_3 = angle_1 + pi, # opposite angle for primary axis
angle_4 = angle_2 + pi, # opposite angle for secondary axis
)
df
# Add horizontal and vertical lines
# again this differs from the solution as i have
# separate variables for the (originally) horizontal and vertical lines
original_axis_data = data.frame(x = 0,
y = 0,
angle_1 = atan(0),
angle_2 = atan(0) + pi/2,
angle_3 = atan(0) + pi,
angle_4 = atan(0) + pi*1.5,
radius = 5,
cases = "reset")
# combine these objects
df = rbind(df, original_axis_data)
# generate list (from solution)
animation_list = list(
df %>% filter(cases == "a") %>% mutate(event = 1),
df %>% filter(cases == "reset") %>% mutate(event = 2),
df %>% filter(cases == "b") %>% mutate(event = 3),
df %>% filter(cases == "reset") %>% mutate(event = 4),
df %>% filter(cases == "c") %>% mutate(event = 5),
df %>% filter(cases == "reset") %>% mutate(event = 6),
df %>% filter(cases == "d") %>% mutate(event = 7),
df %>% filter(cases == "reset") %>% mutate(event = 8),
df %>% filter(cases == "e") %>% mutate(event = 9),
df %>% filter(cases == "reset") %>% mutate(event = 10),
df %>% filter(cases == "f") %>% mutate(event = 11),
df %>% filter(cases == "reset") %>% mutate(event = 12)
)
# convert to data frame (again from solution)
animation_data = bind_rows(animation_list) %>%
mutate(cases = factor(cases)) # To make ggplot respect the order
# animate!
animation_data %>%
ggplot(aes(x = x, y = y, radius = radius)) + # i have simplified these aes
geom_spoke(aes(angle = angle_1)) + # primary axis, original
geom_spoke(aes(angle = angle_2),
linetype = "dashed") + # secondary axis, original, linetype explicit
geom_spoke(aes(angle = angle_3)) + # primary axis plus pi
geom_spoke(aes(angle = angle_4),
linetype = "dashed") + # secondary axis plus pi
coord_cartesian(ylim=c(-1, 1), xlim = c(-1, 1)) + # Zoom in without removing data like scale_*_continous does
theme(legend.position = NULL, aspect.ratio = 1) +
transition_states(event) +
labs(title = "{closest_state}")
答案 0 :(得分:1)
不是使用斜率,也许您可以使用geom_spoke
通过角度实现您想要的效果。
线的倾角为theta = atan(slope)
。相反的角度是theta + pi
。
对于水平线和垂直线,您是否会分别通过 0
和 Inf
的斜率。
编辑:我在展示如何构建动画方面做了一个糟糕的尝试,但我无法让它平滑过渡。希望你能以此为基础。
library(tidyverse)
library(gganimate)
# Seed
set.seed(24601)
# Given the following slopes
slopes <- runif(12,-2, 2)
# What are the angles?
df = data.frame(
x = 0, # Draw from zero
y = 0, # Draw from zero
angle1 = atan(slopes), # First segment, actual angle
angle2 = atan(slopes) + pi, # Second segment, opposite angle
radius = 5, # Make sufficiently long lines
cases =c(rep("a", 2), rep("b", 2), rep("c", 2), rep("d", 2), rep("e", 2), rep("f", 2)),
axes = c("primary", "secondary")
)
# Add horizontal and vertical lines
hline_data = data.frame(x = 0, y = 0, angle1 = atan(0), angle2 = atan(0) + pi, radius = 5, cases = "reset", axes = "primary")
vline_data = data.frame(x = 0, y = 0, angle1 = atan(Inf), angle2 = atan(Inf) + pi, radius = 5, cases = "reset", axes = "primary")
df = rbind(df, vline_data, hline_data)
df %>%
ggplot(aes(x = x, y = y, radius = radius, col = cases, linetype = axes)) +
geom_spoke(aes(angle = angle1)) +
geom_spoke(aes(angle = angle2)) +
coord_cartesian(ylim=c(-1, 1), xlim = c(-1, 1)) + # Zoom in without removing data like scale_*_continous does
theme(legend.position = NULL, aspect.ratio = 1)
# Poor attempt at building the animation
animation_list = list(
df %>% filter(cases == "a") %>% mutate(event = 1),
df %>% filter(cases == "reset") %>% mutate(event = 2),
df %>% filter(cases == "b") %>% mutate(event = 3),
df %>% filter(cases == "reset") %>% mutate(event = 4),
df %>% filter(cases == "c") %>% mutate(event = 5),
df %>% filter(cases == "reset") %>% mutate(event = 6),
df %>% filter(cases == "d") %>% mutate(event = 7),
df %>% filter(cases == "reset") %>% mutate(event = 8),
df %>% filter(cases == "e") %>% mutate(event = 9),
df %>% filter(cases == "reset") %>% mutate(event = 10),
df %>% filter(cases == "f") %>% mutate(event = 11),
df %>% filter(cases == "reset") %>% mutate(event = 12)
)
animation_data = bind_rows(animation_list) %>%
mutate(cases = factor(cases)) # To make ggplot respect the order
animation_data %>%
ggplot(aes(x = x, y = y, radius = radius, linetype = axes, group = event)) +
geom_spoke(aes(angle = angle1)) +
geom_spoke(aes(angle = angle2)) +
coord_cartesian(ylim=c(-1, 1), xlim = c(-1, 1)) + # Zoom in without removing data like scale_*_continous does
theme(legend.position = NULL, aspect.ratio = 1) +
transition_states(event) +
labs(title = "{closest_state}")
由 reprex package (v2.0.0) 于 2021 年 7 月 9 日创建