Reshape group labels in ggradar - r

When using ggradar long variable names don't fit the pane. Is there a way to reshape the variable names in ggradar?
Reproducible example:
library(ggradar)
suppressPackageStartupMessages(library(dplyr))
library(scales)
data <- data.frame(
group = c("A", "B", "C"),
variable_with_long_name_1 = c(0,1,0.5),
variable_with_long_name_2 = c(0,1,.5),
variable_with_long_name_3 = c(1,0,0.5)
)
ggradar(data)
This works and looks something like:
Any hints?

If I may, I suggest the use of ggRadar from ggiraphExtra:
library(ggiraphExtra)
g <- ggRadar(data, aes(color = group), scales = "free") +
theme_minimal() +
theme(text = element_text(size=7), # custom font size
axis.text.y = element_blank())
Plus you'll get to use the ggplot2 grammar.
Also I think it's better to use the simple ggsave, just play around with the dimension, you won't have to sacrifice text size:
g <- ggRadar(data, aes(color = group), scales = "free") +
theme_minimal() +
theme(axis.text.y = element_blank())
print(g)
ggsave("/plt.png", width = 16, height = 9, dpi = 120)
Data used:
data <- data.frame(
group = c("A", "B", "C"),
variable_with_long_name_1 = c(0,1,0.5),
variable_with_long_name_2 = c(0,1,.5),
variable_with_long_name_3 = c(1,0,0.5)
)

It's actually straight forward. ggradar allows to scale all labels:
Variable names are scaled by setting the axis.label.size option,
the scale labels by setting grid.label.size option and
the legend by setting the legend.label.size option.
So
library(ggradar)
suppressPackageStartupMessages(library(dplyr))
library(scales)
data <- data.frame(
group = c("A", "B", "C"),
variable_with_long_name_1 = c(0,1,0.5),
variable_with_long_name_2 = c(0,1,.5),
variable_with_long_name_3 = c(1,0,0.5)
)
ggradar(data, axis.label.size = 3, grid.label.size = 3, legend.text.size = 10)
plots to something like

library(ggradar)
suppressPackageStartupMessages(library(dplyr))
library(scales)
data <- data.frame(
group = c("A", "B", "C"),
"variable with long name"= c(0,1,0.5),
"variable with \n long name" = c(0,1,.5),
variable_with_long_name_3 = c(1,0,0.5)
)
ggradar(data)+
ggtitle("Title on \n two lines")
with other ggplot features I used "\n" inside long labels (like titles or names), but with ggradar it does not work. Maybe you can still use this as a hint to change something

Another method which might work, at least if you only have a few categories in your spider chart:
Add the text to the front of the graph, as indicated by Joachim Schork in the link below
https://statisticsglobe.com/add-bold-and-italic-text-to-ggplot2-plot-in-r
ggp + # Add bold text element to plot, could be anything else like italic
annotate("text", x = 4.5, y = 2.2, size = 5,
label = "My Bold Text",
fontface = "bold")

I just had the same problem, but for me rescaling the label was not an option (readability). As the goal was to not have the labels clipped though, here is the solution i found:
There is the option plot.extent.x.sf which can be increased to extend the size of the plot horizontally. I set it to 2, and then also my longest feature label was plotted correctly.

Related

Display combination of Phonetic Characters on a ggplot graph using a different computer font

I'm creating graphic plots that contain IPA symbols (Phonetic symbols) using ggplot on R. The font used by ggplot looks great for most of the characters, but when it's a combination of characters, they look misaligned when displayed in the output. A combination of characters is something like this: t̪ (t + U032A) or ʈ͡ʂ (U0288+U0282+U0361).
This is the data.frame and code I used for the graph:
phones <- c("a", "e", "k", "ə", "ʈ͡ʂ", "n", "t͡ʃ", "n̪", "s", "l̪", "t̪")
freq <- c(34, 28, 29, 26, 10, 8, 5, 3, 2, 4, 1)
df <- data.frame(phones, freq)
library(ggplot2)
graph <- ggplot(subset(df, freq > 0), aes(x = reorder(phones, -freq), y = freq)) +
geom_bar(stat = "identity")
graph
png(
filename = "test.png",
height = 1500, width = 2500,
res = 300, units = "px")
graph + labs(title = "",
subtitle="",
caption = "",
x = "",
y = "")
dev.off(which = dev.cur())
This creates the following graph:
And I'm expecting something like this (characters in red using a special font Doulos SIL):
I think that I can specify the computer font Doulos SIL (Link to font) (or any other font that display combination of characters) before creating the graph in order to display neat characters, but I haven't been able to do so on my code. I'd appreciate any help, thanks!
As per the above comment, the solution for this answer is to indicate the font within the function theme() with a text option, for example:
graph <- ggplot(subset(df, freq > 0), aes(x = reorder(phones, -freq), y = freq)) +
geom_bar(stat = "identity") +
theme(text=element_text(family = "TT Doulos SIL"))

ggballonplot set limits for axis

To make the plots more comparable, I would like to set the limits of all fill- and symbol size axes to the same size. Is this possible? Also the legends for "size" and "fill" are swapping places in the last two plots, which I would like to prevent as well.
Thanks in advance!!!
ggballonplot chart
Some code as an example
library(ggplot2)
library(ggpubr)
plot4 <- ggballoonplot(data_matrix_comb, x = "Time", y = "Depth",
size = "mean_percentage_of_indivuals",
fill = "mean_variance", facet.by = "Stage",
ggtheme = theme_bw()) + scale_fill_viridis_c(option = "C") +
labs(title "Autumn")
library(gridExtra)
grid.arrange(plot1, plot2, plot3, plot4, ncol=2, nrow = 2)
You can use ggarrange() from ggpubr(),I would suggest a common legend since it doesn't make sense to have it 4 times.
I simulated some data since you did not provide (please do so in the future!).
Also slight variation from what you did, I placed all the data.frames inside a list, and if possible, you should try that so that you don't run the same code multiple times.. (i.e avoid copy-paste code):
library(ggplot2)
library(ggpubr)
library(dplyr)
set.seed(111)
dat = data.frame(Time=rep(c("day","night"),12),
Depth=rep(c("aphotic","euphotic"),each=2,times=6),
Stage = rep(c("adult","juvenil"),each=4),
mean_percentage_of_indivuals=100*runif(24),
mean_variance = rnbinom(24,mu=100,size=0.5))
dat_all = dat %>% group_by(Time,Depth,Stage) %>% summarize_all(mean)
dat_spring = dat[1:8,]
dat_summer = dat[9:16,]
dat_autumn = dat[17:24,]
dat_list = list("All Seasons"=dat_all,"Spring"=dat_spring,
"Summer"=dat_summer,"Autumn"=dat_autumn)
plts = lapply(names(dat_list),function(i){
p <- ggballoonplot(dat_list[[i]], x = "Time", y = "Depth",
size = "mean_percentage_of_indivuals",
fill = "mean_variance", facet.by = "Stage",
ggtheme = theme_bw()) +
scale_fill_viridis_c(option = "C") +
labs(title=i)
return(p)
})
ggarrange(plotlist =plts,ncol=2, nrow=2, common.legend = TRUE)

Interactive faceted rCharts bar graph filled with a third variable (replicate ggplot2 aes(x=var1, fill=var2) + geom_bar + facet_wrap)

I want to make an interactive bar chart of one variable where the bars are filled in by a second variable and faceted by a third variable. I would like to embed it in a slidify deck. I am guessing rCharts is the right tool for this (or would another package be better?).
Here is my data:
df <- data.frame(numbers = rep(1:3, 30),
letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
status = sample(c("good", "bad", "ugly"), 90, replace = TRUE))
I can do this in ggplot2, but I can't make it interactive. I can make this graph (sorry, can't embed):
ggplot(df, aes(letter, fill = status)) + geom_bar() + facet_wrap(.~numbers)
Ideally I would be able to select and deselect "status" and see the bars change. I've played with the bar chart code on this page but can't make it work. Is this functionality possible?
Maybe this is what you're after in ggplot? I couldn't tell if you wanted a ggplots solution or rCharts solution. So this is ggplot.
Add position = "dodge" to your geom_bar argument will mimic the other graph you linked to
ggplot(df, aes(letter, fill = status)) +
geom_bar(position = "dodge") +
facet_wrap(.~numbers)
Alternatively, you could "unselect" status, and fill by number -- note, had to make this a factor in this example:
ggplot(df, aes(letter, fill = as.factor(numbers))) +
geom_bar(position = "dodge") +
facet_wrap(.~numbers)
Or omit and keep grayscale
ggplot(df, aes(letter)) +
geom_bar(position = "dodge") +
facet_wrap(.~numbers)
I was a heavy rCharts user, but nowadays, in my opinion, plotly is a better supported option (rCharts is not in CRAN anymore).
Furthermoreplotly has an automatic way to make ggplot2 charts interactive. For your example:
library(ggplot2)
library(plotly)
df <- data.frame(
numbers = rep(1:3, 30),
letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
status = sample(c("good", "bad", "ugly"), 90, replace = TRUE)
)
p <-
ggplot(df, aes(letter, fill = status)) + geom_bar() + facet_wrap(. ~ numbers)
ggplotly(p)
EDIT 1
This edit is made to suit the needs of the comment.
The changes you requested cannot be made directly from ggplot2 so you need to use plotly. There may be a more elegant way to do the chart than my for loops but they seem to work:
library(data.table)
library(ggplot2)
library(plotly)
# make data.table
df <- data.table(
numbers = rep(1:3, 30),
letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
status = sample(c("good", "bad", "ugly"), 90, replace = TRUE)
)
# keep unique status values for bars and numbers for facets
traces <- df[,unique(status)]
facets <- df[,unique(numbers)]
# cast df
casted_df <- dcast(df,letter + numbers ~ status )
# initialise list to keep charts
facetplots <- list()
for(i in 1:length(facets)){
# initialise chart
facetplots[[i]] <- plot_ly(type = "bar")
facet_df <- casted_df[numbers == facets[i]]
for(j in traces){
if(i == 1){
facetplots[[i]] <- add_trace(facetplots[[i]], x = facet_df[,letter], y = facet_df[,get(j)],legendgroup = j , color = j, name = j )
}else{
facetplots[[i]] <- add_trace(facetplots[[i]], x = facet_df[,letter], y = facet_df[,get(j)],legendgroup = j, color = j , name = j , showlegend = F)
}
}
facetplots[[i]] <- layout( facetplots[[i]], barmode = "stack")
}
q <- subplot(facetplots, shareX = TRUE)
q

How can I force ggplot to show more levels on the legend?

I'm trying to create a complex ggplot plot but some things don't work as expected.
I have extracted the problematic part, the creation of points and its associated legend.
library(data.table)
library(ggplot2)
lev <- c("A", "B", "C", "D") # define levels.
bb <- c(40, 30,20,10,5)/100 # define breaks.
ll <- c("40%","30%","20%","10%","5%") # labels.
# Create data
nodos <- data.table(event = c("A", "B", "D", "C", "D"), ord = c(1, 2, 3, 3, 4),
NP = c(0.375, 0.25, 0.125, 0.125, 0.125))
ggplot() + geom_point(data=nodos,aes(x=ord,
y=event, size=NP), color="black", shape=16) +
ylim(lev) + scale_size_continuous(name="Prop.",
breaks=bb, labels=ll, range=c(0,6))+
scale_x_continuous(limits=c(0.5, 4.5),
breaks=seq(1,4,1))
As you can see, no matter what breaks and labels I use I'm not able to force ggplot to paint a legend containing 0% or 10%.
scale_size_continuous keeps creating just two elements.
And the smaller points are very badly scaled.
I have also tried with scale_scale_area, but it doesn't work either.
I'm using R 3.4.2 and ggplot2 2.2.1 (also tried the latest github version).
How can I get it?
If you set the limits to encompass the breaks you'll be able to alter the legend. Current most of the breaks are outside the default limits of the scale.
ggplot() +
geom_point(data = nodos,
aes(x = ord, y = event, size = NP), color="black", shape = 16) +
scale_size_continuous(name = "Prop.",
breaks = bb,
limits = c(.05, .4),
labels = ll,
range = c(0, 6) )

prevent a second aes() to override the range of the axes (ylim, xlim) in ggplot2

I have prices over time for different types of products. I want to visualize the evolution of different prices in one single sheet, so I am using a faceted ggplot. Here's my toy example:
df1 <- data.frame(time = rep(1:100, times = 5),
type = rep(c("A", "B", "C", "D", "E"), each = 100),
price = rnorm(n = 500, mean = 100))
gp <- ggplot(data = df1, aes(x = time, y = price))
# scales free because the price level of each product may be different
gp <- gp + facet_wrap(~type, nrow = 3, ncol = 2, scales = "free")
gp <- gp + geom_point() + geom_line()
gp
This produces the plot I want:
I also have reference prices for each type of product (in a different data set), and I want to indicate those prices in the plot. So I am using geom_hline() as follows:
df2 <- data.frame(type = c("A", "B", "C", "D", "E"),
refprice = c(100, 105, 95, 50, 40))
gp <- gp + geom_hline(data = df2, aes(yintercept = refprice), facets = ~type)
It works, but it can substantially change the range of the y-axis, and I do not want that. I'd like to keep the ylim as automatically generated by the first part, so as to properly visualize the evolution of the prices regardless of the reference price (it is ok not to see the reference price if it is not relatively close to the actual prices).
I know I can use scale_y_continuous(), coord_cartesian() or the short-hand ylim() to manually set the limits as I want, but I dislike this alternative because either requires hard-coding the limits or too much coding to calculate the appropriate limits. So I thought there must be a simpler and more elegant way in ggplot to avoid the second call to override ylims and instead take advantage of the ylims generated in the first call.
I have been searching (I think, thoroughly) for solutions to this issue (SO, google, rseek, ), and all I find involves the solutions I've just said I dislike. So I decided to post it here to see if someone knows some hidden (or not so hidden) feature in ggplot2 to make this easier and more elegant. Many thanks.
yrange <- sapply(ggplot_build(gp)$panel$ranges, function(x) x$y.range)
#order df2 correctly (the same order as the panels) if it isn't
gp + geom_hline(data = df2[df2$refprice >= yrange[1,] & df2$refprice <= yrange[2,],],
aes(yintercept = refprice))

Resources