I only have a series of number, and I want to count the number of each element. Here is something I have done. X-axis is my element and Y-axis is the number of each element.
My question is, how could I revise the way of presentation in the x-axis? I only want to see 0.4, 0.5, 0.6, 0.7, 0.8 and 0.9 in the axis, but still to keep the same number of bars in the figure (nothing changed). Any suggestion please?
d1 <- ggplot(TestData, aes(factor(TestData$Col1)))
d2 <- d1 + geom_bar() + xlab("") + ylab("")
Create data with mean of 0.5, std of 0.2:
data<- rnorm(1000,0.5,0.2)
dataf <- data.frame(data)
Make histogram for all data range:
ggplot(aes(x = data),data = dataf) +
geom_histogram()
Xlim to 0.4 to 0.9:
ggplot(aes(x = data),data = dataf) +
geom_histogram() +
scale_x_continuous(limits = c(0.4,0.9),
breaks= scales::pretty_breaks(n=5))
In base graphics, you can just omit the axes when generating the plot, then add them manually using the axis function:
set.seed(1234)
dat <- rnorm(1000, 0.5, 0.1)
hist(dat, axes = FALSE, xlim = c(0, 1))
axis(side = 2)
axis(side = 1, at = seq(0.4, 0.9, 0.1))
Related
I cannot figure out how to get the percentage of responses at the end of the bars. I know I'm missing something within the text() function, just not sure what exactly I'm missing. Thank you!
#Training/Specialty Barplot
trainbarplot <- barplot(table(PSR$training), horiz = TRUE,
main="Respondent Distribution of Training", cex.main = 1.1, font.main = 2,
cex.lab = 0.8, cex.names = 0.4, font.axis = 4, las = 2,
xlab="Response Frequency", xlim=c(0, 40), cex.axis = 0.8,
border="black",
col=rgb (0.1, 0.1, 0.4, 0.5, 0.6),
density=c(50,40,30) , angle=c(9,11,36)
)
text(trainbarplot, table(PSR$training) - 3,
labels=paste(round(proportions(table(PSR$training))*100, 0), "%"))
Generate data
I generated some sample data to replicate your problem. Please note that you should always try to provide an example dataset :)
set.seed(123)
df1 <- data.frame(x = rnorm(10, mean=10, sd=2), y = LETTERS[1:20])
Plot the data
Here's a plot that follows the same structure as your code:
bp <- barplot(df1$x, names.arg = df1$y, col = df1$colour, horiz = T)
text(x= df1$x+0.5, y= bp, labels=paste0(round(df1$x),"%"), xpd=TRUE)
Using ggplot2
You can also plot your data using ggplot2. For instance, you could first create a new column in your dataset with information on the labels...
df1$perc <- paste0(round(df1$x),"%")
Next, you can plot your data using ggplot and adding different relevant layers.
library(ggplot2)
ggplot(df1, aes(x = x, y = y)) +
geom_col() +
geom_text(aes(label = perc)) +
theme_minimal()
Good luck!
I'd like to make a plot using ggplot2 where some of the fill values are clipped, i.e. values above or below the limits of the color scale are displayed as the minimum/maximum color. I can get this to work like this, using a combination of limit and oob (out of bounds):
library(ggplot2)
library(scales)
ggplot() + ... + scale_fill_viridis(na.value="white", limit=c(0, 10), oob=squish)
But there is no information in the colorbar that indicates there are values present outside of the limits.
How can I reproduce this matplotlib example in ggplot: https://stackoverflow.com/a/32072348
Specifically, how to get the triangles at the end of the colorbar?
As far as I'm aware there is not a package that implements triangle ends for colourbars in ggplot2 (but please let me know if there is!). However, we can implement our own. We'd need a constructor for our custom guide and a way to draw it. Most of the stuff is already implemented in guide_colourbar() and methods for their class, so what we need to do is just tag on our own class and expand the guide_gengrob method. The code below should work for vertically oriented colourbars. You'd need to know some stuff about the grid package and gtable package to follow along.
library(ggplot2)
library(gtable)
library(grid)
my_triangle_colourbar <- function(...) {
guide <- guide_colourbar(...)
class(guide) <- c("my_triangle_colourbar", class(guide))
guide
}
guide_gengrob.my_triangle_colourbar <- function(...) {
# First draw normal colourbar
guide <- NextMethod()
# Extract bar / colours
is_bar <- grep("^bar$", guide$layout$name)
bar <- guide$grobs[[is_bar]]
extremes <- c(bar$raster[1], bar$raster[length(bar$raster)])
# Extract size
width <- guide$widths[guide$layout$l[is_bar]]
height <- guide$heights[guide$layout$t[is_bar]]
short <- min(convertUnit(width, "cm", valueOnly = TRUE),
convertUnit(height, "cm", valueOnly = TRUE))
# Make space for triangles
guide <- gtable_add_rows(guide, unit(short, "cm"),
guide$layout$t[is_bar] - 1)
guide <- gtable_add_rows(guide, unit(short, "cm"),
guide$layout$t[is_bar])
# Draw triangles
top <- polygonGrob(
x = unit(c(0, 0.5, 1), "npc"),
y = unit(c(0, 1, 0), "npc"),
gp = gpar(fill = extremes[1], col = NA)
)
bottom <- polygonGrob(
x = unit(c(0, 0.5, 1), "npc"),
y = unit(c(1, 0, 1), "npc"),
gp = gpar(fill = extremes[2], col = NA)
)
# Add triangles to guide
guide <- gtable_add_grob(
guide, top,
t = guide$layout$t[is_bar] - 1,
l = guide$layout$l[is_bar]
)
guide <- gtable_add_grob(
guide, bottom,
t = guide$layout$t[is_bar] + 1,
l = guide$layout$l[is_bar]
)
return(guide)
}
You can then use your custom guide as the guide argument in a scale.
g <- ggplot(mtcars, aes(mpg, wt)) +
geom_point(aes(colour = drat))
g + scale_colour_viridis_c(
limits = c(3, 4), oob = scales::oob_squish,
guide = my_triangle_colourbar()
)
There isn't really a natural way to colour out-of-bounds values differently, but you can make very small slices near the extremes a different colour.
g + scale_colour_gradientn(
colours = c("red", scales::viridis_pal()(255), "hotpink"),
limits = c(3, 4), oob = scales::oob_squish,
guide = my_triangle_colourbar()
)
Created on 2021-07-19 by the reprex package (v1.0.0)
library(gg.layers)
library(ggplot2)
library(rcolors)
brk <- c(-Inf, -1, 0, 1, 3, 6, 9, Inf)
nbrk <- length(brk) - 1
cols <- get_color(rcolors$amwg256, nbrk)
g <- make_colorbar(
at = brk, col = cols, height = 1,
tck = 0.4,
space = "right",
legend.text.location = c(0.3, 0.5),
legend.text.just = c(0.5, 0.5),
# legend.text = list(fontfamily = "Times", cex = 1.1),
hjust = 0.05
)
p <- ggplot(mtcars, aes(mpg, disp)) + geom_point()
p + g
https://github.com/rpkgs/gg.layers
Triangles? No idea. Colors? You can set a gradient with custom values where your normal range is manually defined and your extremes are something else.
library(ggplot2)
# example taken from ?viridis::scale_colour_viridis, even if I don't use that function
dsub <- subset(diamonds, x > 5 & x < 6 & y > 5 & y < 6)
dsub$diff <- with(dsub, sqrt(abs(x-y))* sign(x-y))
d <- ggplot(dsub, aes(x, y, colour=diff)) + geom_point()
d +
scale_color_gradientn(
colours=c("red", "red", "blue", "green", "yellow", "red", "red"),
values = c(0, 0.1-1e-9, 0.1, 0.5, 0.9, 0.9+1e-9, 1),
breaks = c(-0.51, -.4, 0, .4, .62),
label = function(z) replace(z, c(1, length(z)), c("Min", "Max"))) +
theme_bw()
I doubled "red" on each end so that there would be no gradient transition with the neighboring colors. You can choose a different color for one end (while in this case it's clear if it's extreme-high or extreme-low).
I chose to manually control values= and labels= to include arbitrary points and labels for the extremes. This can be improved based on your preferences.
The disadvantage to this is that you have to define the viridis colors manually; should not be too difficult. I've hastily approximated it here, I'm confident you can choose better colors for the internal gradient portion.
I have a log-normal density with a mean of -0.4 and standard deviation of 2.5.
At x = 0.001 the height is over 5 (I double checked this value with the formula for the log-normal PDF):
dlnorm(0.001, -0.4, 2.5)
5.389517
When I plot it using the curve function over the input range 0-6 it looks like with a height just over 1.5:
curve(dlnorm(x, -.4, 2.5), xlim = c(0, 6), ylim = c(0, 6))
When I adjust the input range to 0-1 the height is nearly 4:
curve(dlnorm(x, -.4, 2.5), xlim = c(0, 1), ylim = c(0, 6))
Similarly with ggplot2 (output not shown, but looks like the curve plots above):
library(ggplot2)
ggplot(data = data.frame(x = 0), mapping = aes(x = x)) +
stat_function(fun = function(x) dlnorm(x, -0.4, 2.5)) +
xlim(0, 6) +
ylim(0, 6)
ggplot(data = data.frame(x = 0), mapping = aes(x = x)) +
stat_function(fun = function(x) dlnorm(x, -0.4, 2.5)) +
xlim(0, 1) +
ylim(0, 6)
Does someone know why the density height is changing when the x-axis scale is adjusted? And why neither attempt above seems to reach the correct height? I tried this with just the normal density and this doesn't happen.
curves generates a set of discrete points in the range you give it. By default it generates n = 101 points, so there is a step problem. If you increase the number of points you will have almost the correct value:
curve(dlnorm(x, -.4, 2.5), xlim = c(0, 1), ylim = c(0, 6), n = 1000)
In the first case you propose curve generates 101 points in the interval x <- c(0,6), while in the second case generates 101 points in the interval x <- c(0,1), so the step is more dense
I have a simple plot below. I log scaled the x-axis and I want the graph to show 0.1, 1, 10. I can't figure out how to override the default of 0.1, 1.0, 10.0.
Is there a way I could change only two of the x-axis labels?
library(ggplot2)
x <- c(0.1, 1, 10)
y <- c(1, 5, 10)
ggplot()+
geom_point(aes(x,y)) +
scale_x_log10()
You could specify labels and breaks in scale_x_log10
library(ggplot2)
x <- c(0.1, 1, 10)
y <- c(1, 5, 10)
ggplot() + geom_point(aes(x,y)) + scale_x_log10(labels = x, breaks = x)
I'm trying to create a figure similar to the one below (taken from Ro, Russell, & Lavie, 2001). In their graph, they are plotting bars for the errors (i.e., accuracy) within the reaction time bars. Basically, what I am looking for is a way to plot bars within bars.
I know there are several challenges with creating a graph like this. First, Hadley points out that it is not possible to create a graph with two scales in ggplot2 because those graphs are fundamentally flawed (see Plot with 2 y axes, one y axis on the left, and another y axis on the right)
Nonetheless, the graph with superimposed bars seems to solve this dual sclaing problem, and I'm trying to figure out a way to create it in R. Any help would be appreciated.
It's fairly easy in base R, by using par(new = T) to add to an existing graph
set.seed(54321) # for reproducibility
data.1 <- sample(1000:2000, 10)
data.2 <- sample(seq(0, 5, 0.1), 10)
# Use xpd = F to avoid plotting the bars below the axis
barplot(data.1, las = 1, col = "black", ylim = c(500, 3000), xpd = F)
par(new = T)
# Plot the new data with a different ylim, but don't plot the axis
barplot(data.2, las = 1, col = "white", ylim = c(0, 30), yaxt = "n")
# Add the axis on the right
axis(4, las = 1)
It is pretty easy to make the bars in ggplot. Here is some example code. No two y-axes though (although look here for a way to do that too).
library(ggplot2)
data.1 <- sample(1000:2000, 10)
data.2 <- sample(500:1000, 10)
library(ggplot2)
ggplot(mapping = aes(x, y)) +
geom_bar(data = data.frame(x = 1:10, y = data.1), width = 0.8, stat = 'identity') +
geom_bar(data = data.frame(x = 1:10, y = data.2), width = 0.4, stat = 'identity', fill = 'white') +
theme_classic() + scale_y_continuous(expand = c(0, 0))