Rプログラミング「軸」の全て:グラフ描画の基礎とエラー解決

2025-05-27

グラフを作成する際、データの値をそれぞれの軸に沿って配置し、視覚的に表現します。この軸を制御するための様々な機能や引数がRには用意されています。

  • 複数軸

    • Rのグラフィック機能では、メインのX軸とY軸以外に、二次的な軸(セカンダリ軸)を追加することも可能です。これにより、異なる単位のデータを同じグラフ上に表示するなどの複雑なグラフを作成できます。ggplot2では sec_axis などがこれにあたります。
  • 目盛りのラベル (Tick Labels)

    • 目盛りの横や下に表示される数値やカテゴリ名です。
    • cex.axislas などのグラフィカルパラメータ(par() 関数で設定)を使って、目盛りラベルの文字サイズや向きなどを調整できます。
  • 目盛り (Ticks)

    • 軸上に表示される小さな線で、データの値を読み取るための目印です。
    • 目盛りの位置や表示方法もカスタマイズ可能です。axis() 関数を使ったり、ggplot2scale_*_continuous() などで breaks 引数を設定することで制御できます。
  • 軸の範囲 (Axis Limits)

    • X軸の範囲は xlim、Y軸の範囲は ylim 引数を使って設定できます。例えば、plot(x, y, xlim = c(0, 100), ylim = c(0, 50)) のように使います。これにより、表示するデータの範囲を制限したり、特定の範囲に拡大・縮小して表示したりできます。
  • 軸ラベル (Axis Labels)

    • X軸には xlab、Y軸には ylab 引数を使って、軸のタイトルを設定できます。例えば、plot(x, y, xlab = "売上", ylab = "利益") のように使います。
    • ggplot2 のようなパッケージでは、labs() 関数や scale_x_continuous(), scale_y_continuous() などを使って軸ラベルを詳細に制御します。
  • 軸の表示・非表示

    • plot() 関数などの一部のグラフ描画関数では、axes = FALSE のように引数を設定することで、デフォルトで表示される軸を非表示にすることができます。
    • axis() 関数を使うと、軸を詳細にカスタマイズして追加することができます。例えば、どの位置に目盛りを表示するか、目盛りのラベルをどうするかなどを指定できます。


Rのグラフ描画では、plot()axis()ggplot2 などのパッケージを使って軸をカスタマイズしますが、意図しない表示になったりエラーが発生したりすることがあります。

軸が表示されない、または期待通りに表示されない

原因

  • axis() 関数の引数ミス
    axis() 関数を使う際に side (軸の位置) や at (目盛りの位置)、labels (目盛りラベル) の指定が間違っていると、軸が表示されないか、期待通りに表示されません。
  • par() 設定の影響
    par() 関数で mar (余白) や oma (外側の余白) などのグラフィカルパラメータを過度に小さく設定していると、軸ラベルや目盛りラベルが表示されなくなることがあります。
  • 軸のオーバーラップ
    複数のプロットを重ねる際に、後のプロットが前のプロットの軸を上書きしてしまうことがあります。
  • データ範囲と軸の範囲の不一致
    xlimylim で指定した軸の範囲が、実際のデータ範囲と大きくずれている場合、データが描画範囲外に出てしまい、軸だけが表示されるか、データが全く見えない状態になります。
  • axes = FALSE または xaxt = "n", yaxt = "n" の設定
    plot() 関数などで軸を意図的に非表示にしている場合があります。

解決策

  • ggplot2 の場合
    ggplot2 では通常、軸は自動的に生成されます。表示されない場合は、theme() 関数内で axis.text.x = element_blank()axis.title.y = element_blank() など、軸の要素を非表示にする設定がされていないか確認します。
  • 余白の調整
    par(mar = c(bottom, left, top, right))par(oma = c(bottom, left, top, right)) を使って、グラフの余白を十分に確保します。
  • axis() 関数で軸を再描画
    軸が消えてしまった場合は、plot() の後に axis() 関数を使って必要な軸を明示的に描画します。
    plot(1:10, type = "l", axes = FALSE) # 軸を非表示でプロット
    axis(1) # X軸を描画
    axis(2) # Y軸を描画
    
  • データ範囲と軸の範囲を調整
    xlimylim の値をデータに合わせて適切に設定します。必要であれば、range() 関数を使ってデータの最小値と最大値を取得し、それを元に範囲を設定します。
  • 軸の表示設定を確認
    plot() 関数を使用している場合は、axes = TRUE であるか、xaxtyaxt がデフォルトのままであるかを確認します。axis() 関数を使う場合は、plot(..., axes = FALSE) で軸を非表示にしてから axis() で手動で追加します。

目盛りや目盛りラベルの表示がおかしい

原因

  • 数値形式の不一致
    目盛りラベルが数値として認識されず、意図しない表示になることがあります。
  • 目盛りラベルが重なる
    特に日付や時間がX軸に表示される場合など、ラベルが長すぎて重なってしまうことがあります。
  • 目盛りの数が多すぎる/少なすぎる
    自動生成される目盛りがデータの特性に合っていない場合があります。

解決策

  • 目盛りラベルの回転
    par() 関数で las 引数を設定することで、目盛りラベルの向きを変更し、重なりを避けることができます(las = 0 (常に並行), las = 1 (常に水平), las = 2 (常に垂直), las = 3 (常に垂直))。
    plot(1:10, 1:10, xaxt = "n", yaxt = "n")
    axis(1, at = 1:10, labels = paste0("Item_", 1:10), las = 2) # X軸ラベルを垂直に
    
  • 目盛りラベルの書式設定
    labels 引数を使って、目盛りラベルの表示形式を調整します。sprintf()format() 関数が役立ちます。
  • 目盛りの位置を明示的に指定
    axis() 関数の at 引数を使って、目盛りを表示したい具体的な位置をベクトルで指定します。
    plot(rnorm(100))
    axis(side = 2, at = seq(-3, 3, by = 1), labels = c("-3", "-2", "-1", "0", "1", "2", "3"))
    

軸のタイトル(ラベル)が表示されない、または位置がおかしい

原因

  • title() 関数との競合
    plot() で軸ラベルを指定した後、title() 関数で再度設定しようとして上書きされる場合。
  • 余白の不足
    軸ラベルを表示するスペースが十分に確保されていない。
  • xlab / ylab 引数の指定ミス
    plot() 関数などで xlab = ""ylab = "" のように空文字列を指定している場合。

解決策

  • mtext() 関数を使用
    mtext() 関数を使うと、グラフの余白にテキスト(軸ラベルやタイトルなど)を自由に追加できます。
    plot(1:10, 1:10, xlab = "", ylab = "") # 軸ラベルなしでプロット
    mtext("X軸のタイトル", side = 1, line = 3) # 下にX軸タイトルを追加
    mtext("Y軸のタイトル", side = 2, line = 3) # 左にY軸タイトルを追加
    
  • 余白の調整
    par(mar = c(bottom, left, top, right)) を調整し、軸ラベル用のスペースを確保します。特にX軸ラベルが下部余白に収まらない場合やY軸ラベルが左部余白に収まらない場合に有効です。
  • xlab / ylab を適切に設定
    plot(x, y, xlab = "データX", ylab = "データY")
    

Error in plot.window(...) : need finite 'xlim' values または Error in plot.window(...) : need finite 'ylim' values

原因

  • データが空
    描画しようとしているデータが空のベクトルやデータフレームである場合。
  • データに NA (欠損値) や Inf (無限大) が含まれている
    xlimylim を自動的に決定しようとした際に、データ中に無限大や欠損値が含まれていると、Rが軸の範囲を決定できずエラーになります。

解決策

  • データが空でないか確認
    描画する変数が有効なデータを含んでいるか確認します。
  • 欠損値の処理
    グラフ描画前に na.omit()complete.cases() などを使って欠損値を取り除くか、xlimylim を手動で有限の値に設定します。
    data_with_na <- c(1, 2, NA, 4, 5)
    plot(na.omit(data_with_na)) # NAを除去してプロット
    # または
    plot(data_with_na, xlim = c(1, 5), ylim = c(0, 6)) # 範囲を手動で設定
    

Error in axis(...) : invalid 'at' values

原因

  • at の値が軸の範囲外
    指定した at の値が xlimylim で設定された軸の範囲外にある場合。
  • at 引数に数値以外の値が指定されている
    axis() 関数の at 引数には、目盛りの位置を示す数値ベクトルを指定する必要があります。文字列や因子型が指定されている場合に発生します。
  • at の値を軸の範囲内に調整
    xlimylim で指定した範囲と at の値が矛盾しないように調整します。
  • at には数値を指定
    at 引数に渡すベクトルが数値であることを確認します。必要であれば as.numeric() で型変換を行います。


Rの標準グラフィックシステムでの軸操作

plot() 関数と axis() 関数、mtext() 関数などを用いて軸をカスタマイズする例です。

基本的な軸の描画とラベル設定

# サンプルデータの生成
x <- 1:10
y <- x^2

# 基本的なプロット(軸とラベルは自動生成)
plot(x, y,
     main = "シンプルなグラフ", # グラフタイトル
     xlab = "X軸のデータ",     # X軸ラベル
     ylab = "Y軸のデータ"      # Y軸ラベル
     )

軸の非表示と手動での追加

plot() 関数で axes = FALSE とすると、軸が描画されなくなります。その後、axis() 関数を使って必要な軸だけを手動で追加できます。

# サンプルデータの生成
data_val <- rnorm(50, mean = 10, sd = 2)

# 軸を非表示にしてプロット
plot(data_val,
     main = "軸を非表示にしたプロットと手動追加",
     xlab = "", ylab = "", # デフォルトの軸ラベルも非表示に
     axes = FALSE,        # 軸を非表示
     frame.plot = TRUE    # グラフの枠線は残す
     )

# X軸(下側、目盛りは自動、ラベルはデフォルト)
axis(side = 1)

# Y軸(左側、目盛りは0から20まで2刻み、ラベルはカスタム)
axis(side = 2, at = seq(0, 20, by = 2),
     labels = paste0("値", seq(0, 20, by = 2))
     )

# X軸のカスタムラベルを追加
mtext("X軸のインデックス", side = 1, line = 3) # side=1: 下, line=3: 軸から3行目

# Y軸のカスタムラベルを追加
mtext("測定値", side = 2, line = 3) # side=2: 左, line=3: 軸から3行目

軸の範囲と目盛りのカスタマイズ

xlimylim で軸の表示範囲を制御し、at で目盛りの位置、labels で目盛りラベルを指定します。

# サンプルデータの生成
temperature <- c(20, 22, 25, 23, 21, 19, 18, 20, 24, 26)
day <- 1:10

# 軸の範囲とラベルをカスタマイズしたプロット
plot(day, temperature,
     main = "日ごとの気温変化",
     xlab = "観測日",
     ylab = "気温 (°C)",
     xlim = c(0, 11),  # X軸の範囲を0から11に設定
     ylim = c(15, 30), # Y軸の範囲を15から30に設定
     xaxt = "n",       # X軸のデフォルト目盛りを非表示
     yaxt = "n",       # Y軸のデフォルト目盛りを非表示
     type = "b",       # 点と線を両方描画
     pch = 19,         # 点の形
     col = "blue"      # 点と線の色
     )

# カスタムX軸(目盛りは1日おき、ラベルは"Day 1"のような形式)
axis(side = 1, at = day, labels = paste("Day", day))

# カスタムY軸(目盛りは5刻み、ラベルはそのまま)
axis(side = 2, at = seq(15, 30, by = 5))

# 目盛りラベルのテキストサイズを調整(オプション)
# par(cex.axis = 0.8) # これをplot()の前に設定すると、全体に適用される

目盛りラベルの回転(重なり回避)

長い目盛りラベルが重なるのを避けるために、las 引数でラベルの向きを変更できます。

# 長いカテゴリ名のデータ
categories <- c("非常に長いカテゴリ名1", "中程度のカテゴリ名2", "短い3", "さらに長いカテゴリ名4", "カテゴリ5")
values <- 1:5

# 目盛りラベルが重なる可能性のあるプロット
plot(values, type = "b",
     main = "X軸ラベルの回転",
     xaxt = "n", # X軸のデフォルト目盛りを非表示
     xlab = "", ylab = "値"
     )

# X軸ラベルを垂直に(las=2)
axis(side = 1, at = 1:length(categories), labels = categories, las = 2)

# X軸のタイトルを少し下に配置
mtext("カテゴリ", side = 1, line = 4.5)

ggplot2 はより柔軟で体系的なグラフ描画を提供します。軸の操作もレイヤーの概念で行われます。

基本的な軸ラベルとタイトル設定

# ggplot2の読み込み
library(ggplot2)

# サンプルデータフレーム
df <- data.frame(
  group = LETTERS[1:5],
  value = c(10, 15, 7, 20, 12)
)

# 基本的な棒グラフと軸ラベルの設定
ggplot(df, aes(x = group, y = value)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(
    title = "グループ別の値",    # グラフタイトル
    x = "グループ名",          # X軸ラベル
    y = "測定された値"         # Y軸ラベル
  ) +
  theme_minimal() # シンプルなテーマ

scale_x_continuous(), scale_y_continuous(), scale_x_discrete(), scale_y_discrete() を使って軸を詳細に制御します。

# サンプルデータフレーム
df_scatter <- data.frame(
  x = rnorm(100, mean = 50, sd = 10),
  y = rnorm(100, mean = 100, sd = 15)
)

# 散布図で軸の範囲と目盛りをカスタマイズ
ggplot(df_scatter, aes(x = x, y = y)) +
  geom_point(alpha = 0.7, color = "darkgreen") +
  labs(
    title = "散布図とカスタム軸",
    x = "測定X (単位: cm)",
    y = "測定Y (単位: kg)"
  ) +
  # X軸の設定
  scale_x_continuous(
    breaks = seq(20, 80, by = 10), # 目盛りの位置
    limits = c(20, 80),            # 軸の表示範囲
    name = "X軸の新しい名前"      # 軸タイトルをここで変更することも可能
  ) +
  # Y軸の設定
  scale_y_continuous(
    breaks = c(60, 80, 100, 120, 140),
    labels = c("低", "中低", "中央値", "中高", "高"), # 目盛りラベルをカスタム
    limits = c(50, 150)
  ) +
  theme_bw() # 白い背景のテーマ

目盛りラベルの回転と非表示

theme() 関数を使って軸のテキスト(目盛りラベル)の見た目を調整します。

# サンプルデータフレーム
df_long_names <- data.frame(
  product = c("非常に長い製品名A", "中程度の製品名B", "製品C", "超長い製品名D", "製品E"),
  sales = c(100, 150, 80, 200, 120)
)

# X軸ラベルを回転させる棒グラフ
ggplot(df_long_names, aes(x = product, y = sales)) +
  geom_bar(stat = "identity", fill = "salmon") +
  labs(title = "製品別売上", x = "製品名", y = "売上高") +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1), # X軸ラベルを45度回転、右揃え
    axis.text.y = element_text(size = 12),              # Y軸ラベルのフォントサイズ
    axis.title.x = element_text(vjust = -0.5),          # X軸タイトルを少し下に移動
    axis.title.y = element_text(angle = 90, vjust = 1.5) # Y軸タイトルを垂直にし、左に移動
  )

# 軸ラベルを完全に非表示にする例
ggplot(df_long_names, aes(x = product, y = sales)) +
  geom_bar(stat = "identity", fill = "lightgreen") +
  labs(title = "軸ラベル非表示の例") +
  theme(
    axis.text.x = element_blank(),  # X軸の目盛りラベルを非表示
    axis.title.x = element_blank(), # X軸のタイトルを非表示
    axis.ticks.x = element_blank(), # X軸の目盛りを非表示
    axis.line.x = element_blank(),  # X軸の線を非表示
    axis.text.y = element_blank(),  # Y軸の目盛りラベルを非表示
    axis.title.y = element_blank(), # Y軸のタイトルを非表示
    axis.ticks.y = element_blank(), # Y軸の目盛りを非表示
    axis.line.y = element_blank()   # Y軸の線を非表示
  )


latticeパッケージの使用

ggplot2が広く使われるようになる前から、Rには多変量データや条件付きプロットに特化した強力なグラフィックパッケージとして**lattice**がありました。latticeplot()とは異なる独自のグラフィックモデルを持っており、軸の自動調整やパネルごとのカスタマイズが可能です。

特徴

  • 独自の軸カスタマイズ
    axis引数にカスタム関数を渡すことで、目盛りの位置やラベルを細かく制御できます。
  • 一貫性のあるデザイン
    全てのパネルで軸のスケールやラベルが一貫するように設計されています。
  • 多変量データの可視化に強い
    coplot(条件付きプロット)のように、複数の変数に基づいてデータを分割し、それぞれのサブプロットに軸を自動で生成します。

コード例

# latticeパッケージの読み込み
library(lattice)

# irisデータセットを使用
# SpeciesごとにSepal.LengthとSepal.Widthをプロット
xyplot(Sepal.Length ~ Sepal.Width | Species, data = iris,
       main = "Lattice: Speciesごとの散布図",
       xlab = "Sepal.Width (cm)",
       ylab = "Sepal.Length (cm)",
       # 軸のカスタマイズ(例:Y軸の目盛りをカスタム)
       scales = list(y = list(at = c(4, 5, 6, 7, 8),
                               labels = c("4cm", "5cm", "6cm", "7cm", "8cm")),
                     x = list(at = c(2, 3, 4, 5)) # X軸の目盛りもカスタム可能
                     )
       )

この例では、scales引数を使ってY軸とX軸の目盛りの位置とラベルをカスタマイズしています。latticeは特に多数のカテゴリや条件でデータを比較する際に、軸の管理を効率化してくれます。

plotlyやshinydashboardなどインタラクティブグラフでの軸操作

静的なグラフだけでなく、近年ではインタラクティブなグラフの需要が高まっています。plotlyhighcharterなどのパッケージは、RのデータからJavaScriptベースのインタラクティブなグラフを生成します。これらのグラフでは、ユーザーがズームイン・ズームアウトしたり、軸の範囲を動的に変更したりすることが可能です。

特徴

  • Rコードでの初期設定
    Rコードで軸の初期範囲、タイトル、目盛りなどを設定し、それをベースにユーザーが操作できます。
  • ツールチップでの詳細表示
    軸上の特定の点にカーソルを合わせると、詳細な情報が表示されます。
  • 動的な軸の調整
    ユーザーがグラフを操作する際に、軸の範囲が自動的に変化します。

コード例(plotly):

# plotlyパッケージの読み込み
library(plotly)

# サンプルデータ
df_plotly <- data.frame(
  date = seq.Date(from = as.Date("2023-01-01"), by = "day", length.out = 100),
  value = cumsum(rnorm(100)) + 50
)

# plotlyでインタラクティブな時系列プロットを作成
plot_ly(df_plotly, x = ~date, y = ~value, type = "scatter", mode = "lines") %>%
  layout(title = "Plotly: インタラクティブな時系列データ",
         xaxis = list(title = "日付",
                      rangeslider = list(visible = T), # 軸の下に範囲スライダーを表示
                      rangeselector = list(             # 期間セレクターボタン
                        buttons = list(
                          list(count = 1, type = "month", label = "1ヶ月"),
                          list(count = 6, type = "month", label = "6ヶ月"),
                          list(count = 1, type = "year", label = "1年"),
                          list(type = "all", label = "全て")
                        )
                      )),
         yaxis = list(title = "値",
                      fixedrange = FALSE) # Y軸のズームを許可(デフォルトはTRUE)
         )

plotlyでは、layout()関数内でxaxisyaxisのリストを操作することで、軸のタイトル、範囲、そしてズームやパンといったインタラクティブな機能の有無を設定できます。特にrangesliderrangeselectorは、時系列データで特定期間を拡大表示する際に非常に便利です。

グラフィックデバイスと低レベル関数での軸の調整

特徴

  • ベクターグラフィック出力との相性
    PDFやSVGなどのベクター形式で出力する際に、細部の調整が可能です。
  • 描画順序の制御
    軸や目盛り、ラベルなどをどの順序で描画するかを完全に制御できます。
  • 究極の柔軟性
    Rのグラフィックシステムの最も根幹にアクセスするため、どんな複雑なグラフ表現も理論的には可能です。

コード例:カスタムのX軸とY軸に異なる目盛り間隔を設定

# サンプルデータ
data_points <- c(10, 12, 15, 18, 20, 25, 28, 30, 32, 35)

# まずは何も描画しないプロット領域を作成
plot(data_points, type = "n",
     main = "低レベル関数での軸カスタマイズ",
     xlab = "", ylab = "", # 軸ラベルも非表示
     axes = FALSE,        # 軸も非表示
     xlim = c(0.5, 10.5),
     ylim = c(8, 38)
     )

# グラフの枠線を描画
box()

# カスタムX軸(下側、偶数インデックスにのみ目盛りとラベル)
axis(side = 1, at = seq(2, 10, by = 2), labels = paste("データ点", seq(2, 10, by = 2)))

# カスタムY軸(左側、5刻みの目盛りとラベル)
axis(side = 2, at = seq(10, 35, by = 5), las = 1) # las=1でラベルを水平に

# X軸タイトルを配置
mtext("データ点のインデックス", side = 1, line = 3, cex = 1.2)
# Y軸タイトルを配置
mtext("観測値", side = 2, line = 3, cex = 1.2)

# データ点を描画
points(1:length(data_points), data_points, col = "red", pch = 16, cex = 1.5)
lines(1:length(data_points), data_points, col = "red", lty = 2) # 破線で接続

この例では、plot(type = "n", axes = FALSE) でグラフの領域だけを作成し、その後axis()mtext()points()lines()などの低レベル関数を組み合わせて、軸、ラベル、データ点を個別に描画しています。これにより、軸の目盛りの配置、ラベルの書式、グラフ要素の描画順序などを完全にコントロールできます。

Rで軸を操作する方法は、目的とするグラフの種類やカスタマイズの度合いによって多岐にわたります。

  • 究極のカスタマイズ性
    低レベルなグラフィック関数を直接使うことで、Rのグラフィック機能のすべてを制御できますが、コードはより複雑になります。
  • インタラクティブなグラフ
    plotlyなどのパッケージは、ユーザーが軸の範囲を動的に変更できるなど、データ探索に適しています。
  • 複雑な静的グラフや多変量データ
    ggplot2はレイヤー構造と一貫性のある文法で複雑なグラフも効率的に作成できます。latticeも特定のタイプのグラフ(条件付きプロットなど)で優れた代替手段となります。
  • 簡単な静的グラフ
    plot()xlab, ylab, xlim, ylim引数とaxis()関数が最も手軽で強力です。