When I use stat_contour with polygon, some regions should not be filled because there is no data there, i marked them in the figure. Does anyone know how to avoid that? In addition, there is space between axis and plot region, how to remove it?!
Here is the plotting code:
plot_contour <- function (da, native ) {
h2d<-hist2d(da$germ_div,da[[native]],nbins=40,show=F)
h2d$counts<-h2d$counts+1
counts<-log(h2d$counts, base=10)
rownames(counts)<-h2d$x
colnames(counts)<-h2d$y
counts<-melt(counts)
names(counts)<-c('x','y','z')
ggplot(counts,aes(x,y))+
stat_contour(expand=c(0,0),aes(z=z,fill=..level..),geom='polygon')+
stat_contour( data=counts[counts$x<=75,],aes(z=z,fill=..level..),bins=50,geom='polygon')+
scale_fill_gradientn(expand=c(0,0),colours=rainbow(1000),
limits=c(log(2,base=10),4),na.value='white',guide=F)+
geom_contour(aes(z=z,colour=..level..),size=1.5)+
scale_color_gradientn(colours=rainbow(30),limits=c(log(2,base=10),4),na.value='white',
guide=F) + theme_bw()+
scale_x_continuous(expand=c(0,0),limits=c(0,50))+
scale_y_continuous(expand=c(0,0),limits=c(40,100))+
labs(x=NULL, y=NULL, title=NULL)+
theme(axis.text.x = element_text(family='Times', colour="black", size=20, angle=NULL,
hjust=NULL,vjust=NULL,face="plain"),
axis.text.y = element_text( family='Times', colour="black", size=20,angle=NULL,
hjust=NULL,vjust=NULL,face="plain")
)
}
da<-read.table('test.txt',header=T)
i<-'test'
plot_contour(da,i)
This didn't fit in a comment, so posting as an answer:
stat_contour doesn't handle polygons that aren't closed very well. Additionally, there is a precision issue that crops up when setting the bins manually whereby the actual contour calculation can get freaked out (this happens when the contour bins are the same as plot data but aren't recognized as the same due to precision issues).
The first issue you can resolve by expanding your grid by 1 all around in every direction, and then setting every value in in the matrix that is lower than the lowest you care about to some arbitrarily low value. This will force the contour calculation to close all the polygons that would otherwise be open at the edges of the plot. You can then set the limits with coord_cartesian(xlim=c(...)) to have your axes flush with the graph.
The second issue I don't know of a good way to solve without modifying the ggplot code. You may not be affected by this issue.
#BrodieG
Your answer is correct, but it's a bit difficult without some code.
Adding the following lines, with appropriate x,y values (these are a best guess), makes things clearer:
xlim(-10, 60)+
ylim(30, 120)+
coord_cartesian(xlim=c(0, 50),ylim=c(40, 100))
Related
I want to create a number of boxplots in 1 graphic to compare the different boxplots. The code I've written works, but the results differ so much that the graphic is basically useless. Because there are so many outliers, you can't see the actual boxplot. I want to limit the y-axis so that it only shows results up to a certain point, but this also actually limits the results, which I don't want! In other words, I want the y-axis to only show results up to y=70, but I want the results of 70 or above to still be calculated into the results. When I use the ylim function, this does not actually include the results that aren't in the limit. So, how do I limit my graphic, but only graphically and not the actual results?
I'm using ggplot. This is the code, although I doubt it is helpful since there the question is theoretical.
ggplot(dataorgrec,aes(x=Soortnieuw,y=AantalGRFBYE,fill=GRFBYE))+
geom_boxplot()+
ggtitle("Aantal recensies van categorieën van organisaties \n (beperkt tot 70 recensies per organisatie)")+ theme(plot.title = element_text(hjust = 0.5))+
ylab("Aantal recensies")+xlab("")+ylim(0,100)+
scale_fill_manual(values=c("#1D8DB0","#8EA9DB","#DCE7F0"),name="",labels=c("Google Review","Facebook","Yelp"))+
scale_x_discrete(labels = function(x) str_wrap(x, width = 10))
From comments:
Set the limits via coord_cartesian(ylim = ...) instead of via ylim(). Doing so will "zoom" on the desired range. See e.g. How to set limits for axes in ggplot2 R plots?
A problem occurs when i add a colour(gradient) into the aesthetics of geom_line. It seems that the dots are no longer connected by a line but instead transformed into squares, which messes up the plot. Does anyone have an idea how to solve this problem or if this is how R or ggplot handles colour(gradients). This problem doesn't occur, when i remove the colours from the aes().
Thanks in advance!
Simple code:
df <- data.frame(c(1,3,4,2,5,8),c(1,2,3,4,5,6))
colnames(df) <- c("x","y")
ggplot()+
theme_classic()+
geom_line(data=df,aes(x=x,y=y,colour=y),size=2)
ggplot()+
theme_classic()+
geom_line(data=df,aes(x=x,y=y),size=2)
Adjusting the lineend parameter should do it, which has a default of "square". The reason the uncolored version looks okay is that in those cases the segments are treated as continuations of the same series, so they are governed then by the linejoin parameter, which has a default of "round."
ggplot()+
theme_classic()+
geom_line(data=df,aes(x=x,y=y,colour=y),size=2, lineend = "round")
PS - if you want the color to vary within each segment, you might look at alternatives like ggforce::geom_link2, which uses interpolation to allow smooth transitions. However, it's parameterized differently, to be like geom_path, which plots data in order of appearance rather than in order of the x value, like geom_line.
I'm having a trouble with the binwidth of my col graphics.
I'm trying to show the highest/lowest suicide rate by country on the same page using shiny.
But, the country names are overlaping one another as you can see below:
How can i adjust this?
There are quite a few possibilities for resizing and adjusting things so that your long axis labels "fit" on a column plot (or any other ggplot for that matter). I'll go through some options here.
First of all... a sample dataset, since we did not get a suitable reprex from your question.
df <- data.frame(
x=c('Text1', 'Text2', 'Long Text Here', 'Really Really Long Text Label Here', 'Text5', 'Text6', 'Text7'),
y=c(sample(1:20, 7, replace=TRUE)))
df$x <- factor(df$x, levels=df$x) # making sure ggplot doesn't alphabetically sort!
library(ggplot2)
p <- ggplot(df, aes(x,y)) +
geom_col(aes(fill=x), show.legend = FALSE)
p
There's your overlapping labels. Now for some options:
Option #1: Resize the plot
One very simple method to "solving" the problem is to realize that R handles graphics... kind of funny. The look of a particular plot depends on the resolution and aspect ratio of the graphics device. Not only that, but text does not scale the same as the other plot elements. This means that you can fix the problem by forcing a different aspect ratio.
# this was used to create the above plot
ggsave('original.png', width=8, height=5)
# changing the aspect ratio produces the plot below on my graphics device
ggsave('resized.png', width=12, height=5)
Option #2: Change the Text Size
The other option is to make your text size for the axis labels smaller. The result is really similar to just resizing the plot.
p + theme(axis.text.x=element_text(size=6))
Option #3: Angle the Text
One really good option is to angle your text using the theme() element again. Note that when you do this you want to change the default alignment of your labels. Set hjust=1 so that the text is "right aligned". If you are setting your angle to 90°, you will also want to set your vjust=0.5 to make the text aligned with the tick mark vertically. Here I'll show you a 45° angled text option:
p + theme(axis.text.x=element_text(angle=45, hjust=1))
Option #4: Wrap Text Labels
One of my go-to favorite options here is to wrap the text label. There are a few ways to do this, but I prefer using wrap_format() from the scales package and a scale_* function. Note, the number given to wrap_format(X) indicates that wrapping should happen after X number of characters in the label.
library(scales)
p + scale_x_discrete(labels=wrap_format(22))
Option #5: Combine all Above
The best way to fix your problem is to use a combination of all techniques above to get the chart to look the way you believe looks most satisfying. This will depend on how many columns you have in your shiny plot and how you generate that plot (user input or always the same, etc). So it's up to you here.
p + scale_x_discrete(name=NULL, labels=wrap_format(22)) +
scale_y_continuous(expand=expansion(mult=c(0,0.15))) +
theme_classic() + #important to put this before overwriting individual theme elements!
theme(
axis.text.x=element_text(angle=40, hjust=1, size=15),
axis.text.y=element_text(size=15),
panel.grid.major.y=element_line(color='gray75', linetype=2))
You can flip your graph horizontally, it will be better for the readers. You can add this to your graph to flip it:
coord_flip()
I've got some issue creating a map with ggplot2 above which I project points using geom_point. When exporting in pdf or in an other support, the point size varies (because she's absolute and not axis-relative). I've searched how to change that and found a lot of answers saying, that it was on purpose, because if it wasn't the case it would be changing to ellipse each time the axis proprtions change. I understand that, however, because I work on a map, I use coord_fixed to fix the output and avoid distorsions of my map, so if I was able to fix the point size relatively to the plot size, it wouldn't be a problem.
Is there some solution to do that? I've read some interesting things suggesting using geom_polygon to artificially create ellipses. But I have two problems with this method:
First I don't know how to implement that with my data, now I know the place where the centers of my points are, but how could I then later say how to define all the centers and then defin a filled circled polygon around?
Second I have used scale_size_continuous to plot smaller or bigger points relatively to other variable. How could I implement that with geom_polygon?
Facit: I would be happy either with the possibility of override the impossibility to determine a relative unit for the point size, or with some help to make me understand how I can create the same thing with the function geom_polygon.
I tried to join a small reproducible example here. It is only an example, the problem with my data is that I have a lot of closed small values (mainly 1, like the small dot in the reproducible example), and so they seem really good, but when exporting it can become very bigger and create a lot of problems by overplotting, which is the reason why I need to fix this ratio.
Link for the map informations and second link for map informations
dat <- data.frame(postcode=c(3012, 2000, 1669, 4054, 6558), n=c(1, 20, 40, 60, 80))
ch <- read.csv("location/PLZO_CSV_LV03/PLZO_CSV_LV03.csv", sep=";")#first link, to attribute a geographical location for each postcode
ch <- ch%>%
distinct(PLZ, .keep_all=TRUE)%>%
group_by(PLZ, N, E)%>%
summarise
ch <- ch%>%
filter(PLZ %in% dat$postcode)
ch <- ch%>%
arrange(desc(as.numeric(PLZ)))
dat <- dat%>%
arrange(desc(as.numeric(postcode)))
datmap <- bind_cols(dat, ch)
ch2 <- readOGR("location/PLZO_SHP_LV03/PLZO_PLZ.shp")#second link, to make the shape of the country
ch2 <- fortify(ch2)
a <- ggplot()+
geom_polygon(dat=ch2, aes(x=long, y=lat, group=group), colour="grey75", fill="grey75")+
geom_jitter(data=datmap, aes(x=E, y=N, group=FALSE, size=n), color=c("red"))+ #here I put geom_jitter, but geom_point is fine too
scale_size_continuous(range=c(0.7, 5))+
coord_fixed()
print(a)
Thanks in advance for the help!
You can use ggsave() to save the last plot and adjust the scaling factor used for points/lines etc. Try this:
ggplot(data = ch2) +
geom_polygon(aes(x=long, y=lat, group=group),
colour="grey85", fill="grey90") +
geom_point(data=datmap, aes(x=E, y=N, group=FALSE, size=n),
color=c("red"), alpha = 0.5) +
scale_size_continuous(range=c(0.7, 5)) +
coord_fixed() +
theme_void()
ggsave(filename = 'plot.pdf', scale = 2, width = 3, height = 3)
Play around with the scale parameter (and optionally the width and height) until you are happy with the result.
DO NOT use geom_jitter(): this will add random XY variation to your points. To deal with overplotting you can try adding transparency - I added an alpha parameter for this. I also used theme_void() to get rid of axes and background.
Your shape file with map information is quite heavy: you can try a simple one with Swiss cantons, like this one.
Please, help me with this point. I need the positive values to be represented as small points and negative as large points. If I tape minus before size, the point sizes are right but the legend is changing:
df=data.frame(x=rnorm(20),y=runif(20),z=rnorm(20))
ggplot(df,aes(x=x,y=y))+geom_point(aes(size=-z))
so that does not suite.
One solution would be to use scale_size() and set your own breaks and then labels in opposite direction. Changed range of z values to get better representation.
df=data.frame(x=rnorm(20),y=runif(20),z=(-13:6))
ggplot(df,aes(x=x,y=y))+geom_point(aes(size=-z))+
scale_size("New legend",breaks=c(-10,-5,0,5,10),labels=c(10,5,0,-5,-10))
Little late, but an easier way would just to add trans='reverse' to scale_size.
Example:
df=data.frame(x=rnorm(20),y=runif(20),z=z=(-13:6))
ggplot(df,aes(x=x,y=y))+
geom_point(aes(size=z)) +
scale_size(trans = 'reverse')
While this question is very old - and has an accepted answer - the comment from baptiste that suggests using last_plot() + scale_size(range = c(5,1)) + guides(size = guide_legend(reverse=TRUE)) works very elegantly and simply. For my data where I needed to produce the same result as OP, this worked with zero modification required.