19

いくつかのカテゴリでデータの hexbin 表現を作成しようとしています。問題は、これらのビンをファセットすると、すべてのビンが異なるサイズになるように見えることです。

set.seed(1) #Create data
bindata <- data.frame(x=rnorm(100), y=rnorm(100))
fac_probs <- dnorm(seq(-3, 3, length.out=26))
fac_probs <- fac_probs/sum(fac_probs)
bindata$factor <- sample(letters, 100, replace=TRUE, prob=fac_probs)

library(ggplot2) #Actual plotting
library(hexbin)

ggplot(bindata, aes(x=x, y=y)) +
  geom_hex() +
  facet_wrap(~factor)

ここに画像の説明を入力

これらすべてのビンを物理的に同じサイズにするために何かを設定することは可能ですか?

4

4 に答える 4

19

Julius が言うように、問題はhexGrobbin サイズに関する情報を取得せず、 facet 内で見つかった違いから推測することです。

六角形の幅と高さdxを持たないことは、半径を指定せずに中心で円を指定するようなものです。dyhexGrob

回避策:

回避策

resolutionファセットに x と y の両方が異なる 2 つの隣接する六角形が含まれている場合、この戦略は機能します。したがって、回避策として、セルの x と y の中心座標、およびファセットとカウントの係数を含む data.frame を手動で作成します。

質問で指定されたライブラリに加えて、必要になります

library (reshape2)

また、bindata$factor実際には要因である必要があります。

bindata$factor <- as.factor (bindata$factor)

次に、基本的な六角形グリッドを計算します

h <- hexbin (bindata, xbins = 5, IDs = TRUE, 
             xbnds = range (bindata$x), 
             ybnds = range (bindata$y))

次に、に応じてカウントを計算する必要があります。bindata$factor

counts <- hexTapply (h, bindata$factor, table)
counts <- t (simplify2array (counts))
counts <- melt (counts)
colnames (counts)  <- c ("ID", "factor", "counts")

セル ID があるので、この data.frame を適切な座標とマージできます。

hexdf <- data.frame (hcell2xy (h),  ID = h@cell)
hexdf <- merge (counts, hexdf)

data.frame は次のようになります。

> head (hexdf)
  ID factor counts          x         y
1  3      e      0 -0.3681728 -1.914359
2  3      s      0 -0.3681728 -1.914359
3  3      y      0 -0.3681728 -1.914359
4  3      r      0 -0.3681728 -1.914359
5  3      p      0 -0.3681728 -1.914359
6  3      o      0 -0.3681728 -1.914359

ggplotting (以下のコマンドを使用) これにより正しいビン サイズが得られますが、図の外観は少し奇妙です。描画を抑制するには、そこにカウントを設定しNAて、na.value完全に透明にします (デフォルトは gray50 です)。

hexdf$counts [hexdf$counts == 0] <- NA

ggplot(hexdf, aes(x=x, y=y, fill = counts)) +
  geom_hex(stat="identity") +
  facet_wrap(~factor) +
  coord_equal () +
  scale_fill_continuous (low = "grey80", high = "#000040", na.value = "#00000000")

投稿の上部に図が表示されます。

この戦略は、ビン幅がファセットなしで正しい限り機能します。ビン幅が非常に小さく設定されているresolution場合でも、 は大きすぎdxdy. その場合、hexGrob2 つの隣接するビン (ただし、x と y の両方が異なる)NAに各ファセットのカウントを指定できます。

dummy <- hgridcent (xbins = 5, 
                    xbnds = range (bindata$x),  
                    ybnds = range (bindata$y),  
                    shape = 1)

dummy <- data.frame (ID = 0,
                     factor = rep (levels (bindata$factor), each = 2),
                     counts = NA,
                     x = rep (dummy$x [1] + c (0, dummy$dx/2), 
                              nlevels (bindata$factor)),
                     y = rep (dummy$y [1] + c (0, dummy$dy  ), 
                              nlevels (bindata$factor)))

このアプローチのもう 1 つの利点は、既に 0 カウントのすべての行を削除できることです。この場合、 のサイズを約 3/4 (520 行ではなく 122 行)counts減らします。hexdf

counts <- counts [counts$counts > 0 ,]
hexdf <- data.frame (hcell2xy (h),  ID = h@cell)
hexdf <- merge (counts, hexdf)
hexdf <- rbind (hexdf, dummy)

プロットは上記とまったく同じように見えますが、na.value完全に透明でなくても違いを視覚化できます。


問題の詳細

この問題はファセットに固有のものではありませんが、占有されているビンが少なすぎて、「斜めに」隣接するビンが取り込まれない場合に常に発生します。

問題を示す一連の最小限のデータを次に示します。

最初にhexBin、同じ六角形グリッドのすべての中心座標とggplot2:::hexBinによって返されるオブジェクトを取得するようにトレースしhexbinます。

trace (ggplot2:::hexBin, exit = quote ({trace.grid <<- as.data.frame (hgridcent (xbins = xbins, xbnds = xbnds, ybnds = ybnds, shape = ybins/xbins) [1:2]); trace.h <<- hb}))

非常に小さなデータ セットを設定します。

df <- data.frame (x = 3 : 1, y = 1 : 3)

そしてプロット:

p <- ggplot(df, aes(x=x, y=y)) +  geom_hex(binwidth=c(1, 1)) +          
     coord_fixed (xlim = c (0, 4), ylim = c (0,4))

p # needed for the tracing to occur
p + geom_point (data = trace.grid, size = 4) + 
    geom_point (data = df, col = "red") # data pts

str (trace.h)

Formal class 'hexbin' [package "hexbin"] with 16 slots
  ..@ cell  : int [1:3] 3 5 7
  ..@ count : int [1:3] 1 1 1
  ..@ xcm   : num [1:3] 3 2 1
  ..@ ycm   : num [1:3] 1 2 3
  ..@ xbins : num 2
  ..@ shape : num 1
  ..@ xbnds : num [1:2] 1 3
  ..@ ybnds : num [1:2] 1 3
  ..@ dimen : num [1:2] 4 3
  ..@ n     : int 3
  ..@ ncells: int 3
  ..@ call  : language hexbin(x = x, y = y, xbins = xbins, shape = ybins/xbins, xbnds = xbnds, ybnds = ybnds)
  ..@ xlab  : chr "x"
  ..@ ylab  : chr "y"
  ..@ cID   : NULL
  ..@ cAtt  : int(0) 

データ ポイント 2 を除外して、プロットを繰り返します。

p <- ggplot(df [-2,], aes(x=x, y=y)) +  geom_hex(binwidth=c(1, 1)) +          coord_fixed (xlim = c (0, 4), ylim = c (0,4))
p
p + geom_point (data = trace.grid, size = 4) + geom_point (data = df, col = "red")
str (trace.h)

Formal class 'hexbin' [package "hexbin"] with 16 slots
  ..@ cell  : int [1:2] 3 7
  ..@ count : int [1:2] 1 1
  ..@ xcm   : num [1:2] 3 1
  ..@ ycm   : num [1:2] 1 3
  ..@ xbins : num 2
  ..@ shape : num 1
  ..@ xbnds : num [1:2] 1 3
  ..@ ybnds : num [1:2] 1 3
  ..@ dimen : num [1:2] 4 3
  ..@ n     : int 2
  ..@ ncells: int 2
  ..@ call  : language hexbin(x = x, y = y, xbins = xbins, shape = ybins/xbins, xbnds = xbnds, ybnds = ybnds)
  ..@ xlab  : chr "x"
  ..@ ylab  : chr "y"
  ..@ cID   : NULL
  ..@ cAtt  : int(0) 

すべて順調 六角形のプロットがめちゃくちゃ

  • の結果が同じグリッド上にあることに注意してくださいhexbin(セル番号は変更されませんでした。セル 5 だけが入力されていないため、リストされていません)。グリッドの寸法と範囲は変更されていません。しかし、プロットされた六角形は劇的に変化しました。

  • hgridcentまた、最初のセル (左下) の中心座標を返すのを忘れていることに注意してください。

移入されますが:

df <- data.frame (x = 1 : 3, y = 1 : 3)

p <- ggplot(df, aes(x=x, y=y)) +  geom_hex(binwidth=c(0.5, 0.8)) +          
     coord_fixed (xlim = c (0, 4), ylim = c (0,4))

p # needed for the tracing to occur
p + geom_point (data = trace.grid, size = 4) + 
    geom_point (data = df, col = "red") + # data pts
    geom_point (data = as.data.frame (hcell2xy (trace.h)), shape = 1, size = 6)

すべてめちゃくちゃ

ここで、六角形のレンダリングが正しくない可能性があります。それらは 1 つの六角形グリッドに属していません。

于 2013-01-29T15:58:27.037 に答える
12

格子を使用して同じデータセットでソリューションを複製しようとしましたhexbinplot。最初は、エラーが発生しましたxbnds[1] < xbnds[2] is not fulfilled。このエラーは、ビニングでカバーする必要がある値の範囲を指定する数値ベクトルが間違っていることが原因でした。でこれらの引数を変更したhexbinplotところ、何とか機能しました。ggplot で解決するのに役立つかどうかはわかりませんが、おそらくいくつかの出発点です。

library(lattice)
library(hexbin)
hexbinplot(y ~ x | factor, bindata, xbnds = "panel", ybnds = "panel", xbins=5, 
           layout=c(7,3))

ここに画像の説明を入力

編集

長方形のビンはstat_bin2d()問題なく動作しますが:

ggplot(bindata, aes(x=x, y=y, group=factor)) + 
    facet_wrap(~factor) +
    stat_bin2d(binwidth=c(0.6, 0.6))

ここに画像の説明を入力

于 2013-01-26T19:58:38.580 に答える
5

関心のある 2 つのソース ファイルがあります: stat-binhex.rgeom-hex.rで、主hexBinhexGrob関数です。

@Dinreが述べたように、この問題は実際にはファセットとは関係ありません。binwidthが無視されず、特別な方法で使用されていることがわかりますhexBin。この関数はすべてのファセットに個別に適用されます。その後、hexGrobファセットごとに適用されます。たとえば、それらを検査できることを確認するには

trace(ggplot2:::hexGrob, quote(browser()))
trace(ggplot2:::hexBin, quote(browser()))

binwidthしたがって、これはサイズが異なる理由を説明しています-それらは両方と各ファセット自体のデータに依存します。

さまざまな座標変換があるため、プロセスを追跡するのは困難ですが、次の出力に注意してください。hexBin

data.frame(
  hcell2xy(hb),
  count = hb@count,
  density = hb@count / sum(hb@count, na.rm=TRUE)
)

常に非常に普通に見えるように見え、それhexGrobが 16 進ビン、歪みを描画する原因となります。つまり、polygonGrob. ファセットに 16 進ビンが 1 つしかない場合は、より深刻な異常があります。

dx <- resolution(x, FALSE)
dy <- resolution(y, FALSE) / sqrt(3) / 2 * 1.15

私たちは見ることが?resolutionできます

説明

 The resolution is is the smallest non-zero distance between adjacent
 values. If there is only one unique value, then the resolution is
 defined to be one.

このため(resolution(x, FALSE) == 1および)例の最初のファセットのresolution(y, FALSE) == 1x 座標はpolygonGrob

[1] 1.5native  1.5native  0.5native  -0.5native -0.5native 0.5native 

私が間違っていなければ、この場合、ネイティブ ユニットは npc のようなものなので、0 から 1 の間である必要があります。つまり、単一の 16 進ビンの場合、resolution(). この関数は、@Dinre が複数の 16 進ビンを持つ場合でも言及した歪みの理由でもあります。

そのため、今のところ、同じサイズの 16 進ビンを持つオプションはないようです。一時的な (そして多数の要因に対して非常に不便な) 解決策は、次のようなものから始めることができます。

library(gridExtra)
set.seed(2)
bindata <- data.frame(x = rnorm(100), y = rnorm(100))
fac_probs <- c(10, 40, 40, 10)
bindata$factor <- sample(letters[1:4], 100, 
                         replace = TRUE, prob = fac_probs)

binwidths <- list(c(0.4, 0.4), c(0.5, 0.5),
                  c(0.5, 0.5), c(0.4, 0.4))

plots <- mapply(function(w,z){
  ggplot(bindata[bindata$factor == w, ], aes(x = x, y = y)) +
    geom_hex(binwidth = z) + theme(legend.position = 'none')
}, letters[1:4], binwidths, SIMPLIFY = FALSE)

do.call(grid.arrange, plots)

ここに画像の説明を入力

于 2013-01-29T19:27:06.043 に答える
2

また、「ggplot2」の 16 進プロットをいじくり回したところ、因子の母集団が 8 以下に減ったときに、一貫して大きなビンの歪みを生成することができました。パッケージソースを掘り下げることなく、なぜこれが起こっているのかを説明することはできませんが(私はそれをするのは気が進まない)、まばらな要因が一貫して「ggplot2」の16進ビンプロットを破壊しているように見えることを伝えることができます.

これは、「ggplot2」の特定の16進数ビンのサイズと形状が、グループに対して単一の計算を実行して後でデータをプロットするのではなく、各ファセットに固有の計算に関連していることを示唆しています. これは、次のように、その単一の要因のみをプロットすることで、特定のファセットの歪みを再現できるという事実によって多少強化されます。

ggplot(bindata[bindata$factor=="e",], aes(x=x, y=y)) +
geom_hex()

これは、パッケージのメンテナである Hadley Wickham (gmail.com の h.wickham) に昇格させる必要があるような気がします。 この情報は CRAN から公開されています。

更新: 私は Hadley Wickham にこの質問を見てくれるかどうかを尋ねる電子メールを送信しました。彼はこの動作が実際にバグであることを確認しました。

于 2013-01-29T14:35:50.307 に答える