matplotlib swap x and y axis - python

Hello I have made a plot in matplot lib using pandas however I need to swap my x and y axis.
Here is my plot:
broomstick plot
however i need it to look like this:
correct broomstick plot
I'm using a pandas dataframe to plot the data.
I've looked over some documentation and other posts regarding swapping the x and y axis and haven't found any easy way to do this.
Here some of my python code:
python code
Any resources or ideas would be greatly appreciated.

Try this. You need to include your y_vals as an additional column. So with this you can just specify your axis here df.plot(x=, y=):
Code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 100)
y = np.cos(x)
df = pd.DataFrame({'y': y, 'x': x})
df.plot(x='x')
plt.show()
df.plot(x='y')
plt.show()
Plots:

Related

pandas.DataFrame.plot showing colormap inconsistently

So am trying to make some plots and was trying to use the cmap "jet". It kept appearing as viridis, so I dug around SE and tried some very simple plots:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 100)
y = x
t = x
df = pd.DataFrame([x,y]).T
df.plot(kind="scatter", x=0, y=1, c=t, cmap="jet")
x = np.arange(0, 100.1)
y = x
t = x
df = pd.DataFrame([x,y]).T
df.plot(kind="scatter", x=0, y=1, c=t, cmap="jet")
Any thoughts on what is going on here? I can tell that it has something to do with the dtype of the fields in the dataframe (added dypte="float" to the first set of code and got the same result as in the second set of code), but don't see why this would be the case.
Naturally, what I really would like is a workaround if there isn't something wrong with my code.
It actually seems to be related to pandas (scatter) plot and as you've pointed out to dtype float - some more details at the end.
A workaround is to use matplotlib.
The plot is looking the same in the end, but the cmap="jet" setting is also applied for float dtype:
Code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
x = np.arange(0, 100.1)
y = x
t = x
df = pd.DataFrame([x,y]).T
fig, ax = plt.subplots(1,1)
sc_plot = ax.scatter(df[0], df[1], c=t, cmap="jet")
fig.colorbar(sc_plot)
ax.set_ylabel('1')
ax.set_xlabel('0')
plt.show()
Or the shorter version (a little bit closer to the brief df.plot call) using pyplot instead of the Object Oriented Interface:
df = pd.DataFrame([x,y]).T
sc_plot = plt.scatter(df[0], df[1], c=t, cmap="jet")
plt.colorbar(sc_plot)
plt.ylabel('1')
plt.xlabel('0')
plt.show()
Concerning the root cause why pandas df.plot isn't following the cmap setting:
The closest I could find is that pandas scatter plot c takes
str, int or array-like
(while I'm not sure why t isn't referring to the index which would be int again).
Even df.plot(kind="scatter", x=0, y=1, c=df.index.values.tolist(), cmap='jet') falls back to viridis, while df.index.values.tolist() clearly is just int.
Which is even more strange, as pandas df.plot also uses matplotlib by default:
Uses the backend specified by the option plotting.backend. By default,
matplotlib is used.
Looks like it's a new bug in pandas 1.5.0. Reverting pandas to 1.4.4 fixes it. So if you don't need 1.5.0 per se, I'd suggest to reinstall 1.4.4 until the bugfix.

Transposing x and y axes with matplotlib and pandas

I'm trying to use a bar chart to visualize my csv data. The data looks like this:
question,count_1,count_2,count_3,count_4,count_5
Q1,0,0,6,0,0
Q2,6,0,0,0,0
Q3,3,2,1,0,0
Q4,0,0,6,0,0
Q5,6,0,0,0,0
Q6,0,6,0,0,0
Q7,6,0,0,0,0
Q8,0,0,0,5,1
Q9,1,4,0,0,1
Q10,0,0,1,5,0
Here is my code
import pandas as pd
import csv
import matplotlib.pyplot as plt
df = pd.read_csv('example.csv')
ax = df.set_index(['question']).plot.bar(stacked=True)
ax.legend(loc='best')
plt.show()
Which gives me:
What I'm trying to do is flip the x and y axes. I want the bars to be horizontal and y axis to be the questions. I tried to transpose my data frame using:
ax = df.set_index(['question']).T.plot.bar(stacked=True)
but that gives me:
which is not what I want. Can anyone help?
to get the bars horizontally (flip the x and y axis), you need to use barh (horizontal bar). More info here. So, the code would be...
import pandas as pd
import csv
import matplotlib.pyplot as plt
df = pd.read_csv('example.csv')
ax = df.set_index(['question']).plot.barh(stacked=True)
ax.legend(loc='best')
plt.show()
Output plot

Develop wireframe to plot aircraft tracks with Lat, Lon and Alt

I am unable to draw a wireframe (not a map) with Lat, Lon and Alt.
My data looks like this:
latitude longitude altitude
0 53.65947 -1.43819 14525
1 53.65956 -1.43921 14525
2 53.65979 -1.44066 14500
3 53.66025 -1.44447 14475
4 53.66044 -1.44591 14475
Here is what I have so far:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.animation as animation
df = pd.read_csv('/home/luke/Downloads /dump1090-127_0_0_1-170911.txt', sep=',',skiprows=0, low_memory=False)
y = df['latitude']
x = df['longitude']
z = df['altitude']
plt.xticks(range(-3,0))
plt.yticks(range(50,60))
ax = plt.axes(projection='3d')
df1 = df1.dropna()
Help would be greatly appreciated.
The reason your code is not plotting anything is that it isn't complete. You haven't included a plot command.
Suggest reading the documentation and looking at examples when you are trying to do something new.
In the example linked to above, you will see that the plot3D command is used to actually make the plot. If you add this to your code it should work.
ax.plot3D(x, y, z)
plt.show()
Also, note that a 3D wireframe plot is something different. I'm not sure it would be useful for plotting the path of an aeroplane.

Seaborn violin plot over time given numpy ndarray

I have a distribution that changes over time for which I would like to plot a violin plot for each time step side-by-side using seaborn. My initial attempt failed as violinplot cannot handle a np.ndarray for the y argument:
import numpy as np
import seaborn as sns
time = np.arange(0, 10)
samples = np.random.randn(10, 200)
ax = sns.violinplot(x=time, y=samples) # Exception: Data must be 1-dimensional
The seaborn documentation has an example for a vertical violinplot grouped by a categorical variable. However, it uses a DataFrame in long format.
Do I need to convert my time series into a DataFrame as well? If so, how do I achieve this?
A closer look at the documentation made me realize that omitting the x and y argument altogether leads to the data argument being interpreted in wide-form:
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
samples = np.random.randn(20, 10)
ax = sns.violinplot(data=samples)
plt.show()
In the violin plot documentation it says that the input x and y parameters do not have to be a data frame, but they have a restriction of having the same dimension. In addition, the variable y that you created has 10 rows and 200 columns. This is detrimental when plotting the graphics and causes a dimension problem.
I tested it and this code has no problems when reading the python file.
import numpy as np
import seaborn as sns
import pandas as pd
time = np.arange(0, 200)
samples = np.random.randn(10, 200)
for sample in samples:
ax = sns.violinplot(x=time, y=sample)
You can then group the resulting graphs using this link:
https://python-graph-gallery.com/199-matplotlib-style-sheets/
If you want to convert your data into data frames it is also possible. You just need to use pandas.
example
import pandas as pd
x = [1,2,3,4]
df = pd.DataFrame(x)

Howto force Pandas and native matplotlib to share axis

I folks,
Consider the following example
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
fig, (ax1,ax2) = plt.subplots(2,1)
dates = pd.date_range("2018-01-01","2019-01-01",freq = "1d")
x = pd.DataFrame(index = dates, data = np.linspace(0,1,len(dates)) )
x.plot(ax=ax1)
y = np.random.random([len(dates),100]) * x.values
ax2.pcolormesh(range(len(x)), np.linspace(-1,1,100), y.T)
plt.show()
At this point, I would like the both axis (ax1,ax2) to share the x-axis, i.e. displaying proper pandas dates on the second axis. sharex=True does not seem to work. How can I achieve that? I tried different possibilities which did not work out.
Edit: Since the pandas date formatting is superior to the native matplotlib formatting, please provide me with a solution where pandas date formatting is used (for instance, zooming with an interactive environment works much better with pandas date formatting). Thanks You!
One way to do it would be to do all the plotting with matplotlib, this way there are no problems with the different time formats being used:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
fig, (ax1,ax2) = plt.subplots(2,1, sharex='col')
dates = pd.date_range("2018-01-01","2019-01-01",freq = "1d")
x = pd.DataFrame(index = dates, data = np.linspace(0,1,len(dates)) )
#x.plot(ax=ax1)
ax1.plot(x.index, x.values)
y = np.random.random([len(dates),100]) * x.values
ax2.pcolormesh(x.index, np.linspace(-1,1,100), y.T)
fig.tight_layout()
plt.show()
This gives the following plot:
What seems to work fine is to first plot the same line into the axes that should host the image, then plot the image, then remove the line again. What this does is that it tells pandas to apply its locators and formatters to that axes; they will stay after removing the line.
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
fig, (ax1,ax2) = plt.subplots(2,1, sharex=True)
dates = pd.date_range("2018-01-01","2019-01-01",freq = "1d")
x = pd.DataFrame(index = dates, data = np.linspace(0,1,len(dates)) )
x.plot(ax=ax1)
y = np.random.random([len(dates),100]) * x.values
x.plot(ax=ax2, legend=False)
ax2.pcolormesh(dates, np.linspace(-1,1,100), y.T)
ax2.lines[0].remove()
plt.show()
Note that there may be caveats of this solution when zooming or panning. Consider it more like a hack and use it as long as it works, but don't blame anyone once it doesn't.

Categories

Resources