7

あるクラスから別のクラスへの遷移を示すプロットを作成しようとしています。クラス属性に応じたサイズの各クラスを表す円と、あるクラスから別のクラスへの遷移の数に応じたサイズの、あるクラスから別のクラスへの矢印が必要です。

例として:

library(ggplot2)
points <- data.frame( x=runif(10), y=runif(10),class=1:10, size=runif(10,min=1000,max=100000) )
trans <- data.frame( from=rep(1:10,times=10), to=rep(1:10,each=10), amount=runif(100)^3 )
trans <- merge( trans, points, by.x="from", by.y="class" )
trans <- merge( trans, points, by.x="to", by.y="class", suffixes=c(".to",".from") )
ggplot( points, aes( x=x, y=y ) ) + geom_point(aes(size=size),color="red") + 
    scale_size_continuous(range=c(4,20)) + 
    geom_segment( data=trans, aes( x=x.from, y=y.from, xend=x.to, yend=y.to, size=amount ),lineend="round",arrow=arrow(),alpha=0.5)

サンプル画像

円とは異なるスケールで矢印を拡大縮小できるようにしたいと思います。理想的には、両方のスケールをオンにした凡例が必要ですが、これが不可能な場合があることを理解しています ( 1 つの ggplot で 2 つのスケール カラー グラデーションを使用) 。

基になるデータに任意のスケーリングを適用するよりも、これを行うためのよりエレガントな方法はありますか?

4

1 に答える 1

1

便利なオプションは、クラスの円周を一連のポイントとして生成し、データに従ってスケール (直径) を調整することです。次に、円をパスまたはポリゴンとして描画します。

いくつかのサンプルコードに従います。は、以前の投稿circleFunで @joran によって共有されました。これは機能しますか?実際のデータに応じて、円のスケールを微調整する必要があると思います。

特記事項:
また、arrow添付せずにご利用gridいただいていることから、更新していないものとみなしますggplot2。そのコードを自分のセットアップで動作するように変更し、ggplot2下位互換性の問題を引き起こす可能性のあるコードを含めないようにしました。

# Load packages
library(package=ggplot2)  # You should update ggplot2
library(package=plyr)     # To proccess each class separately


# Your data generating code
points <- data.frame(x=runif(10), y=runif(10),class=1:10,
                     size=runif(10,min=1000,max=100000) )
trans <- data.frame(from=rep(1:10,times=10), to=rep(1:10,each=10),
                    amount=runif(100)^3 )
trans <- merge(trans, points, by.x="from", by.y="class" )
trans <- merge(trans, points, by.x="to", by.y="class", suffixes=c(".to",".from") )


# Generate a set of points in a circumference
# Originally posted by @joran in
# https://stackoverflow.com/questions/6862742/draw-a-circle-with-ggplot2
circleFun <- function(center = c(0,0), diameter = 1, npoints = 100){
    r = diameter / 2
    tt <- seq(0,2*pi,length.out = npoints)
    xx <- center[1] + r * cos(tt)
    yy <- center[2] + r * sin(tt)
    return(data.frame(x = xx, y = yy))
}


# Get max and min sizes and min distances to estimate circle scales
min_size <- min(points$size, na.rm=TRUE)
max_size <- max(points$size, na.rm=TRUE)
xs <- apply(X=combn(x=points$x, m=2), MARGIN=2, diff, na.rm=TRUE)
ys <- apply(X=combn(x=points$y, m=2), MARGIN=2, diff, na.rm=TRUE)
min_dist <- min(abs(c(xs, ys)))  # Seems too small
mean_dist <- mean(abs(c(xs, ys)))

# Adjust sizes
points$fit_size <- points$size * (mean_dist/max_size)


# Generate the circles based on the points
circles <- ddply(.data=points, .variables='class',
                 .fun=function(class){
                    with(class,
                    circleFun(center = c(x, y), diameter=fit_size))
                 })
circles <- merge(circles, points[, c('class', 'size', 'fit_size')])


# Plot
ggplot(data=circles, aes(x=x, y=y)) +
    geom_polygon(aes(group=factor(class), fill=size)) + 
    geom_segment(data=trans,
                 aes(x=x.from, y=y.from, xend=x.to, yend=y.to, size=amount),
                 alpha=0.6, lineend="round", arrow=grid::arrow()) +
    coord_equal()
于 2013-02-20T16:00:17.300 に答える