からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

【R】円周の作図

はじめに

 R言語で三角関数の定義や公式を可視化しようシリーズです。

 この記事では、円のグラフを作成します。

【他の記事一覧】

www.anarchive-beta.com

www.anarchive-beta.com

【この記事の内容】

円周の作図

 ggplot2パッケージを利用して、円周(circumference)のグラフを作成します。また、円座標系(circular coordinates)をグラフで確認します。
 詳しい計算については「円周の作図【Matplotlib】 - からっぽのしょこ」も参照してください。

 利用するパッケージを読み込みます。

# 利用パッケージ
library(tidyverse)
library(gganimate)

 この記事では、基本的にパッケージ名::関数名()の記法を使うので、パッケージを読み込む必要はありません。ただし、作図コードがごちゃごちゃしないようにパッケージ名を省略しているためggplot2を読み込む必要があります。
 また、ネイティブパイプ演算子|>を使っています。magrittrパッケージのパイプ演算子%>%に置き換えても処理できますが、その場合はmagrittrも読み込む必要があります。

定義式の確認

 まずは、円の定義式を確認します。

 点  (a, b) を中心とする半径  r の円は、次の式で定義されます。

 \displaystyle
(x - a)^2 + (y - b)^2
    = r^2

 平面上の座標(x軸とy軸の値)は、それぞれ次の式で計算できます。

 \displaystyle
\begin{cases}
    x = a + r \cos \theta \\
    y = b + r \sin \theta
\end{cases}

  \sin \theta はサイン関数、 \cos \theta はコサイン関数です。 \theta は、中心と点  (a + r, b) を結ぶ線分(原点を中心としたときのx軸の正の部分)と、中心と点  (x, y) を結ぶ線分のなす角の角度に対応します。(正確には、なす角は  180^{\circ} 以下の正の値なので、なす角ではないと思いますが適切な呼び方が分かりません。)
 点  (x, y) は、中心からのユークリッドノルム  \|(x - a, y - b)\| = \sqrt{(x - a)^2 + (y - b)^2} r の点です。

 原点  (0, 0) を中心とする( a = 0, b = 0 の)場合は、次の式になります。

 \displaystyle
x^2 + y^2
    = r^2

 座標は、それぞれ次の式で計算できます。

 \displaystyle
\begin{cases}
    x = r \cos \theta \\
    y = r \sin \theta
\end{cases}


 原点を中心とする単位円(半径が1の円)の場合は、次の式になります。

 \displaystyle
x^2 + y^2
    = 1

 座標は、それぞれ次の式で計算できます。

 \displaystyle
\begin{cases}
    x = \cos \theta \\
    y = \sin \theta
\end{cases}


 これらの式を使ってグラフを作成します。

円の描画

 次は、円のグラフを作成します。

 円を描画するためのデータフレームを作成します。

# 中心の座標を指定
a <- 5
b <- 6

# 半径を指定
r <- 2

# 円の描画用
circle_df <- tibble::tibble(
  theta_deg = seq(from = 0, to = 360, length.out = 361), # 度数法
  theta_rad = theta_deg / 180 * pi, # 弧度法
  x = a + r * cos(theta_rad), 
  y = b + r * sin(theta_rad)
)
circle_df
## # A tibble: 361 × 4
##    theta_deg theta_rad     x     y
##        <dbl>     <dbl> <dbl> <dbl>
##  1         0    0       7     6   
##  2         1    0.0175  7.00  6.03
##  3         2    0.0349  7.00  6.07
##  4         3    0.0524  7.00  6.10
##  5         4    0.0698  7.00  6.14
##  6         5    0.0873  6.99  6.17
##  7         6    0.105   6.99  6.21
##  8         7    0.122   6.99  6.24
##  9         8    0.140   6.98  6.28
## 10         9    0.157   6.98  6.31
## # … with 351 more rows

 半径  rr、円の中心のx軸の値  aa、y軸の値  bbとして値を指定して、円周上の点の座標を計算します。
 度数法における角度  0^{\circ} \leq \theta^{\circ} \leq 360^{\circ} の範囲の値を作成してtheta_deg列とします。
 theta_deg列を用いて、弧度法における角度(ラジアン)を  \theta = \theta^{\circ} \frac{2 \pi}{360} で計算してtheta_rad列とします。 \pi は円周率で、piで扱えます。 0^{\circ} = 0 \frac{\pi}{180} = 0 360^{\circ} = 360 \frac{\pi}{180} = 2 \pi なので、ラジアンは、 0 \leq \theta \leq 2 \pi の範囲の値になります。詳しくは「度数法と弧度法の関係」で確認します。
 theta_rad列を用いて、x軸の値  x = a + r \cos \theta とy軸の値  y = b + r \sin \theta を計算してx, y列とします。

 あるいは、ラジアンを作成して、座標を計算します。

# 円周の座標を計算
circle_df <- tibble::tibble(
  theta_rad = seq(from = 0, to = 2*pi, length.out = 361), # ラジアン
  x = a + r * cos(theta_rad), 
  y = b + r * sin(theta_rad)
)
circle_df
## # A tibble: 361 × 3
##    theta_rad     x     y
##        <dbl> <dbl> <dbl>
##  1    0       7     6   
##  2    0.0175  7.00  6.03
##  3    0.0349  7.00  6.07
##  4    0.0524  7.00  6.10
##  5    0.0698  7.00  6.14
##  6    0.0873  6.99  6.17
##  7    0.105   6.99  6.21
##  8    0.122   6.99  6.24
##  9    0.140   6.98  6.28
## 10    0.157   6.98  6.31
## # … with 351 more rows

 ラジアンとして用いる  0 \leq \theta \leq 2 \piの範囲の値を作成して、同様に座標を計算します。

 円周のグラフを作成します。

# 円を作図
ggplot() + 
  geom_path(data = circle_df, 
            mapping = aes(x = x, y = y, linetype = "circle")) + # 円周
  geom_segment(mapping = aes(x = a, y = b, xend = a+r, yend = b)) + # 半径
  geom_text(mapping = aes(x = a+0.5*r, y = b), 
            label = "r", parse = TRUE, 
            size = 5, hjust = 0.5, vjust = -0.5) + # 半径ラベル
  geom_point(mapping = aes(x = a, y = b), 
             size = 3) + # 中心点
  geom_text(mapping = aes(x = a, y = b), 
            label = "O", parse = TRUE, 
            size = 5, hjust = 0.5, vjust = -0.5) + # 中心ラベル
  scale_linetype_manual(breaks = "circle", values = "solid",
                        label = expression((x - a)^2 + (y - b)^2 == r^2), 
                        name = "formula") + # (凡例表示用)
  coord_fixed(ratio = 1) + # アスペクト比
  labs(title = "circle", 
       subtitle = paste0("O=(a, b)=(", a, ", ", b, "), r=", r), 
       x = expression(x == a + r~cos~theta), 
       y = expression(y == b + r~sin~theta))

円のグラフ

 横軸を  a + r \cos \theta、縦軸を  b + r \sin \theta として、(geom_line()ではなく)geom_path()で円を描画します。綺麗な円を描画するには、coord_***()ratio引数に1を指定します。
 また半径の目安として、(なす角が0の)中心と円周上の点を結ぶ線分をgeom_segment()で描画しています。
 数式を表示する場合は、expression()の記法で指定します。

 原点を中心とする半径  r の円全体をx軸方向に  a、y軸方向に  b 移動したグラフになります。

 以上で、円を描画できました。

度数法と弧度法の関係

 最後に、度数法における角度と弧度法における角度(ラジアン)の関係をグラフで確認します。

グラフの作成

 度数法と弧度法の関係を角度目盛を表示したグラフで確認します。

・作図コード(クリックで展開)

 円を描画するためのデータフレームを作成します。

# 半径を指定
r <- 1

# 円周の座標を計算
circle_df <- tibble::tibble(
  theta = seq(from = 0, to = 2*pi, length.out = 601), # ラジアン
  x = r * cos(theta), 
  y = r * sin(theta)
)
circle_df
## # A tibble: 601 × 3
##     theta     x      y
##     <dbl> <dbl>  <dbl>
##  1 0      1     0     
##  2 0.0105 1.00  0.0105
##  3 0.0209 1.00  0.0209
##  4 0.0314 1.00  0.0314
##  5 0.0419 0.999 0.0419
##  6 0.0524 0.999 0.0523
##  7 0.0628 0.998 0.0628
##  8 0.0733 0.997 0.0732
##  9 0.0838 0.996 0.0837
## 10 0.0942 0.996 0.0941
## # … with 591 more rows

 「円の描画」のときと同様にして、円周の座標を計算します。ただし簡単のため、原点を中心とします。

 角度に関する目盛やラベルを描画するためのデータフレームを作成します。

# 半円の目盛の数(分母の値)を指定
denom <- 6

# 目盛の通し番号(分子の値)を作成
tick_vec <- seq(from = 0, to = 2*denom-1, by = 1)

# 角度目盛ラベルの描画用
rad_label_df <- tibble::tibble(
  theta_deg = tick_vec / denom * 180, # 度数法
  theta_rad = tick_vec / denom * pi, # 弧度法
  x = r * cos(theta_rad), 
  y = r * sin(theta_rad), 
  deg_label = paste0(theta_deg, "*degree"), # 度数法用ラベル
  rad_label = paste0("frac(", tick_vec, ", ", denom, ")~pi"), # 弧度法用ラベル
  angle_label = paste0(deg_label, "==", rad_label) # 度数法・弧度法の対応用ラベル
)
rad_label_df
## # A tibble: 12 × 7
##    theta_deg theta_rad         x         y deg_label  rad_label      angle_label
##        <dbl>     <dbl>     <dbl>     <dbl> <chr>      <chr>          <chr>      
##  1         0     0      1   e+ 0  0        0*degree   frac(0, 6)~pi  0*degree==…
##  2        30     0.524  8.66e- 1  5   e- 1 30*degree  frac(1, 6)~pi  30*degree=…
##  3        60     1.05   5   e- 1  8.66e- 1 60*degree  frac(2, 6)~pi  60*degree=…
##  4        90     1.57   6.12e-17  1   e+ 0 90*degree  frac(3, 6)~pi  90*degree=…
##  5       120     2.09  -5   e- 1  8.66e- 1 120*degree frac(4, 6)~pi  120*degree…
##  6       150     2.62  -8.66e- 1  5   e- 1 150*degree frac(5, 6)~pi  150*degree…
##  7       180     3.14  -1   e+ 0  1.22e-16 180*degree frac(6, 6)~pi  180*degree…
##  8       210     3.67  -8.66e- 1 -5   e- 1 210*degree frac(7, 6)~pi  210*degree…
##  9       240     4.19  -5.00e- 1 -8.66e- 1 240*degree frac(8, 6)~pi  240*degree…
## 10       270     4.71  -1.84e-16 -1   e+ 0 270*degree frac(9, 6)~pi  270*degree…
## 11       300     5.24   5   e- 1 -8.66e- 1 300*degree frac(10, 6)~pi 300*degree…
## 12       330     5.76   8.66e- 1 -5.00e- 1 330*degree frac(11, 6)~pi 330*degree…

 角度  \theta に関する軸目盛ラベルを  \frac{i}{n} \pi の形で表示することにします。1周  360^{\circ} 2 \pi なので、この例では、 i 0 から  2 n 未満の整数とします。 n は、半円における目盛の数に対応します。
  nn itick_vecとして値を作成します。

 度数法における角度を  \theta^{\circ} = 180^{\circ} \frac{i}{n} で計算してtheta_deg列、弧度法における角度を  \theta = \frac{i}{n} \pi で計算してtheta_rad列として、円周上の点の座標を計算します。

 theta_deg列やtick_vecを用いて、ラベル用の文字列を作成します。数式を表示する場合は、expression()の記法を用います。

 角マークを描画するためのデータフレームを作成します。

# 角マークの座標を計算
d <- 0.2
angle_mark_df <- tibble::tibble(
  theta = seq(from = 0, to = 1/denom*pi, length.out = 100), 
  x = d * cos(theta), 
  y = d * sin(theta)
)
angle_mark_df
## # A tibble: 100 × 3
##      theta     x       y
##      <dbl> <dbl>   <dbl>
##  1 0       0.2   0      
##  2 0.00529 0.200 0.00106
##  3 0.0106  0.200 0.00212
##  4 0.0159  0.200 0.00317
##  5 0.0212  0.200 0.00423
##  6 0.0264  0.200 0.00529
##  7 0.0317  0.200 0.00635
##  8 0.0370  0.200 0.00740
##  9 0.0423  0.200 0.00846
## 10 0.0476  0.200 0.00952
## # … with 90 more rows

 この例では、なす角  \theta を示すために、軸目盛1つ分の角マーク(小さい扇型)を表示することにします。
 そこで、角マーク用のラジアン  0 \leq \theta \leq \frac{\pi}{n} を作成して、円弧の座標を計算します。サイズの調整用の値(半径)をdとします。

 角ラベルを描画するためのデータフレームを作成します。

# 角ラベルの座標を計算
d <- 0.3
angle_label_df <- tibble::tibble(
  theta = 0.5 / denom * pi, 
  x = d * cos(theta), 
  y = d * sin(theta)
)
angle_label_df
## # A tibble: 1 × 3
##   theta     x      y
##   <dbl> <dbl>  <dbl>
## 1 0.262 0.290 0.0776

 角ラベルは、角マークの中点に表示することにします。
 そこで、角ラベル用のラジアンを  \theta = \frac{\pi}{2 n} として、点の座標を計算します。表示位置の調整用の値(原点からのノルム)をdとします。

 円周上に角度目盛を表示したグラフを作成します。

# 目盛ラベルの表示位置を指定
d <- 1.1

# グラフサイズ用の値を設定
axis_size <- r * d + 0.3

# 円周上の角度目盛を作図
ggplot() + 
  geom_path(data = circle_df, 
            mapping = aes(x = x, y = y), 
            size = 1) + # 円周
  geom_text(data = rad_label_df, 
            mapping = aes(x = x*d, y = y*d, label = angle_label, 
                          hjust = 1-(x/r*0.5+0.5), vjust = 1-(y/r*0.5+0.5)), parse = TRUE) + # 角度目盛ラベル
  geom_text(data = rad_label_df, 
            mapping = aes(x = x, y = y, angle = theta_deg+90), 
            label = "|", size = 2) + # 角度目盛指示線
  geom_segment(data = rad_label_df, 
               mapping = aes(x = 0, y = 0, xend = x, yend = y), 
               linetype = "dotted") + # 角度目盛グリッド
  geom_segment(mapping = aes(x = 0, y = 0, xend = r, yend = 0)) + # x軸上の半径
  geom_text(mapping = aes(x = 0.5*r, y = 0), 
            label = paste0("r==", r), parse = TRUE, 
            size = 5, hjust = 0.5, vjust = 0) + # 半径ラベル
  geom_path(data = angle_mark_df, 
            mapping = aes(x = x, y = y), 
            size = 0.5) + # 角マーク
  geom_text(data = angle_label_df, 
            mapping = aes(x = x, y = y), 
            label = "theta", parse = TRUE, 
            size = 5, hjust = 0.5, vjust = 0.5) + # 角ラベル
  coord_fixed(ratio = 1, 
              xlim = c(-axis_size, axis_size), ylim = c(-axis_size, axis_size)) + # 描画領域
  labs(title = "degree and radian", 
       subtitle = expression(theta*degree == frac(2*pi, 360) ~ theta), 
       #subtitle = expression(theta == frac(360, 2*pi) ~ theta*degree), 
       x = expression(x == r ~ cos~theta), 
       y = expression(y == r ~ sin~theta))

 目盛ラベルの表示位置の調整用の値をdとします。
 また、横・縦方向の表示位置の調整用の引数hjust, vjustを、x, y列の値を使って指定しています。 r \cos \theta, r \sin \theta (x, y列)は  -r から  r の値をとります。 r で割ると  -1 から  1 の値になり、さらに  0.5 を掛けると  -0.5 から  0.5 の値になり、 0.5 を足すと  0 から  1 の値になります。この値を  1 から引いた値を使うといい感じの表示位置になります。hjust, vjustを指定(こんな面倒な設定を)せずに、dを少し大きくしても同様の図になります。
 角度目盛の指示線を|で表示します。線の向きは角度列theta_degを90°回転させた方向です。

角度目盛

度数法と弧度法の対応関係

 度数法  \theta^{\circ} と弧度法  \theta は、 \theta = \frac{2 \pi}{360} \theta^{\circ} \theta^{\circ} = \frac{360}{2 \pi} \theta の関係です。つまり、 \theta^{\circ} = 0^{\circ} のとき  \theta = 0 \theta^{\circ} = 180^{\circ} のとき  \theta = \pi \theta^{\circ} = 360^{\circ} のとき  \theta = 2 \pi です。
 また、 \cos \theta = \cos (\theta + 2 \pi) \sin \theta = \sin (\theta + 2 \pi) なので、 2 \pi で1周期です。
 円の大きさ(半径)や中心の位置(座標)は角度に影響しません。

アニメーションの作成

 続いて、なす角と円周上の点の関係をアニメーションで確認します。

・作図コード(クリックで展開)

 フレームごとの角度を作成します。

# フレーム数を指定
frame_num <- 150

# フレームごとの角度を指定
theta_n <- seq(from = -2*pi, to = 2*pi, length.out = frame_num+1)[1:frame_num]

# フレームごとの角度ラベルを作成
frame_label_vec <- paste0(
  "θ° = ", round(theta_n/pi*180, digits = 1), "°, ", 
  "θ = ", round(theta_n/pi, digits = 2), "π"
)
head(theta_n); head(frame_label_vec)
## [1] "θ° = -360°, θ = -2π"      "θ° = -355.2°, θ = -1.97π"
## [3] "θ° = -350.4°, θ = -1.95π" "θ° = -345.6°, θ = -1.92π"
## [5] "θ° = -340.8°, θ = -1.89π" "θ° = -336°, θ = -1.87π"

 フレーム数frame_numを指定して、frame_num個の  \theta の値を等間隔に作成します。範囲を  2 \pi の倍数にしてframe_num + 1個の等間隔の値を作成して、最後の値を除くと繋がりの良いアニメーションになります。
 この例では、フレームごとの角度をグラフに表示するために、theta_nを用いた文字列をフレーム切替用のラベル列として使います。作図自体には不要な処理です。

 円周上の点を描画するためのデータフレームを作成します。

# フレームごとの円周上の点の座標を計算
anim_angle_point_df <- tibble::tibble(
  frame_i = 1:frame_num, # フレーム番号
  frame_label = factor(frame_label_vec, levels = frame_label_vec), # フレーム切替用ラベル
  theta = theta_n, 
  x = r * cos(theta), 
  y = r * sin(theta)
)
anim_angle_point_df
## # A tibble: 150 × 5
##    frame_i frame_label              theta     x        y
##      <int> <fct>                    <dbl> <dbl>    <dbl>
##  1       1 θ° = -360°, θ = -2π      -6.28 1     2.45e-16
##  2       2 θ° = -355.2°, θ = -1.97π -6.20 0.996 8.37e- 2
##  3       3 θ° = -350.4°, θ = -1.95π -6.12 0.986 1.67e- 1
##  4       4 θ° = -345.6°, θ = -1.92π -6.03 0.969 2.49e- 1
##  5       5 θ° = -340.8°, θ = -1.89π -5.95 0.944 3.29e- 1
##  6       6 θ° = -336°, θ = -1.87π   -5.86 0.914 4.07e- 1
##  7       7 θ° = -331.2°, θ = -1.84π -5.78 0.876 4.82e- 1
##  8       8 θ° = -326.4°, θ = -1.81π -5.70 0.833 5.53e- 1
##  9       9 θ° = -321.6°, θ = -1.79π -5.61 0.784 6.21e- 1
## 10      10 θ° = -316.8°, θ = -1.76π -5.53 0.729 6.85e- 1
## # … with 140 more rows

 フレーム番号を1からframe_numの整数として、フレームラベルframe_label_vecと合わせて格納します。どちらか1つの列があれば作図できます。
 また、フレームごとの角度theta_nを用いて、円周上の各点の座標を計算します。

 角マークを描画するためのデータフレームを作成します。

# フレームごとの角マークの座標を計算
d <- 0.15
anim_angle_mark_df <- tibble::tibble(
  frame_i = 1:frame_num, # フレーム番号
  frame_label = factor(frame_label_vec, levels = frame_label_vec), # フレーム切替用ラベル
) |> 
  dplyr::group_by(frame_i, frame_label) |> # ラジアンの作成用
  dplyr::summarise(
    theta = seq(from = 0, to = theta_n[frame_i], length.out = 100), .groups = "drop"
  ) |> # なす角以下のラジアンを作成
  dplyr::mutate(
    x = d * cos(theta), 
    y = d * sin(theta)
  )
anim_angle_mark_df
## # A tibble: 15,000 × 5
##    frame_i frame_label           theta     x        y
##      <int> <fct>                 <dbl> <dbl>    <dbl>
##  1       1 θ° = -360°, θ = -2π  0      0.15   0      
##  2       1 θ° = -360°, θ = -2π -0.0635 0.150 -0.00951
##  3       1 θ° = -360°, θ = -2π -0.127  0.149 -0.0190 
##  4       1 θ° = -360°, θ = -2π -0.190  0.147 -0.0284 
##  5       1 θ° = -360°, θ = -2π -0.254  0.145 -0.0377 
##  6       1 θ° = -360°, θ = -2π -0.317  0.143 -0.0468 
##  7       1 θ° = -360°, θ = -2π -0.381  0.139 -0.0557 
##  8       1 θ° = -360°, θ = -2π -0.444  0.135 -0.0645 
##  9       1 θ° = -360°, θ = -2π -0.508  0.131 -0.0729 
## 10       1 θ° = -360°, θ = -2π -0.571  0.126 -0.0811 
## # … with 14,990 more rows

 フレームごとにグループ化して、summarise()を使ってフレーム(角度)ごとに0からtheta_n[frame_i]までの値を作成して、円弧の座標を計算します。

 角ラベルを描画するためのデータフレームを作成します。

# フレームごとの角ラベルの座標を計算
d <- 0.2
anim_angle_label_df <- tibble::tibble(
  frame_i = 1:frame_num, # フレーム番号
  frame_label = factor(frame_label_vec, levels = frame_label_vec), # フレーム切替用ラベル
  theta = 0.5 * theta_n, 
  x = d * cos(theta), 
  y = d * sin(theta)
)
anim_angle_label_df
## # A tibble: 150 × 5
##    frame_i frame_label              theta      x         y
##      <int> <fct>                    <dbl>  <dbl>     <dbl>
##  1       1 θ° = -360°, θ = -2π      -3.14 -0.2   -2.45e-17
##  2       2 θ° = -355.2°, θ = -1.97π -3.10 -0.200 -8.38e- 3
##  3       3 θ° = -350.4°, θ = -1.95π -3.06 -0.199 -1.67e- 2
##  4       4 θ° = -345.6°, θ = -1.92π -3.02 -0.198 -2.51e- 2
##  5       5 θ° = -340.8°, θ = -1.89π -2.97 -0.197 -3.34e- 2
##  6       6 θ° = -336°, θ = -1.87π   -2.93 -0.196 -4.16e- 2
##  7       7 θ° = -331.2°, θ = -1.84π -2.89 -0.194 -4.97e- 2
##  8       8 θ° = -326.4°, θ = -1.81π -2.85 -0.191 -5.78e- 2
##  9       9 θ° = -321.6°, θ = -1.79π -2.81 -0.189 -6.58e- 2
## 10      10 θ° = -316.8°, θ = -1.76π -2.76 -0.186 -7.36e- 2
## # … with 140 more rows

 x軸の正の部分とのなす角の中点にラベルと配置するために、0.5 * theta_nを用いて円弧上の点の座標を計算します。

 フレームごとに角度を変化させたアニメーションを作成します。

# ラベルの表示位置を指定
d <- 1.1

# グラフサイズ用の値を設定
axis_size <- d + 0.3

# 角度と円周上の点のアニメーションを作図
anim <- ggplot() + 
  geom_path(data = circle_df, 
            mapping = aes(x = x, y = y), 
            size = 1) + # 円周
  geom_text(data = rad_label_df, 
            mapping = aes(x = x*d, y = y*d, label = angle_label, 
                          hjust = 1-(x*0.5+0.5), vjust = 1-(y*0.5+0.5)), parse = TRUE) + # 角度目盛ラベル
  geom_text(data = rad_label_df, 
            mapping = aes(x = x, y = y, angle = theta_deg+90), 
            label = "|", size = 2) + # 角度目盛指示線
  geom_segment(data = rad_label_df, 
               mapping = aes(x = 0, y = 0, xend = x, yend = y), 
               linetype = "dotted") + # 角度目盛グリッド
  geom_point(data = anim_angle_point_df, 
             mapping = aes(x = x, y = y), 
             size = 4) + # 円周上の点
  geom_segment(data = anim_angle_point_df, 
               mapping = aes(x = 0, y = 0, xend = x, yend = y), 
               size = 1) + # 原点と円周上の点の線分
  geom_segment(mapping = aes(x = 0, y = 0, xend = r, yend = 0), 
               size = 1) + # 正のx軸上の半径
  geom_text(mapping = aes(x = 0.5*r, y = 0), 
            label = "r", parse = TRUE, 
            size = 5, hjust = 0.5, vjust = -0.5) + # 半径ラベル
  geom_path(data = anim_angle_mark_df, 
            mapping = aes(x = x, y = y), 
            size = 0.5) + # 角マーク
  geom_text(data = anim_angle_label_df, 
            mapping = aes(x = x, y = y), 
            label = "theta", parse = TRUE, 
            size = 5, hjust = 0.5, vjust = 0.5) + # 角ラベル
  gganimate::transition_manual(frames = frame_label) + # フレーム
  coord_fixed(ratio = 1, 
              xlim = c(-axis_size, axis_size), ylim = c(-axis_size, axis_size)) + # 描画領域
  labs(title = "degree and radian", 
       subtitle = "{current_frame}", 
       x = expression(x == r ~ cos~theta), 
       y = expression(y == r ~ sin~theta))

# gif画像を作成
gganimate::animate(plot = anim, nframes = frame_num, fps = 100, width = 600, height = 600)

 gganimateパッケージを利用して、アニメーション(gif画像)を作成します。
 transition_manual()のフレーム制御の引数framesにフレームラベル列frame_label(またはフレーム番号列frame_i)を指定して、グラフを作成します。
 animate()plot引数にグラフオブジェクト、nframes引数にフレーム数frame_numを指定して、gif画像を作成します。また、fps引数に1秒当たりのフレーム数を指定できます。

度数法と弧度法の対応関係

 ラジアン(角度)  \theta が大きくなるほど円周上の点が反時計回りに移動するのが分かります。角度が負の値のときは時計回りの方向にできるなす角になります。

 この記事では、円を可視化しました。次の記事からは、三角関数(円関数)を可視化していきます。

おわりに

 最近Python版の記事を書いたこともあり、「三角関数の可視化」他の記事の中で書いていた内容をバージョンアップして独立させました。
 三角関数シリーズを中断して(途中で投げて)線形代数シリーズを書いていたら三角関数の内容が度々登場したので、再開のための準備運動がてら書きました。

 円周率は!3.14159265358979ということで、最後にこの曲をどうぞ。

 あり・をり・はべり・いまそかり♬

【次の内容】

www.anarchive-beta.com