I would like to change the dots in the next plot to the flag for the respective country. For this I know that geom_flag() could works, but... not for me but I got stuck with this error message:
Error in grobify(picture, x = x, y = y, width = width, height = height, :
object '.flaglist' not found
This is my code:
ggplot(df, aes(lenght, Ponto.Caspian)) +
geom_point()+ ggflags::geom_flag(aes(x = longitude, y = latitude+0.5, country = country))
maybe also geom_image() could work but I don't know how to link the flag with the country column...or How to use an image as a point in ggplot?, but I don't understand the process
This my desire plot, but changing dots to flags:
ggplot(df, aes(lenght, Ponto.Caspian)) +
geom_point(aes(colour = factor(country)))+
scale_fill_brewer(palette = "Set3")+ scale_x_continuous(breaks = seq(10, 40, by = 5))+
scale_y_continuous(breaks = seq(0, 16, by = 1))+
theme_classic2() + theme_cleveland()+ geom_smooth(method = "lm", alpha=0.2)+
stat_cor(label.x = 2, label.y = 1)
This is my data:
https://drive.google.com/drive/folders/1qR2mUdrpStOYBmxajc_F4nxS_qf-4bzf?usp=sharing
thanks in advance
It seems to work for me if I convert your countries to two-character ISO codes (which is what the example at https://github.com/jimjam-slam/ggflags uses).
I also had to load the ggflags library, rather than using ggflags::geom_flag
For example, using the countrycode package:
df$iso_code <- tolower(countrycode(df$country, origin = 'country.name', destination = 'iso2c'))
ggplot(df, aes(lenght, Ponto.Caspian)) +
geom_point() +
geom_flag(aes(x = longitude, y = latitude+0.5, country = iso_code))
Related
I would like to change the y axis label (or main title would also be fine) of a ggplot to reflect the column name being iterated over within an apply function.
Here is some sample data and my working apply function:
trial_df <- data.frame("Patient" = c(1,1,2,2,3,3,4,4),
"Outcome" = c("NED", "NED", "NED", "NED", "Relapse","Relapse","Relapse","Relapse"),
"Time_Point" = c("Baseline", "Week3", "Baseline", "Week3","Baseline", "Week3","Baseline", "Week3"),
"CD4_Param" = c(50.8,53.1,20.3,18.1,30.8,24.5,35.2,31.0),
"CD8_Param" = c(5.3,9.7,4.4,4.3,3.1,3.2,5.6,5.3),
"CD3_Param" = c(11.6,16.6,5.0,5.1,14.3,7.1,5.9,8.1))
apply(trial_df[,4:length(trial_df)], 2, function(i) ggplot(data = trial_df, aes_string(x = "Time_Point", y = i )) +
facet_wrap(~Outcome) +
geom_boxplot(alpha = 0.1) +
geom_point(aes(color = `Outcome`, fill = `Outcome`)) +
geom_path(aes(group = `Patient`, color = `Outcome`)) +
theme_minimal() +
ggpubr::stat_compare_means( method = "wilcox.test") +
scale_fill_manual(values=c("blue", "red")) +
scale_color_manual(values=c("blue", "red")))
Example plot output
This creates 3 graphs as expected, however the y axis just says "y". I would like this to display the column name for the column in that iteration. It would also be fine to add a main title with this information, as I just need to know which graph corresponds to which column.
Here are things I have already tried adding to the ggplot code above based on some similar questions I found, but all of them give me the error "non-numeric argument to binary operator":
ggtitle(paste(i))
labs(y = i)
labs(y = as.character(i))
Any help or resources I may have missed would be greatly appreciated, thanks!
So.....for the strangest of reasons I cannot figure out why. This gives what you want but for only one graph!!!
apply(trial_df[,4:length(trial_df)], 2, function(i) ggplot(data = trial_df, aes_string(x = "Time_Point", y = i )) +
facet_wrap(~Outcome) +
geom_boxplot(alpha = 0.1) +
geom_point(aes(color = `Outcome`, fill = `Outcome`)) +
geom_path(aes(group = `Patient`, color = `Outcome`)) +
theme_minimal() +
stat_compare_means( method = "wilcox.test") +
scale_fill_manual(values=c("blue", "red")) +
scale_color_manual(values=c("blue", "red"))+
labs(y=colnames(trial_df)[i]))
Gives these:
I was able to get plots that look like the attached image by using "\n" for the line break. However, the problem is the 8.8e-14. The journal requests I change it to 8.8x10^14 (with the 14 in superscript). However, that only works if I use expression(paste). But in that case, the "\n" doesn't cause a line break anymore. I've spent about 5 hours trial and erroring through different solutions on the internet to no avail. Does anyone have a solution? Thanks in advance.
What I would like it to look like (except I would like it to say 8.8x10^14 instead):
The below works EXCEPT there's no line break (I would like a line break before "Interaction")
plot_fun_to_revise = function(x, y) {
ggplot(data = data_for_median_plots, aes(x = .data[[x]], y = .data[[y]], group = Secretor, linetype = Secretor)) +
stat_summary(geom = "line", fun.data = median_hilow, size = 0.5) +
stat_sum_df_all("median_hilow",
fun.args = (conf.int = 0.5),
linetype = "solid",
size = 0.5) +
theme_classic()
lnnt_plot_median <- plot_fun_to_revise("Timepoint", "LNnT") +
ylim(0,5000) +
labs(y = paste("LNnT", "(\u03BCg/mL)"),
title = expression(paste("Time p = 8.8 x", 10^-14, ", Secretor p = 0.35, Interaction p = 0.51")),
x = "Time (months postpartum)"
Obviously, I don't have your data to replicate the plot itself, but since this is about labelling anyway, let's just make an (essentially) empty plot:
lnnt_plot_median <- ggplot(data.frame(x = 1, y = 1), aes(x, y)) +
geom_point() +
theme_classic() +
theme(text = element_text(face = 2, size = 16),
plot.title = element_text(hjust = 0.5))
Since you are using unicode escapes already, I think the easiest thing to do here is use the unicode escapes for superscript 1 and superscript 4:
lnnt_plot_median +
labs(y = paste("LNnT", "(\u03BCg/mL)"),
title = paste("Time p = 8.8 x 10\u00b9\u2074,",
"Secretor p = 0.35,\n Interaction p = 0.51"),
x = "Time (months postpartum)")
While creating a shot chart in R, I've been using some open source stuff from Todd W. Schneider's BallR court design (https://github.com/toddwschneider/ballr/blob/master/plot_court.R)
along with another Stack Overflow post on how to create percentages within hexbins (How to replicate a scatterplot with a hexbin plot in R?).
Both sources have been really helpful for me.
When I run the following lines of code, I get a solid hexbin plot of percent made for shots for the different locations on the court:
ggplot(shots_df, aes(x = location_y-25, y = location_x, z = made_flag)) +
stat_summary_hex(fun = mean, alpha = 0.8, bins = 30) +
scale_fill_gradientn(colors = my_colors(7), labels = percent_format(),
name = "Percent Made")
However, when I include the BallR court design code snippet, which is shown below:
ggplot(shots_df, aes(x=location_y-25,y=location_x,z=made_flag)) +
stat_summary_hex(fun = mean, alpha = 0.8, bins = 30) +
scale_fill_gradientn(colors = my_colors(7), labels=percent_format(),
name="Percent Made") +
geom_path(data = court_points,
aes(x = x, y = y, group = desc, linetype = dash),
color = "#000004") +
scale_linetype_manual(values = c("solid", "longdash"), guide = FALSE) +
coord_fixed(ylim = c(0, 35), xlim = c(-25, 25)) +
theme_court(base_size = 22)
I get the error: Error in eval(expr, envir, enclos) : object 'made_flag' not found, even though that the made_flag is 100% in the data frame, shots_df, and worked in the original iteration. I am lost on how to fix this problem.
I believe your problem lies in the geom_path() layer. Try this tweek:
geom_path(data = court_points, aes(x = x, y = y, z = NULL, group = desc, linetype = dash))
Because you set the z aesthetic at the top, it is still inheriting in geom_path() even though you are on a different data source. You have to manually overwrite this with z = NULL.
I am trying to run this following code:
p <- ggplot(data=cuernavaca.map, aes(long, lat, group=group))
p + geom_polygon(size=0.1, aes(fill=pobtot)) + coord_equal() + facet_wrap(~nombre_municipio,scales="free") + coord_equal() + scale_fill_gradient2(low="blue", high="red", midpoint=mean(cuernavaca.map$pobtot, na.rm=TRUE))+ tema.mapas + ggtitle("Cuervaca y Zona metropolitana\nPoblación Total") + labs(fill="Población total")
but I got this error:
Error: ggplot2 doesn't know how to deal with data of class uneval
The object cuernavaca.map is a fortified SpatialDataFrame.
The weird thing is that this only happens in one machine (Ubuntu 13.04, RStudio 0.97.551, R 3.0.1) when I execute the knit2html or I hit the button knit HTML, If I execute the lines of code in the console (inside RStudio) everything works (I mean, the plot is done), If I cut and paste that code in other .Rmd file it works and If I execute it in another Ubuntu box (same specs as above) or MacOS X, it works!
Any ideas?
UPDATE:
As is written in the comments, the problem seems to be the order of the unnamed parameters, so I change the code to this:
ggplot(data = cuernavaca.map) +
geom_polygon(mapping = aes(x = long, y = lat, group = group, colour = NA, fill = pobtot)) +
coord_equal() +
facet_wrap(~nombre_municipio, scales = "free") +
scale_fill_gradient2(low = "blue", high = "red", midpoint = mean(cuernavaca.map$pobtot,
na.rm = TRUE)) +
tema.mapas +
ggtitle("Cuervaca y Zona metropolitana\nPoblación Total") +
labs(fill = "Población total")
And know is everything working ... almost.
If you see the code I remove the size parameter in the geom_polygon and I set the colour to NA, I made that, not for aesthetics reasons, but because, that parameters are not working: the line width of the polygon gets enormous and the color is just ignored, sometimes gets light red, in others it just disappears...
As a funny thing, the plots below this one, are working now, too, but guess what? The code is the following:
ggplot(legend = FALSE) +
geom_polygon(data = cuernavaca.map, size = 0.1, aes(long,
lat, group = group, colour = "grey80", fill = ind_vul)) +
scale_fill_gradient2(low = "blue", high = "red", midpoint = mean(cuernavaca.map$ind_vul, na.rm = TRUE)) +
geom_point(data = puntos.df, aes(as.numeric(long), as.numeric(lat), colour = geografico), size = 2) +
facet_wrap(~municipio, scales = "free") +
tema.mapas +
labs(fill = "Índice de vulnerabilidad")
puntos.df is a data.frame with latitude and longitude, so no big deal, but not how the size parameters is out of the aes and is working (I am not getting a error of "not know how to deal with a numeric... blah blah")
Could be a memory issue?
As is told in the edit, the answer was using named parameters:
ggplot(data = cuernavaca.map) +
geom_polygon(mapping = aes(x = long, y = lat, group = group, colour = NA, fill = pobtot)) +
coord_equal() +
facet_wrap(~nombre_municipio, scales = "free") +
scale_fill_gradient2(low = "blue", high = "red", midpoint = mean(cuernavaca.map$pobtot, na.rm = TRUE)) +
There are some unanswered questions, but I posted a new one in: ggplot map with points: size, colour, legend, aesthetics problems
I'm trying to produce a facetted pie-chart with ggplot and facing problems with placing text in the middle of each slice:
dat = read.table(text = "Channel Volume Cnt
AGENT high 8344
AGENT medium 5448
AGENT low 23823
KIOSK high 19275
KIOSK medium 13554
KIOSK low 38293", header=TRUE)
vis = ggplot(data=dat, aes(x=factor(1), y=Cnt, fill=Volume)) +
geom_bar(stat="identity", position="fill") +
coord_polar(theta="y") +
facet_grid(Channel~.) +
geom_text(aes(x=factor(1), y=Cnt, label=Cnt, ymax=Cnt),
position=position_fill(width=1))
The output:
What parameters of geom_text should be adjusted in order to place numerical labels in the middle of piechart slices?
Related question is Pie plot getting its text on top of each other but it doesn't handle case with facet.
UPDATE: following Paul Hiemstra advice and approach in the question above I changed code as follows:
---> pie_text = dat$Cnt/2 + c(0,cumsum(dat$Cnt)[-length(dat$Cnt)])
vis = ggplot(data=dat, aes(x=factor(1), y=Cnt, fill=Volume)) +
geom_bar(stat="identity", position="fill") +
coord_polar(theta="y") +
facet_grid(Channel~.) +
geom_text(aes(x=factor(1),
---> y=pie_text,
label=Cnt, ymax=Cnt), position=position_fill(width=1))
As I expected tweaking text coordiantes is absolute but it needs be within facet data:
NEW ANSWER: With the introduction of ggplot2 v2.2.0, position_stack() can be used to position the labels without the need to calculate a position variable first. The following code will give you the same result as the old answer:
ggplot(data = dat, aes(x = "", y = Cnt, fill = Volume)) +
geom_bar(stat = "identity") +
geom_text(aes(label = Cnt), position = position_stack(vjust = 0.5)) +
coord_polar(theta = "y") +
facet_grid(Channel ~ ., scales = "free")
To remove "hollow" center, adapt the code to:
ggplot(data = dat, aes(x = 0, y = Cnt, fill = Volume)) +
geom_bar(stat = "identity") +
geom_text(aes(label = Cnt), position = position_stack(vjust = 0.5)) +
scale_x_continuous(expand = c(0,0)) +
coord_polar(theta = "y") +
facet_grid(Channel ~ ., scales = "free")
OLD ANSWER: The solution to this problem is creating a position variable, which can be done quite easily with base R or with the data.table, plyr or dplyr packages:
Step 1: Creating the position variable for each Channel
# with base R
dat$pos <- with(dat, ave(Cnt, Channel, FUN = function(x) cumsum(x) - 0.5*x))
# with the data.table package
library(data.table)
setDT(dat)
dat <- dat[, pos:=cumsum(Cnt)-0.5*Cnt, by="Channel"]
# with the plyr package
library(plyr)
dat <- ddply(dat, .(Channel), transform, pos=cumsum(Cnt)-0.5*Cnt)
# with the dplyr package
library(dplyr)
dat <- dat %>% group_by(Channel) %>% mutate(pos=cumsum(Cnt)-0.5*Cnt)
Step 2: Creating the facetted plot
library(ggplot2)
ggplot(data = dat) +
geom_bar(aes(x = "", y = Cnt, fill = Volume), stat = "identity") +
geom_text(aes(x = "", y = pos, label = Cnt)) +
coord_polar(theta = "y") +
facet_grid(Channel ~ ., scales = "free")
The result:
I would like to speak out against the conventional way of making pies in ggplot2, which is to draw a stacked barplot in polar coordinates. While I appreciate the mathematical elegance of that approach, it does cause all sorts of headaches when the plot doesn't look quite the way it's supposed to. In particular, precisely adjusting the size of the pie can be difficult. (If you don't know what I mean, try to make a pie chart that extends all the way to the edge of the plot panel.)
I prefer drawing pies in a normal cartesian coordinate system, using geom_arc_bar() from ggforce. It requires a little bit of extra work on the front end, because we have to calculate angles ourselves, but that's easy and the level of control we get as a result is more than worth it.
I've used this approach in previous answers here and here.
The data (from the question):
dat = read.table(text = "Channel Volume Cnt
AGENT high 8344
AGENT medium 5448
AGENT low 23823
KIOSK high 19275
KIOSK medium 13554
KIOSK low 38293", header=TRUE)
The pie-drawing code:
library(ggplot2)
library(ggforce)
library(dplyr)
# calculate the start and end angles for each pie
dat_pies <- left_join(dat,
dat %>%
group_by(Channel) %>%
summarize(Cnt_total = sum(Cnt))) %>%
group_by(Channel) %>%
mutate(end_angle = 2*pi*cumsum(Cnt)/Cnt_total, # ending angle for each pie slice
start_angle = lag(end_angle, default = 0), # starting angle for each pie slice
mid_angle = 0.5*(start_angle + end_angle)) # middle of each pie slice, for the text label
rpie = 1 # pie radius
rlabel = 0.6 * rpie # radius of the labels; a number slightly larger than 0.5 seems to work better,
# but 0.5 would place it exactly in the middle as the question asks for.
# draw the pies
ggplot(dat_pies) +
geom_arc_bar(aes(x0 = 0, y0 = 0, r0 = 0, r = rpie,
start = start_angle, end = end_angle, fill = Volume)) +
geom_text(aes(x = rlabel*sin(mid_angle), y = rlabel*cos(mid_angle), label = Cnt),
hjust = 0.5, vjust = 0.5) +
coord_fixed() +
scale_x_continuous(limits = c(-1, 1), name = "", breaks = NULL, labels = NULL) +
scale_y_continuous(limits = c(-1, 1), name = "", breaks = NULL, labels = NULL) +
facet_grid(Channel~.)
To show why I think this this approach is so much more powerful than the conventional (coord_polar()) approach, let's say we want the labels on the outside of the pie rather than inside. This creates a couple of problems, such as we will have to adjust hjust and vjust depending on the side of the pie a label falls, and also we will have to make the
plot panel wider than high to make space for the labels on the side without generating excessive space above and below. Solving these problems in the polar coordinate approach is not fun, but it's trivial in the cartesian coordinates:
# generate hjust and vjust settings depending on the quadrant into which each
# label falls
dat_pies <- mutate(dat_pies,
hjust = ifelse(mid_angle>pi, 1, 0),
vjust = ifelse(mid_angle<pi/2 | mid_angle>3*pi/2, 0, 1))
rlabel = 1.05 * rpie # now we place labels outside of the pies
ggplot(dat_pies) +
geom_arc_bar(aes(x0 = 0, y0 = 0, r0 = 0, r = rpie,
start = start_angle, end = end_angle, fill = Volume)) +
geom_text(aes(x = rlabel*sin(mid_angle), y = rlabel*cos(mid_angle), label = Cnt,
hjust = hjust, vjust = vjust)) +
coord_fixed() +
scale_x_continuous(limits = c(-1.5, 1.4), name = "", breaks = NULL, labels = NULL) +
scale_y_continuous(limits = c(-1, 1), name = "", breaks = NULL, labels = NULL) +
facet_grid(Channel~.)
To tweak the position of the label text relative to the coordinate, you can use the vjust and hjust arguments of geom_text. This will determine the position of all labels simultaneously, so this might not be what you need.
Alternatively, you could tweak the coordinate of the label. Define a new data.frame where you average the Cnt coordinate (label_x[i] = Cnt[i+1] + Cnt[i]) to position the label in the center of that particular pie. Just pass this new data.frame to geom_text in replacement of the original data.frame.
In addition, piecharts have some visual interpretation flaws. In general I would not use them, especially where good alternatives exist, e.g. a dotplot:
ggplot(dat, aes(x = Cnt, y = Volume)) +
geom_point() +
facet_wrap(~ Channel, ncol = 1)
For example, from this plot it is obvious that Cnt is higher for Kiosk than for Agent, this information is lost in the piechart.
Following answer is partial, clunky and I won't accept it.
The hope is that it will solicit better solution.
text_KIOSK = dat$Cnt
text_AGENT = dat$Cnt
text_KIOSK[dat$Channel=='AGENT'] = 0
text_AGENT[dat$Channel=='KIOSK'] = 0
text_KIOSK = text_KIOSK/1.7 + c(0,cumsum(text_KIOSK)[-length(dat$Cnt)])
text_AGENT = text_AGENT/1.7 + c(0,cumsum(text_AGENT)[-length(dat$Cnt)])
text_KIOSK[dat$Channel=='AGENT'] = 0
text_AGENT[dat$Channel=='KIOSK'] = 0
pie_text = text_KIOSK + text_AGENT
vis = ggplot(data=dat, aes(x=factor(1), y=Cnt, fill=Volume)) +
geom_bar(stat="identity", position=position_fill(width=1)) +
coord_polar(theta="y") +
facet_grid(Channel~.) +
geom_text(aes(y=pie_text, label=format(Cnt,format="d",big.mark=','), ymax=Inf), position=position_fill(width=1))
It produces following chart:
As you noticed I can't move labels for green (low).