I'd like to create a filled rectangle in R, with white text centered in the middle, and export it to png. I know the rect() function can probably do this, but every example I've seen the rectangle is printed on a plot. Is there a way to do this without the plot?
For reference, I'm building a blogdown() site and trying to create a square that looks pretty much identical to those in the Hugrid theme.
You can use geom_rect() to create rectangles and geom_text() to paste text into them. Modifying rectangle look (color, line size or type) in ggplot2 is easy. All you have to do is to remove default ggplot2 look with theme_classsic() and element_blank().
# Generate dummy dataset
foo <- data.frame(x1 = 1, x2 = 2, y1 = 1, y2 = 2,
text = paste(letters[1:3], letters[1:3], collapse = "\n"))
# Plot rectangle with text
library(ggplot2)
ggplot(foo) +
geom_rect(aes(xmin = x1, xmax = x2, ymin = y1, ymax = y2),
color = "black", size = 2, fill = "lightblue") +
geom_text(aes(x = x1 + (x2 - x1) / 2, y = y1 + (y2 - y1) / 2,
label = text),
size = 20) +
theme_classic() +
theme(axis.line = element_blank(),
axis.ticks = element_blank(),
axis.text = element_blank(),
axis.title = element_blank())
Here's a lightweight solution,
rects <- data.frame(fill = RColorBrewer::brewer.pal(5, "Pastel1"),
colour = RColorBrewer::brewer.pal(5, "Set1"),
label = paste("text", 1:5), stringsAsFactors = FALSE)
library(gridExtra)
gl <- mapply(function(f,l,c) grobTree(rectGrob(gp=gpar(fill=f, col="white",lwd=2)),
textGrob(l, gp=gpar(col=c))),
f = rects$fill, l = rects$label, c = rects$colour,
SIMPLIFY = FALSE)
grid.arrange(grobs=gl)
It's not quite clear from your question what exactly the sticking point is. Do you need to generate the rectangles from R (instead of, say, manually in Illustrator)? And no plot window must be shown?
All of this can be achieved. I prefer to draw with ggplot2, and the specific geoms you'd need here are geom_tile() for the rectangles and geom_text() for the text. And you can save to png without generating a plot by using ggsave().
rects <- data.frame(x = 1:4,
colors = c("red", "green", "blue", "magenta"),
text = paste("text", 1:4))
library(ggplot2)
p <- ggplot(rects, aes(x, y = 0, fill = colors, label = text)) +
geom_tile(width = .9, height = .9) + # make square tiles
geom_text(color = "white") + # add white text in the middle
scale_fill_identity(guide = "none") + # color the tiles with the colors in the data frame
coord_fixed() + # make sure tiles are square
theme_void() # remove any axis markings
ggsave("test.png", p, width = 4.5, height = 1.5)
I made four rectangles in this example. If you need only one you can just make an input data frame with only one row.
Related
It seems that one can only change the size of the text, which scales the text in both width and height in ggplot. Does anyone know if there is a way to plot a text with a given width and height at a given x, y position on the plot? In another words, I want to be able to stretch the text in x or y dimension without affecting the other, like the image provided here.
Much appreciated.
What you want is the ggfittext package
You can play around with it for what you need, but stealing a few examples from its doc gives this :
library(ggplot2)
library(ggfittext)
library(ggpubr) # for ggarrange
g1 <- ggplot(animals, aes(x = type, y = flies, label = animal)) +
geom_tile(fill = "white", colour = "black") +
geom_fit_text() + ggtitle("no options")
g2 <- ggplot(animals, aes(x = type, y = flies, label = animal)) +
geom_tile(fill = "white", colour = "black") +
geom_fit_text(grow = T) + ggtitle("grow = T")
ggarrange(g1, g2, ncol = 2)
I want to display related ggplots together, with axes all the same size, but with some plots displaying the axis title and other plots blanking the axis title. However, using element_blank() to remove the axis also changes the size of the plot. Here's an example:
library(tidyverse)
library(cowplot)
tb <- tibble(a = 1:5, b = 1:5)
with_x_title <- ggplot(tb, aes(a,b)) +
geom_point()
without_x_title <- ggplot(tb, aes(a,b)) +
geom_point() +
theme(axis.title.x = element_blank())
ggdraw() +
draw_plot(with_x_title, x = 0, y = 0, width = 0.5, height = 1) +
draw_plot(without_x_title, x = 0.5, y = 0, width = 0.5, height = 1)
Here, the y-axis of the plot without an x-axis title is expanded. Is there a way to prevent this happening?
I'm aware I can fudge a fix by changing the height and position in the call to ggdraw, but I'd like a fix that works on the ggplots. I also imagine this is a common problem, but haven't been able to find a solution out there.
Specify the name of the x-axis as empty string, i.e. "" instead of element_blank()
...
without_x_title <- ggplot(tb, aes(a,b)) +
geom_point() +
# theme(axis.title.x = element_blank()) +
labs(x = "")
...
I am trying to recreate this visualization of a bubble chart using ggplot2 (I have found the code for doing this in R, but not with the ggplot2 package). This is what I have so far. There are some other errors with my code at the moment, but I want to have the legend show concentric circles for size, versus circles shown in rows. Thanks for your help!
Original visualization:
My reproduction:
My (simplified) code:
crime <-
read.csv("http://datasets.flowingdata.com/crimeRatesByState2005.tsv",
header=TRUE, sep="\t")
ggplot(crime,
mapping= aes(x=murder, y=burglary))+
geom_point(aes(size=population), color="red")+
geom_text(aes(label=state.name), show.legend=FALSE, size=3)+
theme(legend.position = c(0.9, 0.2))
Here's an approach where we build the legend as imagined from scratch.
1) This part slightly tweaks your base chart.
Thank you for including the source data. I missed that earlier and have edited this answer to use it. I switched to a different point shape so that we can specify both outside border (color) as well as interior fill.
gg <- ggplot(crime,
mapping= aes(x=murder, y=burglary))+
geom_point(aes(size=population), shape = 21, color="white", fill = "red")+
ggrepel::geom_text_repel(aes(label = state.name),
size = 3, segment.color = NA,
point.padding = unit(0.1, "lines")) +
theme_classic() +
# This scales area to size (not radius), specifies max size, and hides legend
scale_size_area(max_size = 20, guide = FALSE)
2) Here I make another table to use for the concentric legend circles
library(dplyr); library(ggplot2)
legend_bubbles <- data.frame(
label = c("3", "20", "40m"),
size = c(3E6, 20E6, 40E6)
) %>%
mutate(radius = sqrt(size / pi))
3) This section adds the legend bubbles, text, and title.
It's not ideal, since different print sizes will require placement tweaks. But it seems like it'd get complicated to get into the underlying grobs with ggplot_build to extract and use those sizing adjustments...
gg + geom_point(data = legend_bubbles,
# The "radius/50" was trial and error. Better way?
aes(x = 8.5, y = 250 + radius/50, size = size),
shape = 21, color = "black", fill = NA) +
geom_text(data = legend_bubbles, size = 3,
aes(x = 8.5, y = 275 + 2 * radius/50, label = label)) +
annotate("text", x = 8.5, y = 450, label = "Population", fontface = "bold")
Simple barplot with values on top of bars (I know it is silly - I was forced to add them :)). text works good, but value above highest frequency bar is hidden. I tried margins but it moves the whole plot instead of only the graph area. What can you suggest? Thanks!
x = c(28,1,4,17,2)
lbl = c("1","2","3","4+","tough guys\n(type in)")
bp = barplot(x,names.arg=lbl,main="Ctrl-C clicks",col="grey")
text(x = bp, y = x, label = x, pos = 3, cex = 0.8, col = "red",font=2)
Plot example:
You can fix this by extending the ylim
bp = barplot(x,names.arg=lbl,main="Ctrl-C clicks",col="grey", ylim=c(0,30))
Another solution using ggplot2:
library(ggplot2)
x = c(28,1,4,17,2)
lbl = c("1","2","3","4+","tough guys \n(type in)")
test <- data.frame(x, lbl)
bp = ggplot(test, aes(x=lbl, y= x))+
geom_bar(color = "grey", stat="identity")+ ## set color of bars and use the value of the number in the cells.
geom_text(aes(label= x), vjust = -1, color = "red")+
ggtitle("Ctrl-C clicks")+
theme_bw()+ ## give black and white theme
theme(plot.title = element_text(hjust = 0.5),## adjust position of title
panel.grid.minor=element_blank(), ## suppress minor grid lines
panel.grid.major=element_blank() ##suppress major grid lines
)+
scale_y_continuous(limits = c(0,30)) ## set scale limits
bp
I would like to draw a chart with ggplot for a couple of model accuracies. The detail of the plotted result doesn't matter, however, I've a problem to fill the geom_point objects.
A sample file can be found here: https://ufile.io/z1z4c
My code is:
library(ggplot2)
library(ggthemes)
Palette <- c('#A81D35', '#085575', '#1DA837')
results <- read.csv('test.csv', colClasses=c('factor', 'factor', 'factor', 'numeric'))
results$dates <- factor(results$dates, levels = c('01', '15', '27'))
results$pocd <- factor(results$pocd, levels = c('without POCD', 'with POCD', 'null accuracy'))
results$model <- factor(results$model, levels = c('SVM', 'DT', 'RF', 'Ada', 'NN'))
ggplot(data = results, group = pocd) +
geom_point(aes(x = dates, y = acc,
shape = pocd,
color = pocd,
fill = pocd,
size = pocd)) +
scale_shape_manual(values = c(0, 1, 3)) +
scale_color_manual(values = c(Palette[1], Palette[2], Palette[3])) +
scale_fill_manual(values = c(Palette[1], Palette[2], Palette[3])) +
scale_size_manual(values = c(2, 2, 1)) +
facet_grid(. ~ model) +
xlab('Date of knowledge') +
ylab('Accuracy') +
theme(legend.position = 'right',
legend.title = element_blank(),
axis.line = element_line(color = '#DDDDDD'))
As a result I get unfilled circles and squares. How can I fix it, so that the squares and circles are filled with the specfic color?
Additional question: I would like to add a geom_line to the graph, connecting the three points in each group. However, I fail to adjust linetype and width. It always take the values of scale_*_manual, which is very adverse especially in the case of size.
Thanks for helping!
You need to change the shapes specified, like so:
scale_shape_manual(values = c(21,22,23)) +
For your additional question, that should be solved if you set aes(size=) in the first part of your code (under ggplot(data=...) and then manually specify size=1 under geom_line as +geom_line(size=1....`