problem: I want to keep the column with the width I define (0.20); however, I would like to put the columns closer. I am trying to use position_dodge to do it but it doesn't seem to work (I change the width of the position_dodge but I see no change in the output).
data:
SITE N CHL sd se ci
SITE1 20 0.01037453 0.004217003 0.0009429505 0.001973618
SITE2 20 0.01704401 0.006188691 0.0013838333 0.002896396
SITE3 19 0.01191036 0.004188927 0.0009610057 0.002018998
script:
dodge <- position_dodge(width = 0.25)#this is the width I try to change to get the columns closer, but it doesn't do it
ggplot() + geom_bar(data=s_site2chl, aes(x=SITE, y=CHL, fill=SITE),
stat="identity", colour="black", width = .20, position = dodge)
To use position_dodge() does not help, because there is nothing in your plot. The position only matters, if you have several bars with the same x-value. Then, you need to choose, whether you want to stack them on top of each other ("stack"), next to each other ("dodge"), or let them overplot each other ("identity"). But you have only one bar per x-value and thus position is irrelevant.
You can bring the bars closer together by making them wider, as others have suggested. If you set width = 1, the bars will touch, if you choose a smaller value, there will still be a gap:
ggplot() + geom_bar(data=s_site2chl, aes(x=SITE, y=CHL, fill=SITE),
stat="identity", colour="black", width = .8)
You say in one of your comments, that you only want to bring the bars closer together, but not make them wider. I can see at least two ways to achieve this. One would be to just save the plot with a different resolution. The figure above is 590 pixels wide and 380 pixels high. If I store it with half the width, I get this:
The second possibility is that you expand the x-axis more on both sides. You can use scale_x_discrete() as follows:
ggplot() + geom_bar(data=s_site2chl, aes(x=SITE, y=CHL, fill=SITE),
stat="identity", colour="black", width = .8) +
scale_x_discrete(expand = c(0, 2))
expand takes a vector of two with the following meaning (from ?discrete_scale):
a numeric vector of length two, giving a multiplicative and additive constant used to expand the range of the scales so that there is a small gap between the data and the axes. The defaults are (0,0.6) for discrete scales and (0.05,0) for continuous scales.
I set the additive value to 2 (instead of the default 0.6), which adds more space on both sides of the bars and as a result makes them thinner.
Related
I am trying to create a scatterplot based on four values. My data is just lists of prices (BASIC,VALUE,DELUXE,ULTIMATE). I want VALUE and DELUXE to be the two axis (x,y) and then have the size and color of the points represent the data for the other two columns.
It is hard to set up a reproducible example, because it is only an issue when I get a lot of values listed. i have about 300 points, with about 30 different color/value labels(For ULTIMATE, and 20 size/value labels(For BASIC)
> gg <- ggplot(d, aes(x=DELUXE_PRICE, y=VALUE_PRICE,color=ULTIMATE_PRICE,size=BASIC_PRICE)) + geom_point(alpha = 1)
> plot(gg)
My code does this well, and lists the colors/size with the corresponding value on the side. This is great, but I would like to alter how that is displayed, so that it is not cut off. I would like to be able to "wrap" the values into more columns, or shrink the display size of those so that they fit.
Currently, this lists ULTIMATE in three columns, to the right of the plot area, but cuts off the top of the labels (it extends well above the plot area)
This lists BASIC size/value labels to the right of the plot area, below ULTIMATE labels, in one column, so about half are cut off at the bottom.
I can increase the margins with:
> gg <- ggplot(d, aes(x=DELUXE_PRICE, y=VALUE_PRICE,color=ULTIMATE_PRICE,size=BASIC_PRICE)) + geom_point(alpha = 1) +theme(plot.margin = unit(c(4,2,4,2), "cm"))
> plot(gg)
This gets more of it in, but creates lots of white area and a smaller view of the plot. I would like to be able to just increase the right margin if necessary, and "wrap" the labels in more columns extending to the right. (i.e. put ULTIMATE into 4 columns instead of 3, and put BASIC into 3-4 columns instead of 1 - So that they are shorter and don't run out the plot area.
There is some built in functionality I found to do the required operation. It lies in adding a guides() argument to the plot, specifying whether I am dealing with the color or size legend, and specifying the number of columns with "ncol = " (You can also specify rows). Giving it an order ranking allows you to rank these as well, so my resulting code was:
> gg <- ggplot(Table, aes(x=DELUXE_PRICE, y=VALUE_PRICE,color=ULTIMATE_PRICE,size=BASIC_PRICE)) + geom_point(alpha = 1) + guides(color = guide_legend(order = 0,ncol = 4),size = guide_legend(order = 1,ncol = 4))
I have a plot in which I am trying to highlight different points along the line. My plot looks like this:
library(ggplot2)
X<-c(seq(1:20))
Y<-c(2,4,6,3,5,8,6,5,4,3,2,4,6,6,9,8,9,5,4,3)
Col<-as.character(c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5))
value<-c(NA,NA,NA,NA,10,NA,NA,NA,20,NA,NA,20,20,10,NA,NA,NA,10,NA,NA)
DF<-data.frame(X,Y,Col,value)
p<-ggplot(DF, aes(x=X, y=Y)) +geom_line(size=.02) +geom_point(col='black', size=.5)+ geom_jitter(aes(color = Col, size = value),position = position_jitter(height = .2, width = .2)) + scale_colour_manual(values=c("red", "violetred","orange",'blue','steelblue'))
p+guides(size = "none")
On top of the basic line plot, I have 5 different colored dot possibilities defined by the "Col" column. I also have 2 different size classes I'd like to represent using the "value" column. My issue is that the default sizes chosen to represent the "value" column is scaled so that the larger size appears too big in the plot in comparison to the smaller size.
Is there a way to manually set the scale so I can control the drawn size of the added points (hopefully make them closer is size to each other)? The final plot should be similar to the one here, only the value=10 points would be only slightly smaller than than the value=20 points.
I've tried using some of the "manual" options, but when I do it always plots the other "Y" column points, which for now are suppressed because of the NAs
In the same way you manually define the colours for your points using a scale_colour_ variant, you can define the sizes using scale_size.
In this case you can define the range of sizes to use. Adding + scale_size(range = c(4,6)) seems to give results that fit your description. You can tweak the size of, and the difference in size between the points by changing the numbers.
Take a look at the following plotting code:
library(ggplot2)
library(cowplot)
a <- data.frame(a1=1:10, a2=1:10)
b <- data.frame(b1=1:5, b2=2*(1:5))
aplot <- ggplot(a, aes(x=a1, ymin=0, ymax=12)) +
geom_line(aes(y=a2))
bplot <- ggplot(b, aes(x=b1, ymin=0, ymax=12)) +
geom_line(aes(y=b2))
plot_grid(aplot,bplot, ncol=2)
It yields two side-by-side plots of identical dimensions showing similar lines. But the x-axis scales are rather different. In fact, the second line has twice the slope of the first.
I am looking for a way to plot this figure so that the width of a plot is scaled by the limits of its x-axis, so that the slopes can be compared visually. The real plots I am interested in visualizing are five in number and will lack y-axis labels except for the leftmost. I can use grid.arrange() to plot them all in a row with whatever widths I want, but the problem is that I don't know what width to assign to each panel to make sure they come out right (the panel width has to be large enough to accommodate the plot margins, the y-axis tick marks, and the y-axis text). I can set the margins myself and account for them in my panel widths, but I cannot find a good way to figure out how wide (e.g. in cm) the y-axis text is.
You can use the rel_widths option in plot_grid to achieve this. You need to calculate the relative size you want each plot to be using the ratio of the ranges xmax-xmin of each panel. But, there is an extra catch. rel_widths sets the relative width of the whole panel, including the margins. So we also need to account for the margins in calculating the relative size. In the following code, adding an offset value of 2 to the numerator and denominator of relative.size works for this. But note that this offset value may change if you alter the size of the margins.
aplot <- ggplot(a, aes(x=a1, ymin=0, ymax=12, xmin=0, xmax=max(a$a1))) +
geom_line(aes(y=a2))
bplot <- ggplot(b, aes(x=b1, ymin=0, ymax=12, xmin=0, xmax=max(b$b1))) +
geom_line(aes(y=b2))
relative.size <- (2+max(b$b1)) / (2+max(a$a1)) # the addition of 2 here is to account for the plot margins
plot_grid(aplot,bplot, ncol=2, rel_widths=c(1,relative.size), align = "h")
gives
I'm having trouble creating a figure with ggplot2. I am using geom_dotplot with center stacking to display my data which are discrete values for 4 categories.
For aesthetic reasons I want to customize the positions of the dots so that
reduce the empty space between dots along the y axis, (ie the dots are 1 value large)
The distributions fit and don't overlap
I've adjusted the bin and dotsize to achieve aesthetic goal 1, but that requires me to fiddle with the ylim() parameter to make sure that the groups fit in the plot. This results in a plot with more whitw space and few numbers on the y axis.
Question: Can anyone explain a way to resize the empty space on this plot?
My code is below:.
plot <- ggplot(figdata, aes(y=Counts, x=category, col=strain)) +
geom_dotplot(aes(fill=strain), dotsize=1, binwidth=.7,
binaxis= "y",stackdir ="centerwhole", stackratio=.7) +
ylim(18,59)
plot + scale_color_manual(values=c("#E69F00", "#56B4E9")) +
geom_errorbar(stat="hline", yintercept="mean",
aes( ymax=..y..,ymin=..y.., group = category, width = 0.5),
color="black")
Which produces:
EDIT: Incorporating jitter will allow the all the data to fit, but I don't want to add noise to this data and would prefer to show it as discreet data.
adjusting the binwidth and dotsize to 0.3 as suggested below also fits all the data, however it leaves too much white space.
I think that I might have to transform my data so that the values are steps smaller than 1, in order to get everything to fit horizontally and dot sizes to big large enough to reduce white space.
I think the easiest way is using coord_cartesian:
plot + scale_color_manual(values=c("#E69F00", "#56B4E9")) +
geom_errorbar(stat="hline", yintercept="mean",
aes( ymax=..y..,ymin=..y.., group = category, width = 0.5),
color="black") +
coord_cartesian(ylim=c(17,40))
Which gives me this plot (with fake data that are not as neatly distributed as yours):
I want to draw vertical boxplots of counts, and show the counts as points, overlaid over the boxplots. Because they are discrete values, there are going to be multiple points with the same value. To show the data in ggplot2, I could use geom_jitter() to spread the data and get a slightly better impression, but jitter screws up the values (the vertical component), and the randomness of the horizontal spread means that if the jitter height is set to 0, there is still a high chance of overlapping points.
Is there a way to spread all points which have the same value, evenly and horizontally? Something along the lines of this:
Here is some example data:
wine_votes <- melt(list(a=c(7,7,7,8,8,7,7,8,4,7,7,6,8,6),
b=c(5,8,6,4,3,4,4,9,5,8,4,5,4),
c=c(7.5,8,5,8,6,8,5,6,6.5,7,5,5,6),
d=c(4,4,5,5,6,8,5,8,5,6,3,6,5),
e=c(7,4,6,7,4,6,7,5,6.5,8.5,8,5)
))
names(wine_votes) <- c('vote', 'option')
# Example plot with jitter:
ggplot(wine_votes, aes(x=blend, y=vote)) +
geom_boxplot() + geom_jitter(position=position_jitter(height=0, width=0.2)) +
scale_y_continuous(breaks=seq(0,10,2))
While this isn't exactly what the image looks like it can be adjusted to get there. geom_dotplot (added in version 0.9.0-ish I think) does this:
ggplot(wine_votes, aes(x=option, y=vote)) +
geom_boxplot() +
scale_y_continuous(breaks=seq(0,10,2)) +
geom_dotplot(binaxis = "y", stackdir = "center", aes(fill=option))