web-dev-qa-db-ja.com

yスケールが既にある場合は、ggplot2軸ラベルをコンマ(およびK?MM?)でフォーマットします

Ggplotグラフのy軸ラベルのコストと収益(両方とも数千)とインプレッション(数百万)データをフォーマットしようとしています。

私のプロットは31日前から「昨日」まで実行され、ylim(c(min,max))オプションにその期間の最小値と最大値を使用します。コストの例を示すだけで、

_library(ggplot2)
library(TTR)

set.seed(1984)

#make series
start <- as.Date('2016-01-01')
end <- Sys.Date()

days <- as.numeric(end - start)

#make cost and moving averages
cost <- rnorm(days, mean = 45400, sd = 11640)
date <- seq.Date(from = start, to = end - 1, by = 'day') 
cost_7 <- SMA(cost, 7)
cost_30 <- SMA(cost, 30)

df <- data.frame(Date = date, Cost = cost, Cost_7 = cost_7, Cost_30 = cost_30)


# set parameters for window
left <- end - 31
right <- end - 1

# plot series
ggplot(df, aes(x = Date, y = Cost))+
geom_line(lwd = 0.5) +
geom_line(aes(y = Cost_7), col = 'red', linetype = 3, lwd = 1) +
geom_line(aes(y = Cost_30), col = 'blue', linetype = 5, lwd = 0.75) +
xlim(c(left, right)) + 
ylim(c(min(df$Cost[df$Date > left]), max(df$Cost[df$Date > left]))) +
xlab("")
_

ggplot output

私は、a)y軸上で数千と数百万をコンマで表したい、b)短縮された数字のように、数千を表す「K」または数百万を表す「MM」を表します。私は、b)高い注文かもしれませんが、今のところa)では達成できないことを理解しています

ggplot(...) + ... + ylim(c(min, max)) + scale_y_continuous(labels = comma)

次のエラーがスローされるため:

_## Scale for 'y' is already present. Adding another scale for 'y', which
## will replace the existing scale.
_

scale_y_continuous(labels = comma)セクションをgeom_line() layerの後(上記のエラーをスローします)またはすべてのggplotレイヤーの最後に配置しようとしました。これはylimの制限を上書きしますとにかく、呼び出してから上記のエラーをスローします。

何か案は?

22
d8aninja

コンマ形式の場合、_label=comma_のscalesライブラリを含める必要があります。 ylimと_scale_y_continuous_の両方を使用したため、説明した「エラー」は実際には単なる警告です。 2番目の呼び出しは最初の呼び出しをオーバーライドします。代わりに、_scale_y_continuous_の1回の呼び出しで制限を設定し、カンマ区切りのラベルを指定できます。

_library(scales)

ggplot(df, aes(x = Date, y = Cost))+
  geom_line(lwd = 0.5) +
  geom_line(aes(y = Cost_7), col = 'red', linetype = 3, lwd = 1) +
  geom_line(aes(y = Cost_30), col = 'blue', linetype = 5, lwd = 0.75) +
  xlim(c(left, right)) + 
  xlab("") +
  scale_y_continuous(label=comma, limits=c(min(df$Cost[df$Date > left]), 
                                           max(df$Cost[df$Date > left])))
_

別のオプションは、プロットする前にデータを長い形式に溶かすことです。これにより、必要なコードの量が減り、美的なマッピングが合理化されます。

_library(reshape2)

ggplot(melt(df, id.var="Date"), 
       aes(x = Date, y = value, color=variable, linetype=variable))+
  geom_line() +
  xlim(c(left, right)) + 
  labs(x="", y="Cost") +
  scale_y_continuous(label=comma, limits=c(min(df$Cost[df$Date > left]), 
                                           max(df$Cost[df$Date > left])))
_

いずれにしても、y値を千または百万単位で表すには、y値を1,000または1,000,000で除算できます。以下でdollar_format()を使用しましたが、_unit_format_(@joranの提案による)を使用する場合は、適切な10の累乗で除算する必要もあると思います。例えば:

_div=1000

ggplot(melt(df, id.var="Date"), 
       aes(x = Date, y = value/div, color=variable, linetype=variable))+
  geom_line() +
  xlim(c(left, right)) + 
  labs(x="", y="Cost (Thousands)") +
  scale_y_continuous(label=dollar_format(),
                     limits=c(min(df$Cost[df$Date > left]), 
                              max(df$Cost[df$Date > left]))/div)
_

必要に応じて、_scale_color_manual_および_scale_linetype_manual_を使用して、カスタムの色と線種を設定します。

enter image description here

28
eipi10