Draw circle in date axis with ggplot2 - r

Now I draw plot with ggplot2.
I want to draw circle in my plot.
So I searched it and found the solutions.
Draw a circle with ggplot2
However I can't use this solution, because my plot's x axis is Date format.
my_plot <- qplot(Day, value, data = target_data_melt, shape = variable, colour = variable, geom="line")
my_plot <- my_plot + scale_x_date(labels = date_format("%Y-%m"))
How can I draw a circle in my plot?
Is there any way to draw a circle in Date axis?
target_data_melt looks like this.
Day variable value
1 2010-10-01 231 0.007009346
2 2010-10-03 231 0.005204835
3 2010-10-05 231 0.006214004

You can adapt the code from the link you provided to format the x-coordinate as Date:
require("date")
circle <- function(center_Date = as.Date("2012-11-24"),
center_y = 0,
r.x = 100,
r.y = 100,
npoints = 100) {
cycle <- seq(0,2*pi,length.out = npoints)
xx <- center_Date + r.x * cos(cycle)
yy <- center_y + r.y * sin(cycle)
return(data.frame(x = xx, y = yy))
}
And a demonstration:
df <- circle()
plot <- ggplot(df, aes(x, y)) + geom_path()
plot(plot)
Example image (with an adjusted date and y-center) here.
You'll have to set the r.x and r.y properly to get a perfect circle (rather than an oval). What these should be depends on the scales you use in your plots.

Related

Plotting ambient functions with ggplot2

I'm using the ambient package in R to generate graphs. It provides a custom base plot method.
library(ambient)
library(dplyr)
grid <- long_grid(x = seq(0, 1, length.out = 1000),
y = seq(0, 1, length.out = 1000))
grid <- grid %>%
mutate(
noise = fracture(gen_perlin, fbm, octaves = 4, x = x, y = y, freq_init = 5)
)
plot(grid, noise)
However I'd like to plot this image using ggplot2 and geom_raster instead of base plotting. I tried doing
ggplot(grid, aes(x = x, y = y, color = noise)) +
geom_raster()
But that just produced
Any idea how I can make this with ggplot2?
Wrong aesthetic: raster draws a bunch of same-size tiles, where the color is the border and the fill is the color of the tile. You want fill=noise here:
ggplot(grid, aes(x,y, fill=noise)) + geom_raster()

Can I draw a horizontal line at specific number of range of values using ggplot2?

I have data (from excel) with the y-axis as ranges (also calculated in excel) and the x-axis as cell counts and I would like to draw a horizontal line at a specific value in the range, like a reference line. I tried using geom_hline(yintercept = 450) but I am sure it is quite naive and does not work that way for a number in range. I wonder if there are any better suggestions for it :)
plot.new()
library(ggplot2)
d <- read.delim("C:/Users/35389/Desktop/R.txt", sep = "\t")
head(d)
d <- cbind(row.names(d), data.frame(d), row.names=NULL)
d
g <- ggplot(d, aes(d$CTRL,d$Bin.range))+ geom_col()
g + geom_hline(yintercept = 450)
First of all, have a look at my comments.
Second, this is how I suggest you to proceed: don't calculate those ranges on Excel. Let ggplot do it for you.
Say, your data is like this:
df <- data.frame(x = runif(100, 0, 500))
head(df)
#> x
#>1 322.76123
#>2 57.46708
#>3 223.31943
#>4 498.91870
#>5 155.05416
#>6 107.27830
Then you can make a plot like this:
library(ggplot2)
ggplot(df) +
geom_histogram(aes(x = x),
boundary = 0,
binwidth = 50,
fill = "steelblue",
colour = "white") +
geom_vline(xintercept = 450, colour = "red", linetype = 2, size = 1) +
coord_flip()
We don't have your data, but the following data frame is of a similar structure:
d <- data.frame(CTRL = sample(100, 10),
Bin.range = paste(0:9 * 50, 0:9 * 50 + 49.9, sep = "-"))
The first thing to note is that your y axis does not have your ranges ordered correctly. You have 50-99.9 at the top of the y axis. This is because your ranges are stored as characters and ggplot will automatically arrange these alphabetically, not numerically. So you need to reorder the factor levels of your ranges:
d$Bin.range <- factor(d$Bin.range, d$Bin.range)
When you create your plot, don't use d$Bin.range, but instead just use Bin.range. ggplot knows to look for this variable in the data frame you have passed.
g <- ggplot(d, aes(CTRL, Bin.range)) + geom_col()
If you want to draw a horizontal line, your two options are to specify the y axis label at which you want to draw the line (i.e. yintercept = "400-449.9") or, which is what I suspect you want, use a numeric value of 9.5 which will put it between the top two values:
g + geom_hline(yintercept = 9.5, linetype = 2)

Plotting a geom_arc() over a geom_point() plot

I am trying to plot a 90 degree arc from the x axis to the y axis as part of a geom_point() plot I already have with the aim of creating two parts to the graph, inside the arc and outside.
This is the data I have:
set.seed(1)
vector1 <- sample(1:500,250, replace = T)
vector2 <- replicate(250,min(sample(200,2,replace=TRUE)))
so.df <- data.frame(vector1, vector2)
so.df
ggplot(data = so.df, aes(x=vector2, y=vector1)) + geom_point()
I would like the arc to go from 100 on the y-axis to 100 on the x-axis with a radius of 10.
If I can clarify anything further please ask.
Thanks.
You can make the necessary coordinates using a little bit of geometry and then add it on in an additional geom_line:
set.seed(1)
vector1 <- sample(1:500,250, replace = T)
vector2 <- replicate(250,min(sample(200,2,replace=TRUE)))
so.df <- data.frame(vector1, vector2)
so.df
arc_data <- data.frame(
x = 0:100
) %>%
mutate(y = sqrt(100^2 - x^2))
ggplot(data = so.df, aes(x=vector2, y=vector1)) + geom_point() +
geom_line(aes(x, y), data = arc_data, col = "red")
That being said, I'm not sure how something with radius 10 reaches 100 on both axes?

Transform angles from polar coordinates

I am in need of some help with angles.
Calculating bearings with the package fossil and the function fossil::earth.bear we obtain, according to the help,
"the bearing in degrees clockwise from True North between any two points on the globe".
I have a vector of angles obtained with this function, and I need to transform them so the origin (0º) is on the x axis (East) and the angles increment counterclockwise.
Basically I need a way to rotate 90º clockwise my angles (so the 0º will be on the x axis "facing East") and then calculate the angle in the opposite direction (counterclockwise).
Intuitively, I've tried adding 90º to my bearings (to rotate clockwise) and then substracting them from 360 (to calculate the angle in the "opposite direction").
However, it does not work and I highly suspect that there is a different thing to do for each quadrant, but I just can't figure it out.
Below a test with dummy data and polar histograms to prove that the solution is not working as the resulting vector bearings2is not equivalent to the starting vector bearings
# Generate vector with 100 random values between 0 and 360
set.seed(123)
bearing <- runif(100, 0,360)
# generate a histogram with values binned every 5º
breaks = seq(0, 360, by=5)
bearing.cut = cut(bearing, breaks, right=FALSE)
bearing.freq = as.data.frame(table(bearing.cut))
bearing.freq$bearing.cut <- seq(5,360, by = 5)
#plot with ggplot
library(ggplot2)
ggplot(bearing.freq, aes(x = bearing.cut, y = Freq)) +
coord_polar(theta = "x", start = 0 direction = 1) + #start 0 for north, direction 1 for cloclwise
geom_bar(stat = "identity") +
scale_x_continuous(breaks = seq(0, 360, 5))
This is the plot that this creates
Now I perform the mentioned operations in my bearing vector
bearing2 <- 360-(bearing-90)
# repeat the process to generate freq table and plot
breaks = seq(0, 360, by=5)
bearing.cut2 = cut(bearing2, breaks, right=FALSE)
bearing.freq2 = as.data.frame(table(bearing.cut2))
bearing.freq2$bearing.cut <- seq(5,360, by = 5)
#plot with ggplot
library(ggplot2)
ggplot(bearing.freq2, aes(x = bearing.cut2, y = Freq)) +
coord_polar(theta = "x", start = -pi/2, direction = -1) + # now start at E and counterclockwise
geom_bar(stat = "identity") +
scale_x_continuous(breaks = seq(0, 360, 5))
And this is the plot that this generates. Clearly, if my conversion was correct, these two plots should look the same... and they don't.
** I have edited as per Gregor's suggestion (and to set a seed so it is repeatable). Looks better but we lose all angles between 0º and 90º. Which reinforces my initial idea that there's a different operation to do for each quadrant, but still can't figure it out. Still, thanks for the tip!
Ok I think I figured it out but not really sure why it works. I'll just leave it here to mark the question as answered.
The solution is that, for the first quadrant (angles between 0º and 90º, we need to calculate the complementray angle so we need 90-bearing . For the rest of the quadrants, we do what Gregor suggested(360-(bearing-90)).
Below the complete code to a reproducible example
library(ggplot2)
set.seed(123)
# 0º at North and clockwise
bearing <- runif(100, 0,360)
#create histogram
breaks = seq(0, 360, by=5) # half-integer sequence
bearing.cut = cut(bearing, breaks, right=FALSE)
bearing.freq = as.data.frame(table(bearing.cut))
bearing.freq$bearing.cut <- seq(5,360, by = 5)
#plot
p1 <- ggplot(bearing.freq, aes(x = bearing.cut, y = Freq)) +
coord_polar(theta = "x", start =0, direction = 1) +
geom_bar(stat = "identity") +
scale_x_continuous(breaks = seq(0, 360, 5))
# transform to 0º at E and counterclockwise
bearing2 <- ifelse(bearing <=90, (90-bearing), (360 - (bearing - 90)))
#create histogram
bearing.cut2 = cut(bearing2, breaks, right=FALSE)
bearing.freq2 = as.data.frame(table(bearing.cut2))
bearing.freq2$bearing.cut <- seq(5,360, by = 5)
# plot
p2 <- ggplot(bearing.freq2, aes(x = bearing.cut, y = Freq)) +
coord_polar(theta = "x", start = -pi/2, direction = -1) +
geom_bar(stat = "identity") +
scale_x_continuous(breaks = seq(0, 360, 5))
require(gridExtra)
grid.arrange(p1, p2, ncol=2)

Add annotation outside of stratigraphic plot

How can I add some annotations to a stratigraphic plot?
For example, here's Stratiplot from analogue:
library(analogue)
data(V12.122)
Depths <- as.numeric(rownames(V12.122))
names(V12.122)
(plt <- Stratiplot(Depths ~ O.univ + G.ruber + G.tenel + G.pacR,
data = V12.122,
type = c("h","l","g"),
zones = 400))
plt
I want to add some text in the white space between the blue plots and the zones rectangle on the far right. For example, like this:
With A = 150, B = 600, C = 1000
Here's one way:
pacman::p_load(analogue)
data(V12.122)
Depths <- as.numeric(rownames(V12.122))
names(V12.122)
(plt <- Stratiplot(Depths ~ O.univ + G.ruber + G.tenel + G.pacR,
data = V12.122,
type = c("h","l","g"),
zones = 400))
(plt2 <- Stratiplot(Depths ~ O.univ + G.ruber + G.tenel + G.pacR,
data = V12.122,
type = c("h","l","g"),
yticks = c(150,600,1000)
))
We need to update the y-axis labels like this:
plt2$y.scales$labels <- c("A", "B", "C")
And then we can plot it with the two y-axes like so:
require(latticeExtra)
doubleYScale(plt,plt2,add.axis=T)
I checked out the source code of this function and figured out that it was a wrapper around xyplot then I did a search to find out that doubleYScale can be used this way to add a 2nd Y axis to an xyscale.
Or to keep the colours uniformly black,
doubleYScale(plt,plt2,add.axis=T,use.style = F)

Resources