0

I'm looking to make a stacked barchart with colors representing values from a separate data column as well as add an accurate color bar using just the base graphics in R. There is one other post about this but it is pretty disorganized and in the end doesn't help me answer my question.

# create reproducible data
d <- read.csv(text='Day,Location,Length,Amount
            1,4,3,1.1
            1,3,1,.32
            1,2,3,2.3
            1,1,3,1.1
            2,0,0,0
            3,3,3,1.8
            3,2,1,3.54
            3,1,3,1.1',header=T)

# colors will be based on values in the Amount column
v1 <- d$Amount
# make some colors based on Amount - normalized
z <- v1/max(v1)*1000
colrs <- colorRampPalette(c('lightblue','blue','black'))(1000)[z]

# create a 2d table of the data needed for plotting
tab <- xtabs(Length ~ Location + Day, d)
# create a stacked bar plot
barplot(tab,col=colrs,space=0)

# create a color bar
plotr::color.bar

This for sure produces a color coded stacked bar graph, but the colors do not represent the data accurately.

For Day 1, Locations 4 and 1 should be identical in color. Another example, the first and last entries in the Amount column are identical, but color of the top of the left column doesn't match the bottom of the right column.

Also, I found how to make a color bar on a different post and it uses the plotr::color.bar code, but plotr apparently isn't a package and I'm not sure how to carry on.

How can I get the colors to match the appropriate section and add an accurate color bar?

4

3 に答える 3

1

「かなり整理されていない」投稿が、 r で水平積み上げ棒グラフのスタイルで時系列プロットを作成する方法に対する私の答えではないことを願っています! 大丈夫です、悪気はありません。

このソリューションは、次のようにデータに適応させることができます。

## store data
df <- read.csv(text='Day,Location,Length,Amount\n1,4,3,1.1\n1,3,1,.32\n1,2,3,2.3\n1,1,3,1.1\n2,0,0,0\n3,3,3,1.8\n3,2,1,3.54\n3,1,3,1.1',header=T);

## extract bar segment lengths from Length and bar segment colors from a function of Amount, both stored in a logical matrix form
lengths <- xtabs(Length~Location+Day,df);
amounts <- xtabs(Amount~Location+Day,df);
colors <- matrix(colorRampPalette(c('lightblue','blue','black'))(1001)[amounts/max(amounts)*1000+1],nrow(amounts));

## transform lengths into an offset matrix to appease design limitation of barplot(). Note that colors will be flattened perfectly to accord with this offset matrix
lengthsOffset <- as.matrix(setNames(reshape(cbind(id=1:length(lengths),stack(as.data.frame(unclass(lengths)))),dir='w',timevar='ind')[-1],colnames(lengths)));
lengthsOffset[is.na(lengthsOffset)] <- 0;

## draw plot
barplot(lengthsOffset,col=colors,space=0,xlab='Day',ylab='Length');

オフセット積み上げ棒グラフ


ノート

  • あなたの質問では、「パーミル」形式に変換された8つの元の値を使用colrs <- colorRampPalette(c('lightblue','blue','black'))(1000)[z]してカラーベクトルを構築しようとしました。これには、要素の 1 つがゼロであり、有効なインデックス値ではないという点で、わずかな欠陥がありました。そのため、本来は 8 色である必要があるのに、7 色になっているのです。これをコードで修正し、1 ミリあたりの値に 1 を追加して 1001 色を生成しました。zAmountz
  • また、色の生成に関連して、8 つの色 (つまり、元の値ごとに 1 つ) を生成する代わりに、色の完全なマトリックスを生成して、マトリックス (コードで呼び出したもの)Amountを並列化しました。このカラー マトリックスは、の引数に渡されるカラー ベクトルとして実際に直接使用できます。これは、内部的に (少なくとも概念的には) ベクトルにフラット化され、引数に渡すオフセット バー セグメントの長さに対応するためです (次の注を参照してください)。lengthstabbarplot()colbarplot()height
  • 前述の記事で詳しく説明しているように、このソリューションの要は、バー セグメントの長さの「オフセット マトリックス」を作成し、隣接する列をゼロにして、セグメントごとに異なる色を割り当てることができるようにすることです。これをマトリックスlengthsOffsetから作成します。lengths
  • おそらく直感に反するかもしれませんが、height引数のインデックス値がbarplot()小さいほど下のセグメントとして描画され、その逆も同様です。つまり、端末でそのデータを印刷するときのテキスト表示は、棒グラフでの表示とは垂直方向に反転します。 . lengthsOffset逆の順序が必要な場合は、行列とベクトルを垂直に逆にすることができますがcolors、私のコードではこれを行っていません。

参考までに、すべてのデータ構造を次に示します。

df;
##   Day Location Length Amount
## 1   1        4      3   1.10
## 2   1        3      1   0.32
## 3   1        2      3   2.30
## 4   1        1      3   1.10
## 5   2        0      0   0.00
## 6   3        3      3   1.80
## 7   3        2      1   3.54
## 8   3        1      3   1.10
lengths;
##         Day
## Location 1 2 3
##        0 0 0 0
##        1 3 0 3
##        2 3 0 1
##        3 1 0 3
##        4 3 0 0
amounts;
##         Day
## Location    1    2    3
##        0 0.00 0.00 0.00
##        1 1.10 0.00 1.10
##        2 2.30 0.00 3.54
##        3 0.32 0.00 1.80
##        4 1.10 0.00 0.00
colors;
##      [,1]      [,2]      [,3]
## [1,] "#ADD8E6" "#ADD8E6" "#ADD8E6"
## [2,] "#4152F5" "#ADD8E6" "#4152F5"
## [3,] "#0000B3" "#ADD8E6" "#000000"
## [4,] "#8DB1EA" "#ADD8E6" "#0000FA"
## [5,] "#4152F5" "#ADD8E6" "#ADD8E6"
lengthsOffset;
##    1 2 3
## 1  0 0 0
## 2  3 0 0
## 3  3 0 0
## 4  1 0 0
## 5  3 0 0
## 6  0 0 0
## 7  0 0 0
## 8  0 0 0
## 9  0 0 0
## 10 0 0 0
## 11 0 0 0
## 12 0 0 3
## 13 0 0 1
## 14 0 0 3
## 15 0 0 0
于 2015-05-27T17:04:23.127 に答える
0

以下のコメントに基づいて:

library(ggplot2)
ggplot(d, aes(x = Day, y = Length)) + geom_bar(aes(fill = Amount, order = Location), stat = "identity") 
于 2015-05-27T15:29:19.810 に答える
0

これは色の定義に間違いがあったと思います.5つの場所があり、場所1には毎日要素がゼロであるため、色の1つが使用されないため、棒グラフには5色しか必要ありません.

修理:

colrs <- colorRampPalette(c('yellow', 'lightblue','blue','black', 'lightblue'))(5)

色ベクトルを固定した後の出力

グループ内の観測値が 0 であるため、「黄色」は描画されないことに注意してください (OP のサンプル データ)。

于 2015-05-27T15:45:30.313 に答える