在ggplot中,如何用一条线绘制一个圆/圆盘,根据给定的比例和里面的彩色点划分其面积? [英] In ggplot, how to draw a circle/disk with a line that divides its area according to a given ratio and colored points inside?

查看:57
本文介绍了在ggplot中,如何用一条线绘制一个圆/圆盘,根据给定的比例和里面的彩色点划分其面积?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用圆内的点来可视化比例.例如,假设我有 100 个点希望散布(有点随机抖动)在一个圆圈中.

接下来,我想用这张图来表示每个州在 2020 年美国总统大选中投票给拜登/哈里斯的人的比例.

示例 1 -- 密歇根
拜登获得了密歇根州 50.62% 的选票.我将绘制一个将圆分成两半的水平直径,然后将直径下的点涂成蓝色(民主党的颜色).


示例 2 -- 怀俄明州
与密歇根州不同的是,在怀俄明州,拜登只获得了 26.55% 的选票,大约是选票的四分之一.在这种情况下,我会画一个水平弦来划分圆,这样弦下方的 磁盘 区域是整个磁盘区域的 25%.然后我会将那个区域的各个点涂成蓝色.因为我总共有 100 分,所以 25 分代表怀俄明州 25% 的人投票给拜登.


我的问题:我怎样才能用 ggplot 做到这一点?我研究了这个问题,这里有很多几何学.首先,我所说的那种区域称为

I want to visualize proportions using points inside a circle. For example, let's say that I have 100 points that I wish to scatter (somewhat randomly jittered) in a circle.

Next, I want to use this diagram to represent the proportions of people who voted Biden/Harris in 2020 US presidential elections, in each state.

Example #1 -- Michigan
Biden got 50.62% of Michigan's votes. I'm going to draw a horizontal diameter that splits the circle to two halves, and then color the points under the diameter in blue (Democrats' color).


Example #2 -- Wyoming
Unlike Michigan, in Wyoming Biden got only 26.55% of the votes, which is approximately a quarter of the vote. In this case I'd draw a horizontal chord that divides the circle such that the disk's area under the chord is 25% of the entire disk area. Then I'll color the respective points in that area in blue. Since I have 100 points in total, 25 points represent the 25% who voted Biden in Wyoming.


My question: How can I do this with ggplot? I researched this issue, and there's a lot of geometry going on here. First, the kind of area I'm talking about is called a "circular segment". Second, there are many formulas to calculate its area, if we know some other parameters about the shape (such as the radius length, etc.). See this nice demo.

However, my goal isn't to solve geometry problems, but just to represent proportions in a very specific way:

  1. draw a circle
  2. sprinkle X number of points inside
  3. draw a (real or invisible) horizontal line that divides the circle/disk area according to a given proportion
  4. ensure that the points are arranged respective to the split. That is, if we want to represent a 30%-70% split, then have 30% of the points under the line that divides the disk.
  5. color the points under the line.

I understand that this is somewhat an exotic visualization, but I'll be thankful for any help with this.


EDIT


I've found a reference to a JavaScript package that does something very similar to what I'm asking.

解决方案

I took a crack at this for fun. There's a lot more that could be done. I agree that this is not a great way to visualize proportions, but if it's engaging your audience ...

Formulas for determining appropriate heights are taken from Wikipedia. In particular we need the formulas

a/A = (theta - sin(theta))/(2*pi)
h = 1-cos(theta/2)

where a is the area of the segment; A is the whole area of the circle; theta is the angle described by the arc that defines the segment (see Wikipedia for pictures); and h is the height of the segment.

Machinery for finding heights.

afun <- function(x) (x-sin(x))/(2*pi)
## curve(afun, from=0, to = 2*pi)
find_a <- function(a) {
    uniroot(
        function(x) afun(x) -a,
        interval=c(0, 2*pi))$root
}
find_h <- function(a) {
    1- cos(find_a(a)/2)
}
vfind_h <- Vectorize(find_h)
## find_a(0.5)
## find_h(0.5)
## curve(vfind_h(x), from = 0, to= 1)

set up a circle

dd <- data.frame(x=0,y=0,r=1)
library(ggforce)
library(ggplot2); theme_set(theme_void())
gg0 <- ggplot(dd) + geom_circle(aes(x0=x,y0=y,r=r)) + coord_fixed()

finish

props <- c(0.2,0.5,0.3)  ## proportions
n <- 100                 ## number of points to scatter
cprop <- cumsum(props)[-length(props)]
h <- vfind_h(cprop)
set.seed(101)
r <- runif(n)
th <- runif(n, 0, 2 * pi)
  
dd <- 
 data.frame(x = sqrt(r) * cos(th), 
            y = sqrt(r) * sin(th))

dd2 <- data.frame(x=r*cos(2*pi*th), y = r*sin(2*pi*th))
dd2$g <- cut(dd2$y, c(1, 1-h, -1))
gg0 + geom_point(data=dd2, aes(x, y, colour = g), size=3)

There are a bunch of tweaks that would make this better (meaningful names for the categories; reverse the axis order to match the plot; maybe add segments delimiting the sections, or (more work) polygons so you can shade the sections.

You should definitely check this for mistakes — e.g. there are places where I may have used a set of values where I should have used their first differences, or vice versa (values vs cumulative sum). But this should get you started.

这篇关于在ggplot中,如何用一条线绘制一个圆/圆盘,根据给定的比例和里面的彩色点划分其面积?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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