Why is Pandas inverting my x-axis order? [duplicate] - pandas

This question already has answers here:
x-axis inverted unexpectedly by pandas.plot(...)
(2 answers)
Closed 4 years ago.
When I was plotting two series of data against eachother, the X axis was inverted unexpectedly. I know this question sounds pretty similar to this other: x-axis inverted unexpectedly by pandas.plot(...) and it actually is, but I want to know if this can be disabled or something, not a workaround. Let me explain myself.
I have a very simple DF that consists on a datetime index and two columns; one has humidity measurements and the other daily weights. Both of them are in descending order because when my sample loses water, it also loses weight and humidity. So my DF looks something like this, where my data is in descending order
But then, when I plot using X = "Peso" (weight), and Y = 'Humedad' (humidity), my X axis goes in ascending order insted of descending order.
My ploting code:
plt.figure(figsize=(12,9))
plt.scatter(data['Peso'],data['Humedad'])
plt.xlabel('Peso (kg)',fontsize=14)
plt.ylabel("Raw Counts",fontsize=14)
plt.xticks(rotation=90,fontsize=10)
plt.grid()
Resulting in this kind of plot, where X axis is inverted
So, I could do two simple types of workaround:
plt.scatter(sorted(data['Peso']),data['Humedad'])
or
plt.scatter(data['Peso'][::-1],data['Humedad'])
Both of them have the same result, they print my data as I wanted, BUT my xticks are still inverted:
So what I did was creating a list with my weight values in order to insert it as it follows:
semin=data['Peso']
semin=semin.tolist()
And then adding it to my plt.xticks like this
plt.xticks(semin,rotation=90,fontsize=10)
It "kind off" worked, overlaping some of the xticks as you can see in the image below:
I know I can solve this with [Locs] and general xticks information, but I really wanted to know if it's possible to just ask Pandas to follow the natural data descending order or anything similiar and avoiding all of this xticks stuff?
I've checked this too: https://github.com/pandas-dev/pandas/issues/10118
and I tried by doing the set_index suggestion:
plt.figure(figsize=(12,9))
data.set_index('Peso').Humedad.plot()
plt.xlabel('Peso (kg)',fontsize=14)
plt.ylabel("Raw Counts",fontsize=14)
plt.xticks(rotation=90,fontsize=10)
plt.grid()
And it went almost perfect, except that I needed it in scatter...
So I tried some stuff to "scatter it"
1. Putting the marker type:
data.set_index('Peso').Humedad.plot(marker='o')
Got a marker + line graph:
2. Changing .plot for .scatter to the plot:
data.set_index('Peso').Humedad.scatter()
Got this error:
AttributeError: 'Series' object has no attribute 'scatter'
3. Using both
data.set_index('Peso').Humedad.plot.scatter()
Got this one:
AttributeError: 'SeriesPlotMethods' object has no attribute 'scatter'
4. Making this giant question. Please help.
And that's all, sorry if I'm missing something or if my post is too long. I'm open to suggestions, corrections or anything you're willing to tell me.
Thanks!

Oh I just saw that the linked question actually does exactly what you need. Will leave this as here. But please refer to the linked question instead.
It's not a solution to change the ticks! The resultung plot may easily get completely wrong.
Instead google for "invert x axis" or so and find that you can invert the axis via
ax = df.plot(...)
ax.invert_xaxis()
This is not a workaround. It is the solution. (How much easier can it get?)

Related

Altair sorting Chart

I'm trying to plot the data of my DataFarme in a groupedChart and I want the columns to preserve the order I gave them before. The data looks as follows (its not all there but its in the same way organized)
dataframe
When I plot it I get the following Graph:
graph
So the months were sorted even though I specified not to sort in the chart. I used the following code:
chart2 = alt.Chart(melted).mark_bar().encode(
column=alt.Column('variable',sort=None),
x=alt.X('room',sort=None),
y=alt.Y('value'),
color='room',
tooltip= ['room', 'value']
)
Does anyone know how I could fix that?
You've already used sort=None, which is the correct way to make scales in a non-faceted chart reflect the input order.
The missing piece is that faceted charts share scales by default (See Scale and Guide Resolution), so each facet is being forced to share an order.
If you make the x scale resolution independent, then each facet should retain the input order:
chart2 = alt.Chart(melted).mark_bar().encode(
column=alt.Column('variable',sort=None),
x=alt.X('room',sort=None),
y=alt.Y('value'),
color='room',
tooltip= ['room', 'value']
).resolve_scale(x='independent')

How can I plot this kind of picture using Matplotlib or Mayavi?

I have three 2d arrays: X,Y,Z, which contain irregular 3d points coordinate,respectively.And another 2d array data, which contains the values on those points.
What I want to do is to display this data in 3d space , with 0 value part masked out.Much like this one:
In matlab, I can use function fill3 to achieve this, but how can I plot the same kind of picture in matplotlib or mayavi ? I have tried to use mask array ,plot_surface and colorface together, as the example here:
Plotting a masked surface plot using python, numpy and matplotlib
and it worked, the result is the link below:
but that is really really slow, and will cost too much time. Is there a better way?
Well, today I find out an alternative way to solve the problem. Except using plot_surface, I choose to use scatter3D,
the core code is some what like this
aa=np.shape(X)[0]
bb=np.shape(X)[1]
x=X.reshape(aa*bb)
y=Y.reshape(aa*bb)
z=Z.reshape(aa*bb)
data=data.reshape(aa*bb)
x1=[]
y1=[]
z1=[]
da1=[]
for i in range(aa*bb):
if data[i]>0:
x1.append(x[i])
y1.append(y[i])
z1.append(z[i])
da1.append(data[i])
my_cmap=cm.jet
my_cmap.set_over('c')
my_cmap.set_under('m')
N=da1/max(da1)
fig=plt.figure()
ax=fig.add_subplot(111,projection='3d')
ax.scatter3D(x1,y1,z1,s=6,alpha=0.8,marker=',',facecolors=my_cmap(N),lw=0)
and the result is like this:
this doesn't really solve the problem, but it is a nice substitution.
I'll keep waiting for more answers.

How do I include a matplotlib Figure object as subplot? [duplicate]

This question already has an answer here:
Embed matplotlib figure in larger figure
(1 answer)
Closed 8 years ago.
How can I use a matplotlib Figure object as a subplot? Specifically, I have a function that creates a matplotlib Figure object, and I would like to include this as a subplot in another Figure.
In short, here's stripped-down pseudocode for what I've tried:
fig1 = plt.figure(1, facecolor='white')
figa = mySeparatePlottingFunc(...)
figb = mySeparatePlottingFunc(...)
figc = mySeparatePlottingFunc(...)
figd = mySeparatePlottingFunc(...)
fig1.add_subplot(411, figure=figa)
fig1.add_subplot(412, figure=figb)
fig1.add_subplot(413, figure=figc)
fig1.add_subplot(414, figure=figd)
fig1.show()
Sadly, however, this fails. I know for a fact the individual plots returned from the function invocations are viable--I did a figa.show(),...,figd.show() to confirm that they are OK. What I get for the final line in the above code block--fig1.show()--is
a collection of four empty plots that have frames and x- and y- tickmarks/labels.
I've done quite a bit of googling around, and experimented extensively, but it's clear that I've missed something that is either really subtle, or embarrassingly obvious (I'll be happy for it to be the latter as long as I can get un-stuck).
Thanks for any advice you can offer!
You can't put a figure in a figure.
You should modify your plotting functions to take axes objects as an argument.
I am also unclear why the kwarg figure is there, I think it is an artifact of the way that inheritance works, the way that the documentation is auto-generated, and the way some of the getter/setter work is automated. If you note, it says figure is undocumented in the Figure documentation, so it might not do what you want;). If you dig down a bit, what that kwarg really controls is the figure that the created axes is attached too, which is not what you want.
In general, moving existing axes/artists between figures is not easy, there are too many bits of internal plumbing that need to be re-connected. I think it can be done, but will involving touching the internals and there is no guarantee that it will work with future versions or that you will get warning if the internals change in a way that will break it.
You need to your plotting functions to take an Axes object as argument. You can use a pattern like:
def myPlotting(..., ax=None):
if ax is None:
# your existing figure generating code
ax = gca()
so if you pass in an Axes object it gets drawn to (the new functionality you need), but if you don't all of your old code will work as expected.

Easiest way to plot values as symbols in scatter plot?

In an answer to an earlier question of mine regarding fixing the colorspace for scatter images of 4D data, Tom10 suggested plotting values as symbols in order to double-check my data. An excellent idea. I've run some similar demos in the past, but I can't for the life of me find the demo I remember being quite simple.
So, what's the easiest way to plot numerical values as the symbol in a scatter plot instead of 'o' for example? Tom10 suggested plt.txt(x,y,value)- and that is the implementation used in a number of examples. I however wonder if there's an easy way to evaluate "value" from my array of numbers? Can one simply say: str(valuearray) ?
Do you need a loop to evaluate the values for plotting as suggested in the matplotlib demo section for 3D text scatter plots?
Their example produces:
(source: sourceforge.net)
However, they're doing something fairly complex in evaluating the locations as well as changing text direction based on data. So, is there a cute way to plot x,y,C data (where C is a value often taken as the color in the plot data- but instead I wish to make the symbol)?
Again, I think we have a fair answer to this- I just wonder if there's an easier way?
The easiest way I've seen to do this is:
for x, y, val in zip(x_array, y_array, val_array):
plt.text(x, y, val)
Also, btw, you suggested using str(valarray), and this, as you may have noticed doesn't work. To convert an array of numbers to a sequence of strings you could use
valarray.astype(str)
to get a numpy array, or,
[str(v) for v in valarray]
to get a Python list. But even with valarray as a proper sequence of strings, plt.text won't iterate over it's inputs.

Octave colorbar and units

In GNU Octave you can make a picture where different colors represent different values in a matrix. You can also add a colorbar, which shows what color corresponds to what value.
Is it possible to somehow add units to the values shown in the colorbar? Instead of saying “0.36” it would say “0.36 V/nm”? I know this is possible in Matlab, but I can’t figure out how to do it in Octave. Any good workarounds?
I assume someone here will mention that I should use matplotlib instead (that usually happens). How would you accomplish the same thing with that?
The matplotlib answer (using pylab) is
imshow(random((20,20)))
colorbar(format='%.2f V/nm')
In Octave it seems that the following works (but I'm no Octave expert so maybe there's a better way):
c=colorbar();
labels = {};
for v=get(c,'ytick'), labels{end+1} = sprintf('%.2f V/nm',v); end
set(c,'yticklabel',labels);