I was curious if anyone knew how to create a heatmap with an isoquant curve that identifies all x and y combinations whose product equals a certain constant. The final product should look like the following picture:
Scatterplot with isoquant curve
Here is the code I use to generate my plot, but as of right now I can't get the curve in the plot as depicted in the picture above:
vs.vpd.by.drop_days <- ggplot(event_drops, aes(vs, vpd)) +
geom_point(aes(color = day_since), size = 2, alpha = 0.2) +
scale_color_gradientn(colors = c("darkblue","green","yellow","red"),
breaks = c(0,25,50,75),
limits = c(0,75),
name = "Days since \n first drop") +
ggtitle("Drops by VPD and Wind Speed") +
theme(plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
axis.title = element_text(size = 15)) +
xlab(label = "Wind Speed (mph)") +
ylab(label = "Vapor Pressure Deficit") +
expand_limits(x = 0, y = 0) +
scale_x_continuous(expand = c(0, 0), limits = c(0,20)) +
scale_y_continuous(expand = c(0, 0), limits = c(0,5))
vs.vpd.by.drop_days
One option to achieve that would be geom_function.
Using mtcars as example data:
library(ggplot2)
ggplot(mtcars, aes(hp, mpg, color = disp)) +
geom_point() +
geom_function(fun = function(x) 3000 / x)
Related
I have a gganimate sketch in R and I would like to have the percentages of my bar chart appear as labels.
But for some bizarre reason, I am getting seemingly random colours in place of the labels that I'm requesting.
If I run the ggplot part without animating then it's a mess (as it should be), but it's obvious that the percentages are appearing correctly.
Any ideas? The colour codes don't correspond to the colours of the bars which I have chosen separately. The codes displayed also cycle through about half a dozen different codes, at a rate different to the frame rate that I selected. And while the bars are the same height (they grow until they reach the chosen height displayed in the animation) then they display the same code until they stop and it gets frozen.
Code snippet:
df_new <- data.frame(index, rate, year, colour)
df_new$rate_label <- ifelse(round(df_new$rate, 1) %% 1 == 0,
paste0(round(df_new$rate, 1), ".0%"), paste0(round(df_new$rate, 1), "%"))
p <- ggplot(df_new, aes(x = year, y = rate, fill = year)) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = colour) +
#geom_text(aes(y = rate, label = paste0(rate, "%")), vjust = -0.7) +
geom_shadowtext(aes(y = rate, label = rate_label),
bg.colour='white',
colour = 'black',
size = 9,
fontface = "bold",
vjust = -0.7,
alpha = 1
) +
coord_cartesian(clip = 'off') +
ggtitle("% population belonging to 'No religion', England and Wales census") +
theme_minimal() +
xlab("") + ylab("") +
theme(legend.position = "none") +
theme(plot.title = element_text(size = 18, face = "bold")) +
theme(axis.text = element_text(size = 14)) +
scale_y_continuous(limits = c(0, 45), breaks = 10*(0:4))
p
p <- p + transition_reveal(index) + view_follow(fixed_y = T)
animate(p, renderer = gifski_renderer(), nframes = 300, fps = frame_rate, height = 500, width = 800,
end_pause = 0)
anim_save("atheism.gif")
I think you have missed some delicate points about ggplot2. I will try my best to describe them to you. First of all, you need to enter the discrete values as factor or integer. So you can use as.factor() before plotting or just factor() in the aesthetic. Also, you should consider rounding the percentages as you wish. Here is an example:
set.seed(2023)
df_new <- data.frame(index=1:10, rate=runif(10), year=2001:2010, colour=1:10)
df_new$rate_label <- ifelse(round(df_new$rate, 1) %% 1 == 0,
paste0(round(df_new$rate, 1), ".0%"),
paste0(round(df_new$rate, 1), "%"))
The ggplot for this data is:
library(ggplot2)
p <- ggplot(df_new, aes(x = factor(year), y = rate, fill = factor(colour))) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(aes(y = rate, label = paste0(round(rate,2), "%")), vjust = -0.7) +
coord_cartesian(clip = 'off') +
ggtitle("% population belonging to 'No religion', England and Wales census") +
theme_minimal() +
xlab("") + ylab("") +
theme(legend.position = "none",
plot.title = element_text(size = 18, face = "bold"),
axis.text = element_text(size = 14))
p
And you can combine all theme element in one theme() function (as did I). The output is:
And you can easily animate the plot using the following code:
library(gganimate)
p + transition_reveal(index)
And the output is as below:
Hope it helps.
So it was answered here although I don't know why the fix works.
For some reason, labels need to go into gganimate as factors
as.factor()
I just had to add the line:
df_new$rate_label <- as.factor(df_new$rate_label)
and it works fine.
I am including marginal distribution plots on a scatterplot of a continuous and integer variable. However, in the integer variable maringal distribution plot (y-axis) there is this zig-zag pattern that shows up because the y-values are all integers. Is there any way to increase the "width" (not sure that's the right term) of the bins/values the function calculates the distribution density over?
The goal is to get rid of that zig-zag pattern that develops because the y-values are integers.
library(GlmSimulatoR)
library(ggplot2)
library(patchwork)
### Create right-skewed dataset that has one continous variable and one integer variable
set.seed(123)
df1 <- data.frame(matrix(ncol = 2, nrow = 1000))
x <- c("int","cont")
colnames(df1) <- x
df1$int <- round(rgamma(1000, shape = 1, scale = 1),0)
df1$cont <- round(rgamma(1000, shape = 1, scale = 1),1)
p1 <- ggplot(data = df1, aes(x = cont, y = int)) +
geom_point(shape = 21, size = 2, color = "black", fill = "black", stroke = 1, alpha = 0.4) +
xlab("Continuous Value") +
ylab("Integer Value") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 16, color = "black"),
axis.text.y = element_text(size = 16, color = "black"))
dens1 <- ggplot(df1, aes(x = cont)) +
geom_density(alpha = 0.4) +
theme_void() +
theme(legend.position = "none")
dens2 <- ggplot(df1, aes(x = int)) +
geom_density(alpha = 0.4) +
theme_void() +
theme(legend.position = "none") +
coord_flip()
dens1 + plot_spacer() + p1 + dens2 +
plot_layout(ncol = 2, nrow = 2, widths = c(6,1), heights = c(1,6))
From ?geom_density:
adjust: A multiplicate [sic] bandwidth adjustment. This makes it possible
to adjust the bandwidth while still using the a bandwidth
estimator. For example, ‘adjust = 1/2’ means use half of the
default bandwidth.
So as a start try e.g. geom_density(..., adjust = 2) (bandwidth twice as wide as default) and go from there.
I'd like to make a density scatterplot with log10 scale in R. I tried to plot it using ggplot and stat_density2d in R. I used this code:
ggplot(data=vod_agb_df, aes(vod, agb)) +
stat_density2d(aes(fill = ..density..), geom = "tile", contour = FALSE, n = 100) +
scale_fill_distiller(palette = 'YlOrRd', direction = 1) +
scale_x_continuous(breaks=seq(0, 1, 0.25), limits = c(0, 1)) +
scale_y_continuous(breaks=seq(0, 300, 50), limits = c(0, 300)) +
labs(x='L-VOD', y='AGB(Mg/ha)') +
theme_bw()
But the result looks strange. the density scatterplot with my code
This is the plot I want to plot
The original scatterplot
You can log10-transform the density; here's a minimal & reproducible example
library(MASS)
library(tidyverse)
set.seed(2020)
mvrnorm(100, mu = c(0, 0), Sigma = matrix(c(1, 0.5, 0.5, 1), 2, 2)) %>%
as_tibble() %>%
ggplot(aes(V1, V2)) +
stat_density2d(
aes(fill = log10(..density..)), geom = "tile", contour = FALSE, n = 100) +
scale_fill_distiller(palette = 'YlOrRd', direction = 1) +
theme_bw()
Update
It's not clear to me what you mean by ""I'd like to make the density scatterplot in the point distributed area, not the whole area of the plot."" If you're asking how to increase the height of the gradient colour bar, you can do the following
set.seed(2020)
mvrnorm(100, mu = c(0, 0), Sigma = matrix(c(1, 0.5, 0.5, 1), 2, 2)) %>%
as_tibble() %>%
ggplot(aes(V1, V2)) +
stat_density2d(
aes(fill = log10(..density..)), geom = "tile", contour = FALSE, n = 100) +
scale_fill_distiller(palette = 'YlOrRd', direction = 1) +
theme_bw() +
guides(fill = guide_colorbar(barheight = unit(3.5, "in"), title.position = "right"))
Whatever plot you are showing as your expected output for that you can use following code
library(tidyverse)
# Bin size control + color palette
ggplot(iris, aes(x=Sepal.Length, y=Petal.Length) ) +
geom_bin2d(bins = 20) +
scale_fill_distiller(palette = 'YlOrRd', direction = 1) +
theme_bw() +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())
I would really appreciate if anyone could guide me with the following challenge.
I am trying to build column wise heatmap. For each column, I want the lowest value to be green and highest value to be red. The current solution takes a matrix wide approach.
I saw the solution on Heat map per column with ggplot2. As you can see, I implemented the same code but I am not getting the desired result [picture below]
df <- data.frame(
F1 = c(0.66610194649319, 0.666123551800434,
0.666100611954119, 0.665991102703081,
0.665979885730484),
acc_of_pred = c(0.499541627510021, 0.49960260221954,
0.499646067768102, 0.499447308828986,
0.499379552967265),
expected_mean_return = c(2.59756065316356e-07, 2.59799087404167e-07,
2.86466725381146e-07, 2.37977452007967e-07,
2.94242908573705e-07),
win_loss_ratio = c(0.998168189343307, 0.998411671274781,
0.998585272507726, 0.997791676357902,
0.997521287688458),
corr_pearson = c(0.00161443345430616, -0.00248811119331013,
-0.00203407575954095, -0.00496817102369628,
-0.000140531627184482),
corr_spearman = c(0.00214838517340878, -0.000308343671725617,
0.00228492127281917, -0.000359577740835049,
0.000608090759428587),
roc_vec = c(0.517972308828151, 0.51743161463546,
0.518033230192484, 0.518033294993802,
0.517931553535524)
)
combo <- data.frame(combo = c("baseline_120", "baseline_20",
"baseline_60", "baseline_288",
"baseline_5760"))
df.scaled <- scale(df)
df.scaled <- cbind(df.scaled,combo)
df.melt <- melt(df.scaled, id.vars = "combo")
ggplot(df.melt, aes(combo, variable)) +
geom_tile(aes(fill = value), colour = "white") +
scale_fill_gradient(low = "green", high = "red") +
geom_text(aes(label=value)) +
theme_grey(base_size = 9) +
labs(x = "", y = "") + scale_x_discrete(expand = c(0, 0)) +
scale_y_discrete(expand = c(0, 0)) +
theme(legend.position = "none", axis.ticks = element_blank(),
axis.text.x = element_text(size = 9 * 0.8,
angle = 0, hjust = 0, colour = "grey50"))
You are nearly correct. The code you implemented is the same for plotting. But the person who asked the question did one step in data preparation, he added a scaling variable.
If you scale your variable before plotting it and using the scaled factor as fill argument it works (i just added the rescale in scale_fill_gradient in ggplot after calculating it):
df.melt <- melt(df.scaled, id.vars = "combo")
df.melt<- ddply(df.melt, .(combo), transform, rescale = rescale(value))
ggplot(df.melt, aes(combo, variable)) +
geom_tile(aes(fill = rescale), colour = "white") +
scale_fill_gradient( low= "green", high = "red") +
geom_text(aes(label=round(value,4))) +
theme_grey(base_size = 9) +
labs(x = "", y = "") + scale_x_discrete(expand = c(0, 0)) +
scale_y_discrete(expand = c(0, 0)) +
theme(legend.position = "none", axis.ticks = element_blank(),
axis.text.x = element_text(size = 9 * 0.8,
angle = 0, hjust = 0, colour = "grey50"))
giving the plot:
I am trying to plot the following vector using ggplot:
library(ggplot2)
vec =c(44.55 ,47.81 ,40.28 ,44.32 ,53.57 ,45.68 ,52.02 ,44.27 ,33.44 ,41.16)
by = c("1994-04-30", "1994-05-31", "1994-06-30", "1994-07-31", "1994-08-31", "1994-09-30", "1994-10-31", "1994-11-30", "1994-12-31", "1995-01-31")
vec.zoo = zoo(vec, order.by = as.Date(by))
g <-ggplot(vec.zoo) +
geom_line (aes(x=index(vec.zoo), y=coredata(vec.zoo)), color = "cadetblue4", size = 0.6) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
xlab("Time") +
ylab("Hit Ratio") +
scale_y_continuous(limits = c(0, 100))
scale_x_date(limits = c(start(vec.zoo), end(vec.zoo)))
g
Although I set the limits of the axis, they still don't intersect at origin. I would like to set the intersection at x= 0 and y = start(vec).
Here is the result I obtain:
You may use the expand argument in your scale calls. Setting expand to zero, removes the default, small gap between data and axes (see here)
g <-ggplot(vec.zoo) +
geom_line (aes(x=index(vec.zoo), y=coredata(vec.zoo)), color = "cadetblue4", size = 0.6) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
xlab("Time") +
ylab("Hit Ratio") +
scale_y_continuous(limits = c(0, 100), expand = c(0, 0)) +
scale_x_date(limits = c(start(vec.zoo), end(vec.zoo)), expand = c(0, 0))
g