6

独自の関数を作成できる R の ggplot2 の新しい機能を使用しようとしていstat_ます。2次元配列に配置されたポイント間の補間サーフェスを計算してプロットするための単純なものを作成しています。

xy、およびval美学を必要とする stat_topo() を作成し、単純なgeom_raster補間valマップをにプロットしたいと思いますfill

library(ggplot2)
library(dplyr)
library(akima)

cpt_grp <- function(data, scales) {
  #interpolate data in 2D
  itrp <- akima::interp(data$x,data$y,data$val,linear=F,extrap=T)
  out <- expand.grid(x=itrp$x, y=itrp$y,KEEP.OUT.ATTRS = F)%>%
    mutate(fill=as.vector(itrp$z))
  # str(out)
  return(out)
}

StatTopo <- ggproto("StatTopo", Stat,
                    compute_group = cpt_grp,
                    required_aes = c("x","y","val")
)
stat_topo <- function(mapping = NULL, data = NULL, geom = "raster",
                       position = "identity", na.rm = FALSE, show.legend = NA, 
                       inherit.aes = TRUE, ...) {
  layer(
    stat = StatTopo, data = data, mapping = mapping, geom = geom, 
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, ...)
  )
}

set.seed(1)
nchan <- 30
d <- data.frame(val = rnorm(nchan), # some random values to be mapped to fill color
         x = 1:nchan*cos(1:nchan), # the x and y position of the points to interpolate
         y = 1:nchan*sin(1:nchan))
plot(d$x,d$y)

ggplot(d,aes(x=x,y=y,val=val)) +
  stat_topo() +
  geom_point()

これを実行すると、次のエラーが表示されます。

Error: numerical color values must be >= 0, found -1

何故かfill美学のスケールがバラバラに設定されているからだと理解しています。

これを入力すると:

ggplot(d,aes(x=x,y=y,val=val)) +
  stat_topo() +
  scale_fill_continuous() +
  geom_point()

私が望んでいたものを手に入れました:デフォルトstat_でやりたい連続カラースケールを持つ予想されるラスター...

ここに画像の説明を入力

したがって、問題は次のとおりだと思います。ここでggplotが個別のスケールを設定するのを防ぎ、理想的には、新しいstat_関数の呼び出し内でデフォルトのスケールを設定するにはどうすればよいですか。

4

2 に答える 2

2

どうやら、関数内で新しい変数を作成するときは、ggproto 定義内のstat_パラメーターでマップされる美学に明示的に関連付ける必要があります。default_aes = aes(fill = ..fill..)

これは、それが計算された美学であり、データ型に基づいてスケールを選択することを ggplot に伝えています。

したがって、ここではstat_を次のように定義する必要があります。

cpt_grp <- function(data, scales) {
  # interpolate data in 2D
  itrp <- akima::interp(data$x,data$y,data$val,linear=F,extrap=T)
  out <- expand.grid(x=itrp$x, y=itrp$y,KEEP.OUT.ATTRS = F)%>%
    mutate(fill=as.vector(itrp$z))
  # str(out)
  return(out)
}

StatTopo <- ggproto("StatTopo", Stat,
                    compute_group = cpt_grp,
                    required_aes = c("x","y","val"),
                    default_aes = aes(fill = ..fill..)
)

stat_topo <- function(mapping = NULL, data = NULL, geom = "raster",
                      position = "identity", na.rm = FALSE, show.legend = NA, 
                      inherit.aes = TRUE, ...) {
  layer(
    stat = StatTopo, data = data, mapping = mapping, geom = geom, 
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, ...)    
  )
}

次に、次のコード:

set.seed(1)
nchan <- 30
d <- data.frame(val = rnorm(nchan),
                x = 1:nchan*cos(1:nchan),
                y = 1:nchan*sin(1:nchan))
ggplot(d,aes(x=x,y=y,val=val)) +
  stat_topo() +
  geom_point()

期待どおりに生成されます:

stat_topo の結果

手動で指定する必要はありscale_ませんが、通常のように簡単にスケールを調整する可能性を残しています。scale_fill_gradient2(low = 'blue',mid='white',high='red')

ここでこの回答を得ました: https://github.com/hadley/ggplot2/issues/1481

于 2016-01-12T22:13:11.510 に答える
1

さて、それで寝て、アイデアがありました。これはあなたが望むことをするかもしれないと思います. stat_topoの代わりにレイヤー関数で、それggprotoを最初の要素としてリストを返し、そのリストに別ggprotoの呼び出しを追加しましたscale_fill_continuous()

library(ggplot2)
library(dplyr)
library(akima)

cpt_grp <- function(data, scales) {
  #interpolate data in 2D
  itrp <- akima::interp(data$x,data$y,data$val,linear=F,extrap=T)
  out <- expand.grid(x=itrp$x, y=itrp$y,KEEP.OUT.ATTRS = F)%>%
    mutate(fill=as.vector(itrp$z))
  return(out)
}
StatTopo <- ggproto("StatTopo", Stat,
                    compute_group = cpt_grp,
                    required_aes = c("x","y","val")
)
stat_topo <- function(mapping = NULL, data = NULL, geom = "raster",
                      position = "identity", na.rm = FALSE, show.legend = NA, 
                      inherit.aes = TRUE, ...) {
  list(
    layer(
      stat = StatTopo, data = data, mapping = mapping, geom = geom, 
      position = position, show.legend = show.legend, inherit.aes = inherit.aes,
      params = list(na.rm = na.rm )
    ),
    scale_fill_continuous()
  )
}
set.seed(1)
nchan <- 30
d <- data.frame(val = rnorm(nchan), # some random values to be mapped to fill color
                x = 1:nchan*cos(1:nchan), # the x and y position of interp points
                y = 1:nchan*sin(1:nchan))
 ggplot(d,aes(x=x,y=y,val=val)) +
   stat_topo() +
   geom_point()

上記と同じ画像が得られます。

于 2016-01-11T07:02:34.163 に答える