ggplot: Modify histogram plot - r

I made this plot using the following code:
ggplot(all, aes(x = year, color = layer)) +
geom_histogram(binwidth = 0.5, fill = "white", alpha = 0.5, position = "dodge") +
scale_x_continuous(breaks = pretty(all$year)) +
scale_color_discrete(name = "title", labels = c("A","B")) +
theme_light() +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank(),
text = element_text(size = 20),
axis.title.x = element_text(margin = margin(t = 25, r = 0, b = 0, l = 0)),
axis.title.y = element_text(margin = margin(t = 0, r = 25, b = 0, l = 0)),
axis.text.x = element_text(angle = 50, hjust = 1, size = 18, color = "black"),
axis.text.y = element_text(size = 18, color = "black"))
I would now like to change the colors first, using colors from the viridis palette. Furthermore, there are blue and red strokes between the histograms, which I would like to remove.
Could someone help me to change the code?
Thanks in advance!
Test Data:
year <- runif(10, 2014, 2021)
year <- round(year, 0)
layer <- sample(c("A","B"), size=10, replace=T)
all <- as.data.frame(year,layer)

Seems like you want a bar plot not a histogram.
all <- data.frame(year,layer) ## fix the sample data creation
ggplot(all, aes(x = year, fill = layer)) + ## I think fill looks better...
geom_bar(position = position_dodge(preserve = "single")) + ## bar, not histogram
#scale_x_continuous(breaks = pretty(all$year)) + ## this line just confirmed defaults
scale_fill_viridis_d() +
theme_light() ## omitted the rest of the theme as irrelevant for the issue at hand
If you do want outline color, not fill, switching to geom_bar "fixes" the strokes between the bars:
ggplot(all, aes(x = year, color = layer)) +
geom_bar(position = position_dodge(preserve = "single"), fill = NA) +
scale_color_viridis_d() +
theme_light()

Thank you, this is helpful information!

Related

Overlapping labels in legend in ggplot?

How to avoid overlapping the lagend labels in ggplot?
ggplot(g3, aes(variable, country, fill= value)) + geom_tile() +
theme(axis.text.y = element_text(size = 15), axis.text.x = element_text(angle = 45, hjust = 1, size = 15), legend.position="bottom", legend.text = element_text(size = 15, angle = 50),
axis.title.x = element_blank(),axis.title.y = element_blank())
For axis labels, the best way to fix this is to use the ggplot2::guide_axis() function, which will adjust both the angle and vertical/horizontal positioning at the same time. You can also make your legend labels easier to read by scaling the label. This might obviate the need to rotate the legend labels. For example:
library(ggplot2)
ggplot(g3, aes(variable, country, fill = value)) +
geom_tile() +
labs(x = "", y = "") +
scale_fill_continuous(labels = scales::label_number(scale = 10000, suffix = "k")) +
guides(x = guide_axis(angle = 45), fill = guide_colorbar(direction = "horizontal)) +
theme(legend.position = "bottom", text = element_text(size = 15))

R ggridges plot - Showing y axis ticks and labels

I am trying to generate overlay density plots over time, comparing densities of males vs. females. Here is my output:
I am following the Australian athletes height example from https://cran.r-project.org/web/packages/ggridges/vignettes/gallery.html.
Here is my code:
ggplot(math_dat, aes(x = order_math, y = time, color = gender, point_color = gender, fill = gender)) +
geom_density_ridges(
jittered_points = TRUE, scale = .95, rel_min_height = .01,
point_shape = "|", point_size = 3, size = 0.25,
position = position_points_jitter(height = 0)
) +
scale_y_discrete(expand = c(0, 0)) +
scale_x_continuous(expand = c(0, 0), name = "Rankings") +
scale_fill_manual(values = c("#D55E0050", "#0072B250"), labels = c("female", "male")) +
scale_color_manual(values = c("#D55E00", "#0072B2"), guide = "none") +
scale_discrete_manual("point_color", values = c("#D55E00", "#0072B2"), guide = "none") +
coord_cartesian(clip = "off") +
guides(fill = guide_legend(
override.aes = list(
fill = c("#D55E00A0", "#0072B2A0"),
color = NA, point_color = NA)
)
) +
ggtitle("Ranks over time") +
theme_ridges(center = TRUE)
My problem is I am unable to generate any Y axis tick values and the example doesn't display any either. Any ideas how to get Y axis tick marks to display?
Here is some sample data similar to mine:
## generating dataset
order_math<-c(1,2,1,2,3,3,1,2,3,1,2,3)
gender<-c("M","F","M","M","M","F","F","M","F","M","M","F")
time<-c(1,1,2,3,3,2,1,2,3,2,3,1)
sample<-data.frame(order_math,gender,time)
UPdate:
After #Tomasu's suggestions I have updated my code, but it does not run:
ggplot(math_dat, aes(x = order_math, y = time, color = gender, point_color = gender, fill = gender)) +
geom_density_ridges(
jittered_points = TRUE, scale = .95, rel_min_height = .01,
point_shape = "|", point_size = 3, size = 0.25,
position = position_points_jitter(height = 0)
) +
scale_y_reverse(limits = c(1000, 500, 100),expand = c(0, 0)) +
scale_x_continuous(expand = c(0, 0), name = "Rankings") +
scale_fill_manual(values = c("#D55E0050", "#0072B250"), labels = c("female", "male")) +
scale_color_manual(values = c("#D55E00", "#0072B2"), guide = "none") +
scale_discrete_manual("point_color", values = c("#D55E00", "#0072B2"), guide = "none") +
coord_cartesian(clip = "off") +
guides(fill = guide_legend(
override.aes = list(
fill = c("#D55E00A0", "#0072B2A0"),
color = NA, point_color = NA)
)
) +
ggtitle("Ranks over time") +
theme_ridges(center = TRUE)+
theme(
axis.ticks = element_line(size=0.5), # turn ticks back on
axis.ticks.length = grid::unit(5, "pt"), # set length
axis.ticks.y = element_line(colour = "red"), # define tick line color
axis.text.y = element_text(vjust = .4) # center text with tick
)
An easy solution to this problem would be to use a theme_ that includes the axis ticks as theme_ridges() has them turned off. Just removing that theme all together and using the base ggplot2 theme achieves the desired outcome.
However, let's say we still want to use theme_ridges() and just turn ticks back on. This can be achieved with a theme() edit after the theme_ridges().
I'm using the example in the link provided as I couldn't get your sample data to work properly.
library(ggplot2)
library(ggplot2movies)
library(ggridges)
ggplot(movies[movies$year>1912,], aes(x = length, y = year, group = year)) +
geom_density_ridges(scale = 10, size = 0.25, rel_min_height = 0.03) +
theme_ridges() +
theme(
axis.ticks = element_line(size=0.5), # turn ticks back on
axis.ticks.length = grid::unit(5, "pt"), # set length
axis.ticks.y = element_line(colour = "red"), # define tick line color
axis.text.y = element_text(vjust = .4) # center text with tick
) +
scale_x_continuous(limits = c(1, 200), expand = c(0, 0)) +
scale_y_reverse(
breaks = c(2000, 1980, 1960, 1940, 1920, 1900),
expand = c(0, 0)
) +
coord_cartesian(clip = "off")
Created on 2021-05-11 by the reprex package (v1.0.0)
I think your problem is that you need to specify the group.
Related thread: geom_density_ridges requires the following missing aesthetics: y
Extending on code from user tomasu's answer +1
library(ggridges)
library(ggplot2)
order_math<-c(1,2,1,2,3,3,1,2,3,1,2,3)
gender<-c("M","F","M","M","M","F","F","M","F","M","M","F")
time<-c(1,1,2,3,3,2,1,2,3,2,3,1)
sample<-data.frame(order_math,gender,time)
ggplot(sample, aes(x = order_math, y = time, group = time,
color = gender, point_color = gender, fill = gender)) +
geom_density_ridges() +
theme(
axis.ticks = element_line(size=0.5), # turn ticks back on
axis.ticks.length = grid::unit(5, "pt"), # set length
axis.ticks.y = element_line(colour = "red"), # define tick line color
axis.text.y = element_text(vjust = .4) # center text with tick
)
#> Picking joint bandwidth of 0.555
Created on 2021-05-12 by the reprex package (v2.0.0)

How to organize geom_bar() values ​after applying coord.flip()? Package ggplot2

How to place the numbers centralized and in their correct positions? I have tested numerous parameters but I have not found a solution. Everything was very confusing after coordin_flip (). Observe the image and code below.
Code:
# Package
library(ggplot2)
# Create a dataframe
RATE <- c('IgG','IgG','IgA/IgG','IgA/IgG')
GROUP <- c('Asymptomatic','Symptomatic','Asymptomatic','Symptomatic')
N_POSITIVE <- c(12,100,14,107)
PORCENT <- c(7.05, 58.8, 7.73, 59.1)
df <- data.frame(RATE, GROUP, N_POSITIVE, PORCENT)
# Plot
ggplot(df, aes(x = RATE, y = PORCENT, fill = GROUP)) +
geom_bar(stat="identity", width = 0.5) +
geom_text(aes(label=N_POSITIVE),
vjust = -0.3, color = 'black',
size = 3) +
coord_flip() +
labs(x = '', y = 'Percentage (%)\n') +
scale_fill_manual(values = c("#0073c2", "#efc000")) +
theme_classic() +
theme(
legend.position = "top",
legend.title = element_blank(),
axis.text = element_text(angle = 0, color = "black", size = 10, face = 0),
axis.title.x = element_text(angle = 0, color = "black", size = 12, face = 0))
Image:
Does this do what you want? (minus the other formatting which I left out)
ggplot(df, aes(x = PORCENT, y = RATE, fill = GROUP)) +
geom_col(width = 0.5) +
geom_text(aes(label=N_POSITIVE),
vjust = -0.3, color = 'black', hjust = 1.1,
size = 3, position = "stack")
(Note, since ggplot2 3.3.0 in March 2020, most geom's don't need coord_flip if you assign them to the axis you want. If it doesn't interpret correctly, there's also an "orientation" parameter but that doesn't seem necessary here. Also, geom_col is equal to geom_bar(stat="identity").)

ggplot2 barplot with dual Y-axis and error bars

I am trying to generate a barplot with dual Y-axis and error bars. I have successfully generated a plot with error bars for one variable but I don't know how to add error bars for another one. My code looks like this. Thanks.
library(ggplot2)
#Data generation
Year <- c(2014, 2015, 2016)
Response <- c(1000, 1100, 1200)
Rate <- c(0.75, 0.42, 0.80)
sd1<- c(75, 100, 180)
sd2<- c(75, 100, 180)
df <- data.frame(Year, Response, Rate,sd1,sd2)
df
# The errorbars overlapped, so use position_dodge to move them horizontally
pd <- position_dodge(0.7) # move them .05 to the left and right
png("test.png", units="in", family="Times", width=2, height=2.5, res=300) #pointsize is font size| increase image size to see the key
ggplot(df) +
geom_bar(aes(x=Year, y=Response),stat="identity", fill="tan1", colour="black")+
geom_errorbar(aes(x=Year, y=Response, ymin=Response-sd1, ymax=Response+sd1),
width=.2, # Width of the error bars
position=pd)+
geom_line(aes(x=Year, y=Rate*max(df$Response)),stat="identity",color = 'red', size = 2)+
geom_point(aes(x=Year, y=Rate*max(df$Response)),stat="identity",color = 'black',size = 3)+
scale_y_continuous(name = "Left Y axis", expand=c(0,0),limits = c(0, 1500),breaks = seq(0, 1500, by=500),sec.axis = sec_axis(~./max(df$Response),name = "Right Y axis"))+
theme(
axis.title.y = element_text(color = "black"),
axis.title.y.right = element_text(color = "blue"))+
theme(
axis.text=element_text(size=6, color = "black",family="Times"),
axis.title=element_text(size=7,face="bold", color = "black"),
plot.title = element_text(color="black", size=5, face="bold.italic",hjust = 0.5,margin=margin(b = 5, unit = "pt")))+
theme(axis.text.x = element_text(angle = 360, hjust = 0.5, vjust = 1.2,color = "black" ))+
theme(axis.line = element_line(size = 0.2, color = "black"),axis.ticks = element_line(colour = "black", size = 0.2))+
theme(axis.ticks.length = unit(0.04, "cm"))+
theme(plot.margin=unit(c(1,0.1,0.1,0.4),"mm"))+
theme(axis.title.y = element_text(margin = margin(t = 0, r = 4, b = 0, l = 0)))+
theme(axis.title.x = element_text(margin = margin(t = 0, r = 4, b = 2, l = 0)))+
theme(
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank())+
ggtitle("SRG3")+
theme(legend.position="top")+
theme( legend.text=element_text(size=4),
#legend.justification=c(2.5,1),
legend.key = element_rect(size = 1.5),
legend.key.size = unit(0.3, 'lines'),
legend.position=c(0.79, .8), #width and height
legend.direction = "horizontal",
legend.title=element_blank())
dev.off()
and my plot is as follows:
A suggestion for future questions: your example is far from being a minimal reproducible example. All the visuals an the annotations are not related to your problem but render the code overly complex which makes it harder for others to work with it.
The following would be sufficient:
ggplot(df) +
geom_bar(aes(x = Year, y = Response),
stat = "identity", fill = "tan1",
colour = "black") +
geom_errorbar(aes(x = Year, ymin = Response - sd1, ymax = Response + sd1),
width = .2,
position = pd) +
geom_line(aes(x = Year, y = Rate * max(df$Response)),
color = 'red', size = 2) +
geom_point(aes(x = Year, y = Rate * max(df$Response)),
color = 'black', size = 3)
(Notice that I've removed stat = "identity" in all geom_s because this is set by default. Furthermore, y is not a valid aestetic for geom_errorbar() so I omitted that, too.)
Assuming that the additional variable you would like to plot error bars for is Rate * max(df$Response)) and that the relevant standard deviation is sd2, you may simply append
+ geom_errorbar(aes(x = Year, ymin = Rate * max(df$Response) - sd2,
ymax = Rate * max(df$Response) + sd2),
colour = "green",
width = .2)
to the code chunk above. This yields the output below.

Can this type of plot be done with ggplot2?

I am using R and ggplot2 to do some plots for publishing purposes. I have come across this plot and I would like to replicate it using ggplot2. However, I have never seen a plot like this made using ggplot2.
Can it be done with ggplot2? What about the text below the bars? I guess these will have to be hard coded in the ggplot2 codes. And how do you align those text?
This gets fairly close:
# Generate sample data (I'm too lazy to type out the full labels)
df <- data.frame(
perc = c(60, 36, 44, 41, 42, 57, 34, 52),
type = rep(c("blue", "green"), 4),
label = rep(c(
"Individual reports created as needed",
"Regular reports on single topics",
"Analytics using data integrated from multiple systems",
"Business unit-specific dashboards and visuals"), each = 2))
library(ggplot2)
ggplot(df, aes(1, perc, fill = type)) +
geom_col(position = "dodge2") +
scale_fill_manual(values = c("turquoise4", "forestgreen"), guide = FALSE) +
facet_wrap(~ label, ncol = 1, strip.position = "bottom") +
geom_text(
aes(y = 1, label = sprintf("%i%%", perc)),
colour = "white",
position = position_dodge(width = .9),
hjust = 0,
fontface = "bold") +
coord_flip(expand = F) +
theme_minimal() +
theme(
axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text = element_text(angle = 0, hjust = 0, face = "bold"))
A few explanations:
We use dodged bars and matching dodged labels with position = "dodge2" (note that this requires ggplot_ggplot2_3.0.0, otherwise use position = position_dodge(width = 1.0)) and position = position_dodge(width = 0.9), respectively.
We use facet_wrap and force a one-column layout; strip labels are moved to the bottom.
We rotate the entire plot with coord_flip(expand = F), where expand = F ensures that left aligned (hjust = 0) facet strip texts align with 0.
Finally we tweak the theme to increase the overall aesthetic similarity.
You can try using the data from the other answer. Differences are: we use scales::percent to draw percents. We use ggpubr::theme_transparent() theme to tweak as less as possible.
df$perc <- c(.60, .36, .44, .41, .42, .57, .34, .52)
ggplot(df, aes(label, perc, label=scales::percent(round(perc,2)),fill= factor(type))) +
geom_col(position = position_dodge(0.9), show.legend = F) +
geom_text(aes(y=0), position = position_dodge(0.9), size=5, hjust=-0.1, color="white", fontface="bold") +
scale_y_continuous("",labels = scales::percent) +
coord_flip(expand = F) +
facet_wrap(~label,scales = "free", strip.position = "bottom", ncol = 1) +
ggpubr::theme_transparent() +
xlab("") +
theme(strip.background = element_blank(),
strip.text = element_text(size = 12, face = "bold",hjust=0))
Maybe using facet wrap and adjusting the style?
dat <- data.frame(perc = c(60, 20, 90, 30), col = rep(c("gr1", "gr2"), 2),
text = c(rep("text1", 2), rep("text2", 2)))
ggplot(dat, aes(y = perc, x = col, fill = col)) +
geom_bar(stat = "identity", position = "dodge") +
coord_flip() +
facet_wrap(~text, strip.position = "bottom", ncol = 1)

Resources