this is my first question here, i try to describe my problem the best possible. (i am sorry, if i am not successful with that)
i want to make a barplot in ggplot while using facet_grid.
plot1<-ggplot(data2,aes(x=fc4mean,y=Fraktion,fill=methode))+
facet_grid(~Standort, scales="free_y",)+
geom_barh(stat="identity",aes(fill=methode), position=position_dodge2(),width = 0.3)+
theme_bw()+
theme(axis.text.x = element_text(hjust = 1))+
scale_fill_brewer(palette = "Greys",direction=-1)+
scale_color_brewer("Black")+
theme(legend.title=element_blank())+
ylab("fraction")+
guides(colour = guide_legend(reverse=T))+
geom_errorbar(aes(xmin=fc4mean-fc4sd, xmax=fc4mean+fc4sd),position=position_dodge2(),width=0.3)
it works, but the standard settings make the bars huge and ugly. so i decided to set bar widths to 0.3. the problem is that then the groups of bars are far away from each other. so i tried to reduce the spacing.
i tried a lot of different approaches, for example workarounds with
position=position_dodge()
or
scale_y_discrete(expand = c(0, 2))+
to remove spacing between the 2 factor ticks on the y-axis. this worked but then i have massive empty space at the top and the bottom of the panels.
i tried to condense the plot with
theme(plot.margin = unit(c(5,0,5,0), "cm"))
which did not help at all.
as i am not willing to give up and merge the plot in paint, i hope somebody has a nice idea how to deal with the width of the bars, the spacing between the bars, and the spacing of the panels in facet grid.
hoping for some nice input, cheers :)
with the help of your comments, i was able to create a decent plot by using the commands
scale_y_discrete(expand=expansion(c(0,2)))
position=position_dodge()
width = ()
and by adjusting the aspect ratio of the plot windows.
thank you
Related
I have a chart that has strings for its x axis (a list of names). It's linked to a dynamic array, I have a problem where the graph resizes itself and squeezes 14-15 strings from the array and makes the bar chart small and tiny.
How can I achieve chunky bars and a scroll bar to scroll down to see the rest of the data even when new values are being added to the x-axis at runtime.
Have spent an hour searching with no help! =[
Edit:
Setting the PixelPointWidth Property to 300 gave me the width of the bar the way I want to be, but it has bunched the bars so that all the bars of the 4 series are overlapping instead of being side by side. WHere to go from here?
Edit2:
Manipulating the charts height is definitely getting the desired results, the only thing is the bigger the height, the more white space at the top of the chart, whats the fix for that,. and a fix for the Series representations to be "frozen" on scroll.
You can set the width of the chart every time you add new data to it:
Dim barWidth = Double.Parse(Chart1.Series(0)("PixelPointWidth"))
Chart1.Width = CInt(nData * barWidth) + 100
where nData is how many points there are and the 100 is some amount to take into account the space needed for the Y-axis labels and the legend.
Place the chart control in a Panel as suggested by jmcilhinney with AutoScroll set to true, and you will get a scrollbar when the width of the chart exceeds the width of the panel.
If you want the chart to show the latest added data, you can set the horizontal scroll position after setting the width of the chart:
Panel1.HorizontalScroll.Value = Panel1.HorizontalScroll.Maximum
I'm having some issues in setting the ticks in my plots using matplotlib. What I need is to set the ticks inwards, so inside the figure (but the labels must stay outside), and at the same time I need to have ticks on all four boundaries. Do you know a simple way to do this?
Thanks in advance!
Just because it can be useful for other people, I post here the simple solution I found after looking for some time in the documentation, as suggested by cfort:
ax.xaxis.set_ticks_position('both')
ax.xaxis.set_tick_params(direction='in', which='both', labelsize=16)
ax.yaxis.set_ticks_position('both')
ax.yaxis.set_tick_params(direction='in', which='both', labelsize=16)
ax.minorticks_on()
these lines of code set the tick inwards on both sides (e.g. for the x axis they are placed at top and bottom of the figure), set the label size and add the minorticks, which will point in the inward direction as well.
I want to set the width and height of a mpld3 plot to a specific value (in pixels, so it fits the div it is in). The way I tried it looks like this (javascript):
commands["width"]=plotWidth;
commands["height"]=plotHeight;
mpld3.draw_figure("plotname",commands);
plotWidth and plotHeight the values I want the height and width to be set to.
Now, this actually sets the size of the mpld3-figure object to the values I want, but the plot inside still keeps its old size, so it looks like nothing happened.
So, how do I change the size of the plot itself? So far it looks like whatever I do, the plot does not change.
You can change the shape of an mpld3 plot when creating a figure with the python code plt.figure(figsize=(width,height)) (where width and height are in inches). Here is a notebook demonstrating this.
There has been some interest in making mpld3 figures "responsive", which would be a cooler and more precise way to accomplish your goal, but so far no one has tried making the necessary code changes. Patches welcome!
Is there a way to render the tick labels just right inside the axes, i.e, something like the direction property there is on the ticks themself?
Right now I'm setting the x property to a positive value on the ticklabels to draw them inside of the axis, i.e.,
ax2.set_yticklabels(['0', '2500', '5000', '7500'], minor=False, x=0.05)
But this doesn't really work on resizable plots, as the 0.05 figure is absolute (and too big on big plots).
Any ideas?
I'm assuming that ax2 is constructed as ax2 = ax.twinx(), which is to say that it is on the right side of the axes.
You could do something like the following:
ax2.set_yticklabels(['0', '2500', '5000', '7500'], minor=False, horizontalalignment='right')
for tick in ax2.yaxis.get_major_ticks():
tick.set_pad(-8)
If you want the left side axis on the inside too, then you'd simply switch the horizontal alignment to 'left' and change the pad from -8 to -25.
The two numbers might not be exact and could depend on other matplotlib settings you might have (e.g. length of major ticks) so you may want to increase or decrease those values slightly.
I'm trying to get and set the position of a draggable legend in matplotlib. My application consists of an interactive GUI, which has a redraw/plot function that should perform the follow steps:
save the position of the current legend.
clear the current axes and perform various plotting operations, which may or may add labels to their plots.
build a new draggable legend (ax.legend().draggable()) and restore the old position of the legend.
In between these steps the user is free to drag the legend around, and the goal is to persist the legend position when the plots are redrawn.
My first approach was to use oldpos = legend.get_bbox_to_anchor() and legend.set_bbox_to_anchor(oldpos) in steps 1 and 3. However this causes to move the legend completely off the visible area.
Note that I have to use ax.legend() and cannot use fig.legend(lines, labels), since step 2 is completely decoupled, i.e., I don't know anything about lines and labels in step 3. According to answers to the question How to position and align a matplotlib figure legend? there seems to be a difference between these two possibilities regarding axes or figure coordinates. Obviously my problem calls for figure coordinates, but I haven't fully understood how to convert the bbox to a "bbox in figure coordinates".
The even more severe problem I just realized is that apparently legend.get_bbox_to_anchor() always seems to return the same values irrespective of the drag position. So maybe the anchor can only be (ab-)used to manipulate the position of static legends? Is there another/proper way to save and restore the position of a draggable legend?
By looking at the implementation of Legend I found out that there is an undocumented property _loc, which exactly does what I want. My solution now looks astonishingly simple:
oldLegPos = ax.get_legend()._loc
# perform all plotting operations...
legend = ax.legend().draggable()
legend._loc = oldLegPos
It looks like _loc automatically stores figure coordinates, since I do not have to convert the coordinates in any way (eg. when the plotting operations completely change the axes ranges/coordinates).