问题
What would be the best way to draw a circular histogram in R?
My data has this form:
Dir N
1: 360 56564
2: 0 NA
3: 180 149374
4: 210 82219
5: 240 23315
6: 300 11436
7: 330 30648
8: 30 32198
9: 60 15266
10: 90 14596
11: 120 26267
12: 150 81782
13: 270 10100
I have tried using windrose
function from the circular package but it requires input data in another format.
I have looked into the graphics:: functions and stars looked promising, but nothing concrete so far.
Thanks
回答1:
You can try the following with circular
, but since your data size is small, the plot is not very fancy:
library(circular)
df <- read.table(text='Dir N
1: 360 56564
2: 0 NA
3: 180 149374
4: 210 82219
5: 240 23315
6: 300 11436
7: 330 30648
8: 30 32198
9: 60 15266
10: 90 14596
11: 120 26267
12: 150 81782
13: 270 10100', header=TRUE)
rownames(df) <- NULL
names(df) <- c('dir', 'mag')
df$dir <- circular(as.numeric(df$dir), units='degrees')
df$mag <- df$mag / 10000 # scale magnitude
windrose(df, breaks=circular(seq(0, 2 * pi, by = pi/4)), increment=5)
With another library openair
it looks like the following:
library(openair)
df <- read.table(text='Dir N
1: 360 56564
2: 0 NA
3: 180 149374
4: 210 82219
5: 240 23315
6: 300 11436
7: 330 30648
8: 30 32198
9: 60 15266
10: 90 14596
11: 120 26267
12: 150 81782
13: 270 10100', header=TRUE)
names(df) <- c('wd', 'ws')
df$ws <- df$ws / 10000 # scale speed
windRose(df, angle=45)
The polar coord plot with ggplot2
looks different (which just converts geom_bar
into polar coordinates)
library(ggplot2)
ggplot(df, aes(x=dir, y=mag)) + geom_bar(stat='identity') + coord_polar()
Some implementation I tried in base R
from scratch (just for the idea, the implementation is not very efficient, you can always improve the efficiency of implementation, for example use polygon
instead of segments
to fill the arcs), we can use a similar implementation in base R
to mimic the one in ggplot
:
add.filled.arc <- function(center.x, center.y, radius, angle.start, angle.end, col='black') {
theta <- seq(angle.start, angle.end, .0001)
segments(0, 0, radius*cos(theta), radius*sin(theta), col)
segments(0, 0, cos(angle.start), sin(angle.start), col='gray')
segments(0, 0, cos(angle.end), sin(angle.end), col='gray')
}
plot.coord.polar <- function(df) {
df <- df[complete.cases(df),]
df <- df[order(df[,1]),]
df[,1] <- df[,1]*(pi/180) # convert dir to radian
df[,2] <- df[,2] / max(df[,2]) # normalize magnitude within [0-1]
plot(-1:1, -1:1, type= 'n', xlab='', ylab='', xaxt='n', yaxt='n')
sapply(1:(nrow(df)-1), function(i) add.filled.arc(0, 0, df[i,2], df[i,1], df[i+1,1], rainbow(nrow(df))[i]))
theta <- seq(0, 2*pi, 0.0001)
lines(cos(theta), sin(theta), col='gray')
}
df <- read.table(text='Dir N
1: 360 56564
2: 0 NA
3: 180 149374
4: 210 82219
5: 240 23315
6: 300 11436
7: 330 30648
8: 30 32198
9: 60 15266
10: 90 14596
11: 120 26267
12: 150 81782
13: 270 10100', header=TRUE)
plot.coord.polar(df)
回答2:
You could use ggplot2:
library(ggplot2)
data(mpg)
g <- ggplot(mpg, aes(class)) + geom_bar() + coord_polar()
g
For your data, assuming your data frame above is called df, and you want to graph N you would do:
library(ggplot2)
g <- ggplot(df, aes(N)) + geom_bar() + coord_polar()
g
来源:https://stackoverflow.com/questions/41627124/r-base-graphics-circular-histogram