在ggplot中使用多个尺寸比例 [英] using multiple size scales in a ggplot

查看:96
本文介绍了在ggplot中使用多个尺寸比例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图构建一个显示从一个类到另一个类的转换的情节。我希望每个类都有一个圆圈,它们根据类属性大小以及从一个类到另一个类的箭头大小,根据从一个类到另一个类的转换次数来确定。

例如:

  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,时间= 10),= rep(1:10,每个= 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)



我希望能够将不同比例的箭头缩放到圆圈。理想情况下,我想要一个有两个比例的传说,但我明白这可能是不可能的(在一个ggplot上使用两个比例颜色渐变)

是否有更好的方法可以做到这一点,而不是对底层应用任意缩放数据?

一个不错的选择是将您的课程周长生成一系列点,调整比例(直径)根据你的数据。然后,您将圆圈绘制为路径或多边形。



遵循一些示例代码。 circleFun 由@joran在中共享上一篇文章。这是否工作?我认为您应该根据您的实际数据调整圈子比例。


重要说明:

另外,从使用 arrow 而不附加 grid ,我假设你没有更新 GGPLOT2 。我更改了该代码以使用我的设置,并且尝试不包含任何可能导致向后兼容性问题的 ggplot2 代码。




 #加载软件包
library(package = ggplot2)#您应该更新ggplot2
library(package = plyr)#To分别处理每个类


#您的数据生成代码
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) (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))


#在周围生成一组点
#最初由@joran发布在
#中https://stackoverflow.com/questions/6862742/draw-a -cgcle-with-ggplot2
circleFun< - 函数(分er = c(0,0),直径= 1,npoints = 100){
r =直径/ 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))
}


#获取最大和最小尺寸以及最小距离来估计圆尺度
min_size < - min(points $ size,na (r = 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)))#似乎太小
mean_dist< - mean(abs(c(xs,ys)))

#调整大小
points $ fit_size< - points $ size *(mean_dist / max_size)


#根据分数生成圆圈
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' )])


#地块
ggplot(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()


I'm trying to construct a plot which shows transitions from one class to another. I want to have circles representing each class sized according to a class attribute, and arrows from one class to another, sized according to the number of transitions from one class to another.

As an example:

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)

I'd like to be able to scale the arrows on a different scale to the circles. Ideally, I'd like a legend with both scales on, but I understand this may not be possible (using two scale colour gradients on one ggplot)

Is there a more elegant way to do this than applying arbitrary scaling to the underlying data?

解决方案

A nice option is to generate the circumference of your classes as a series of points, adjusting the scale (diameter) according to your data. Then you draw the circles either as paths or polygons.

Follows some example code. The circleFun was shared by @joran in a previous post. Does this work? I think you should tweak the circle scales acording to your real data.

Important note:
Also, from your use of arrow without attaching grid, I assume you have not updated ggplot2. I changed that code to work with my setup, and tried not to include any ggplot2 code that might cause backward compatibility issues.

# 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()

这篇关于在ggplot中使用多个尺寸比例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆