web-dev-qa-db-ja.com

ggplot2:色を因子レベルに修正

私はggplot2でいくつかのプロットを作成する、より大きなプロジェクトに取り組んでいます。プロットは、いくつかの異なる目立たないカテゴリ(国、種、タイプなど)にわたっていくつかの異なる結果をプロットすることに関係しています。 Type = Aが常に赤で表示され、Type = Bが常に青で表示されるように、他の要素が存在するかどうかに関係なく、すべてのプロットにわたって、離散型の色へのマッピングを完全に修正したいと思います。私はscale_fill_manual()について知っています。手動で色の値を指定して、drop = FALSEこれは、未使用の因子レベルの処理に役立ちます。ただし、すべてのプロットは、正しい方法での因子の並べ替え、因子の並べ替えと一致する色値の並べ替え、未使用のレベルの削除などを処理するために、いくつかの手作業を必要とするため、これは非常に扱いにくいと感じます。

私が探しているのは、私が1回およびグローバルに因子レベルを特定の色(A =緑、B =青、C =赤、...)にマップして、プロットする方法です。私が好きなものは何でも、ggplotは正しい色を選びます。

ポイントを説明するためのコードを以下に示します。

# Full set with 4 categories
df1 <- data.frame(Value = c(40, 20, 10, 60), 
                  Type = c("A", "B", "C", "D"))

ggplot(df1, aes(x = Type, y = Value, fill = Type)) + geom_bar(stat = "identity")


# Colors change complete because only 3 factor levels are present
df2 <- data.frame(Value = c(40, 20, 60), 
                  Type = c("A", "B", "D"))

ggplot(df2, aes(x = Type, y = Value, fill = Type)) + geom_bar(stat = "identity")


# Colors change because factor is sorted differently
df3 <- data.frame(Value = c(40, 20, 10, 60), 
                  Type = c("A", "B", "C", "D"))
df3$Type <- factor(df3$Type, levels = c("D", "C", "B", "A"), ordered = TRUE)

ggplot(df3, aes(x = Type, y = Value, fill = Type)) + geom_bar(stat = "identity")
13
Chris

コードの繰り返しを回避するために、カスタムプロット関数(scale_fill_manualおよび適切なデフォルトの色を含む)を作成できます。

library(ggplot2)
custom_plot <- function(.data,
  colours = c("A" = "green", "B" = "blue", "C" = "red", "D" = "grey"))  {
  ggplot(.data, aes(x=Type, y=Value, fill= Type)) + geom_bar(stat="identity") +
   scale_fill_manual(values = colours)
}

df1 <- data.frame(Value=c(40, 20, 10, 60), Type=c("A", "B", "C", "D"))
df2 <- data.frame(Value=c(40, 20, 60), Type=c("A", "B", "D"))
df3 <- data.frame(Value=c(40, 20, 10, 60), Type=c("A", "B", "C", "D"))
df3$Type <- factor(df3$Type, levels=c("D", "C", "B", "A"), ordered=TRUE)

custom_plot(df1)
custom_plot(df2)
custom_plot(df3)

必要に応じて、独自のカスタムスケールを定義できます。 scale_fill_manualのソースを見ると、

scale_fill_manual
#> function (..., values) 
#> {
#>     manual_scale("fill", values, ...)
#> }
#> <environment: namespace:ggplot2>

実際には非常に簡単です。

library(ggplot2)

scale_fill_chris <- function(...){
    ggplot2:::manual_scale(
        'fill', 
        values = setNames(c('green', 'blue', 'red', 'orange'), LETTERS[1:4]), 
        ...
    )
}

df1 <- data.frame(Value = c(40, 20, 10, 60), 
                  Type = c("A", "B", "C", "D"))

ggplot(df1, aes(x = Type, y = Value, fill = Type)) + 
    geom_col() + 
    scale_fill_chris()

df2 <- data.frame(Value = c(40, 20, 60), 
                  Type = c("A", "B", "D"))

ggplot(df2, aes(x = Type, y = Value, fill = Type)) + 
    geom_col() + 
    scale_fill_chris()

df3 <- data.frame(Value = c(40, 20, 10, 60), 
                  Type = c("A", "B", "C", "D"))
df3$Type <- factor(df3$Type, levels = c("D", "C", "B", "A"), ordered = TRUE)

ggplot(df3, aes(x = Type, y = Value, fill = Type)) + 
    geom_col() + 
    scale_fill_chris()

13
alistaire