HOWTO · R
R の ggplot2 で軸の目盛りラベルを変更する方法
ggplot2 の離散軸と連続軸で目盛りラベルを変更・整形し、長いラベルの重なりを回避する方法を説明します。
因子または文字列の目盛り名には scale_x_discrete(labels = ...)、数値の目盛り位置と書式には scale_x_continuous(breaks = ..., labels = ...) を使います。回転などの見た目は theme(axis.text.x = element_text(...)) で調整します。軸タイトルを変える labs(x = ...) は目盛りラベルとは別です。縦軸では各関数の x を y に置き換えます。
例には R と ggplot2 が必要で、連続軸の書式設定には scales も使います。動作確認環境は R 4.1.2、ggplot2 3.3.5、scales 1.1.1 です。ここで使うスケール引数は現行 ggplot2 にもありますが、テーマの細部はバージョンによって異なることがあります。
| 目的 | ggplot2 の指定 |
|---|---|
| 軸タイトルを変える | labs(x = "Title") または labs(y = "Title") |
| 因子・文字列の目盛り名を変える | scale_x_discrete(labels = ...) |
| 数値の目盛り位置と文字列を指定する | scale_x_continuous(breaks = ..., labels = ...) |
| 目盛り文字列を回転・装飾する | theme(axis.text.x = element_text(...)) |
Date 軸を書式設定する |
scale_x_date(breaks = ..., labels = ...) |
基準となる ggplot2 グラフを作成する
各変更を比較しやすいように、小さなデータフレームを共通して使います。plan は因子なので x 軸は離散スケール、数値の orders は連続 y スケールになります。
library(ggplot2)
plan_sales <- data.frame(
plan = factor(
c("starter", "standard", "premium", "enterprise"),
levels = c("starter", "standard", "premium", "enterprise")
),
orders = c(180, 250, 210, 140)
)
base_plot <- ggplot(plan_sales, aes(x = plan, y = orders)) +
geom_col(fill = "#2c7fb8", width = 0.7) +
labs(x = "Plan", y = "Orders") +
theme_minimal(base_size = 16)
base_plot
ggsave(
"ggplot-default-axis-tick-labels.png",
plot = base_plot, width = 7.4, height = 4.82, dpi = 100, bg = "white"
)
x 軸には保存済みの 4 つの因子値、y 軸には自動選択された数値の目盛りが表示されます。labs(x = "Plan") は軸タイトルの「Plan」を設定しますが、starter などの目盛り文字列は変えません。
スケールを選ぶ前に、見た目で推測せず変数を確認します。str(plan_sales$plan) は因子、str(plan_sales$orders) は数値ベクトルと報告します。"1"、"2" のような数字を含む因子も離散型で、値が数個しかない数値列も連続型です。型の変更は、その型が値の意味に合う場合だけ行います。
離散軸の目盛りラベルと順序を変更する
離散スケールでは breaks と labels を対にします。breaks は表示する目盛りに対応するデータ値を選び、labels は表示文字列を与えます。両方を明示すれば、順序が変わったときの誤対応を防げます。
次の例はデータのコピーで因子レベルを安全に変え、同じ並びを breaks に渡します。名前付きベクトルなので、実行前でも対応が明確です。
plan_order <- c("premium", "standard", "starter", "enterprise")
plan_names <- c(
premium = "Premium",
standard = "Standard",
starter = "Starter",
enterprise = "Enterprise"
)
ordered_sales <- plan_sales
ordered_sales$plan <- factor(ordered_sales$plan, levels = plan_order)
discrete_plot <- ggplot(ordered_sales, aes(x = plan, y = orders)) +
geom_col(fill = "#2c7fb8", width = 0.7) +
scale_x_discrete(
breaks = plan_order,
labels = plan_names[plan_order]
) +
labs(x = "Plan", y = "Orders") +
theme_minimal(base_size = 16)
discrete_plot
ggsave(
"ggplot-discrete-axis-tick-labels.png",
plot = discrete_plot, width = 7.4, height = 4.82, dpi = 100, bg = "white"
)
表示順は Premium、Standard、Starter、Enterprise です。小文字のデータ値は変わらず、表示だけが変わります。同じ規則を全目盛りに適用するなら、scale_x_discrete(labels = abbreviate) のようなラベル関数も使えます。これはブレーク値を base R の abbreviate() に渡します。独自の function(x) は、入力と同じ長さの文字ベクトルを返す必要があります。
既存順序のまま名前だけ変えるなら、breaks を省略して c(starter = "Starter", standard = "Standard", premium = "Premium", enterprise = "Enterprise") のような名前付きベクトルを渡せます。表示集合と順序の両方が要件なら、上のように明示的に対で指定する方法が確実です。フィルタ後は x 軸を左から読み、ここに示した順序と照合してください。
breaks と limits は同じではありません。離散軸の breaks は受け入れるカテゴリを変えず、表示する目盛りだけを選びます。limits は許可する値と順序を定義し、範囲外の値を欠損値にするため、geom_col() が該当行を警告付きで除くことがあります。順序がデータ上の意味なら因子レベルを変更し、limits は意図的な除外にだけ使います。
連続軸の目盛り位置と書式を設定する
数値軸には連続スケールを使います。位置を breaks に、対応する文字列または書式設定関数を labels に渡します。値が変わる場合は、ggplot2 が最終ブレーク値で呼び出す関数の方が安全です。
次の散布図は馬力の目盛りを 100、200、300 に置き、scales::label_number() で単位を付けます。関数を直接呼ぶことで、描画前に文字列も確認できます。
hp_breaks <- c(100, 200, 300)
hp_formatter <- scales::label_number(suffix = " hp", accuracy = 1)
hp_formatter(hp_breaks)
continuous_plot <- ggplot(mtcars, aes(x = hp, y = mpg)) +
geom_point(size = 3, color = "#d95f0e") +
scale_x_continuous(
breaks = hp_breaks,
labels = hp_formatter
) +
labs(x = "Engine power", y = "Fuel economy (mpg)") +
theme_minimal(base_size = 16)
continuous_plot
ggsave(
"ggplot-continuous-axis-tick-labels.png",
plot = continuous_plot, width = 7.4, height = 4.82, dpi = 100, bg = "white"
)
[1] "100 hp" "200 hp" "300 hp"
x 軸にはこの 3 つだけが表示されます。数値 y 軸では scale_y_continuous() を使います。scales の別の関数なら桁区切り、割合、通貨なども表示でき、データ自体は数値のままです。
位置自体に意味があるときは明示的な breaks が適切です。書式だけが重要なら breaks を省略し、ggplot2 に位置を選ばせます。単位を付けるために数値列を文字列化すると、辞書順になって数値間隔を失う可能性があります。書式設定関数なら計算や点の位置を変えません。
Date は別の型です。列が Date を継承するなら、数値・離散スケールへ無理に通さず scale_x_date() または y 軸版を使います。日付対応の指定になりますが、breaks と labels の役割は同じです。
重なった目盛りラベルを回転する
内容の変更とスタイルの変更は別です。文字列が正しくても重なるならスケールは保ち、axis.text.x を調整します。angle = 35 は回転角、hjust = 1 は右端を目盛り位置に合わせる指定です。base_size = 18 で基本の文字サイズを大きくすると、グラフを狭く表示したときも読みやすさを保てます。
channel_sales <- data.frame(
channel = c(
"North America Online",
"Europe Retail Stores",
"Asia Pacific Partners",
"Latin America Direct"
),
orders = c(260, 220, 195, 150)
)
rotated_plot <- ggplot(channel_sales, aes(x = channel, y = orders)) +
geom_col(fill = "#31a354", width = 0.65) +
labs(x = "Sales channel", y = "Orders") +
theme_minimal(base_size = 18) +
theme(
axis.text.x = element_text(angle = 35, hjust = 1, vjust = 1)
)
rotated_plot
ggsave(
"ggplot-rotated-axis-tick-labels.png",
plot = rotated_plot, width = 7.4, height = 4.82, dpi = 100, bg = "white"
)
回転してもカテゴリ名はすべて残ります。まだ重なるなら、急角度にするより文言を短くするかグラフを広げる方が読みやすいことがあります。検証済みの ggplot2 3.3.5 では scale_x_discrete(guide = guide_axis(n.dodge = 2)) で離散ラベルを 2 段にずらせ、この関数は現行 API にもあります。水平文字を保てますが縦の空間を使います。詳しくはbase R または ggplot2 で軸ラベルを回転する方法を参照してください。
ラベル、目盛り線、ブレークを意図的に隠す
同義として扱わず、消したい要素に合う指定を選びます。
control_plot <- base_plot +
theme_classic(base_size = 16)
labels_hidden <- control_plot +
theme(axis.text.x = element_blank())
ticks_hidden <- control_plot +
theme(axis.ticks.x = element_blank())
breaks_hidden <- control_plot +
scale_x_discrete(breaks = NULL)
control_plot の theme_classic() は短い目盛り線を描くので比較できます。labels_hidden は x 軸文字列だけ、ticks_hidden は短い目盛り線だけを消し、後者ではカテゴリ名が残ります。breaks_hidden は主要 x ブレークを生成せず、それに結び付くラベルと目盛り線を消します。どれも plan_sales の行を除きません。
labels = NULL はブレーク位置を残してラベルを抑制します。スケール定義として非表示にするならこれを使い、特定テーマで描画しないだけなら element_blank() を使います。カテゴリが重要なら、隠したラベルの代わりに直接注釈や別のキーを用意します。
この 3 オブジェクトはコードと説明の方が比較しやすいため画像にしていません。R コンソールで ticks_hidden を表示し、control_plot と比べてください。3 つとも棒と高さは変わらず軸ガイドだけが異なります。図形が変わったり行削除警告が出たりしたら、テーマではなく別の limits 呼び出しを調べます。
誤った、または欠けた目盛りラベルを直す
連続値を離散スケールに渡した、または逆方向のエラーなら、str() で列を確認します。因子・文字列には離散、数値には連続、Date・日時には対応する日付スケールを使います。エラーを消すだけでなく、値の意味に合うときだけ型を変えます。
labels が文字ベクトルなら、明示的な breaks と対にし、長さを同じにします。そうしないと、フィルタ、並べ替え、カテゴリ追加後にずれることがあります。plan_names のような名前付き対応は保存値と表示名の関係を示し、一律変換なら関数が長さの問題を避けます。
棒の欠落や行削除警告は labels より limits が原因のことがあります。データ値が範囲から漏れていないか確認し、表示目盛り数だけを減らすなら breaks を使います。ズームや範囲指定は、目盛りのブレークと混同せずに ggplot2 の軸範囲を設定する方法を参照してください。
最後に、変更対象が軸タイトルではないか確認します。labs(x = "Plan") と x スケールの name はタイトルを、labels は目盛り文字列を設定します。役割を分ければ、タイトルだけ変わってカテゴリや数値が変わらない混乱を防げます。
通常はマッピングしたデータ型に合うスケールを選び、正確な文字列には breaks と labels を対にし、見た目だけを theme() に任せます。これにより観測値を保ったまま予測可能に軸を変更できます。