Markers in beginning and end of line plots - python

I have 5 datasets that have thousands of x and y coordinates grouped by 'frame' that create 5 trajectory plots. I'd like to mark the first and last coordinates for each plot but having difficulty figuring it out. I am using Jupiter Notebook.
mean_pos1 = gr1.mean()
mean_pos2 = gr2.mean()
mean_pos3 = gr3.mean()
mean_pos4 = gr4.mean()
mean_pos5 = gr5.mean()
plt.figure()
xlim=(200, 1500)
ylim=(0, 1200)
ax1 = mean_pos1.plot(x='x', y='y',color='blue',label='Dolphin A'); ax1.set_title('mean trajectory');
ax2 = mean_pos2.plot(x='x', y='y',color='red',label='Dolphin B'); ax2.set_title('mean trajectory');
ax3 = mean_pos3.plot(x='x', y='y',color='green',label='Dolphin C'); ax3.set_title('mean trajectory');
ax4 = mean_pos4.plot(x='x', y='y',color='magenta',label='Dolphin D'); ax4.set_title('mean trajectory');
ax5 = mean_pos5.plot(x='x', y='y',color='cyan',label='Dolphin E'); ax5.set_title('mean trajectory');
ax1.set_xlim(xlim)
ax1.set_ylim(ylim)
ax2.set_xlim(xlim)
ax2.set_ylim(ylim)
ax3.set_xlim(xlim)
ax3.set_ylim(ylim)
ax4.set_xlim(xlim)
ax4.set_ylim(ylim)
ax5.set_xlim(xlim)
ax5.set_ylim(ylim)
plt.show()
the output of them looks like this:

Use the scatter method to plot the markers separately on the same axis by grabbing the first and last elements from your x and y series:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'x': np.random.normal(3,0.2,10), 'y': np.random.normal(5,0.3,10)})
fig, ax = plt.subplots()
df.plot(x='x', y='y', ax=ax)
ax.scatter(df['x'].iloc[0], df['y'].iloc[0], marker='o', color='red')
ax.scatter(df['x'].iloc[-1], df['y'].iloc[-1], marker='o', color='red')
plt.show()

Related

python - repositioning my legend using loc

this is the output of my code
as you can see both legends 'pl' and 'ppl' are overlapping at the top right. How do I get one of them to move to top left.
I tried searching for ans, and used "loc" to fix the issue, somehow I continue getting error. Can someone help please?
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.set_xlabel('Date')
ax1.set_ylabel('percent change / 100')
dd = pd.DataFrame(np.random.randint(1,10,(30,2)),columns=['pl','ppl'])
dd['pl'].plot(ax=ax1,legend=True)
dd['ppl'].plot(ax=ax2, style=['g--', 'b--', 'r--'],legend=True)
ax2.set_ylabel('difference')
plt.show()
Perhaps plot directly with matplotlib instead of using DataFrame.plot:
ax1.plot(dd['pl'], label='pl')
ax1.legend(loc='upper left')
ax2.plot(dd['ppl'], ls='--', c='g', label='ppl')
ax2.legend(loc='upper right')
Output:
I think you need to call legend on plot and position the legend accordingly. Please see below.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.set_xlabel('Date')
ax1.set_ylabel('percent change / 100')
dd = pd.DataFrame(np.random.randint(1,10,(30,2)),columns=['pl','ppl'])
dd['pl'].plot(ax=ax1, legend=True).legend(loc='center left',bbox_to_anchor=(1.0, 0.5))
dd['ppl'].plot(ax=ax2, style=['g--', 'b--', 'r--'],legend=True).legend(loc='upper right')
You can create the legend in several ways:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.set_xlabel("Date")
ax1.set_ylabel("percent change / 100")
dd = pd.DataFrame(np.random.randint(1, 10, (30, 2)), columns=["pl", "ppl"])
dd["pl"].plot(ax=ax1)
dd["ppl"].plot(ax=ax2, style=["g--", "b--", "r--"])
# # two separate legends
# ax1.legend()
# ax2.legend(loc="upper left")
# # a single legend for the whole fig
# fig.legend(loc="upper right")
# # a single legend for the axis
# get the lines in the axis
lines1 = ax1.lines
lines2 = ax2.lines
all_lines = lines1 + lines2
# get the label for each line
all_labels = [lin.get_label() for lin in all_lines]
# place the legend
ax1.legend(all_lines, all_labels, loc="upper left")
ax2.set_ylabel("difference")
plt.show()
The last one I left uncommented creates a single legend inside the ax, with both lines listed.
Cheers!

How to add a y label for each subplot in matplotlib

fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)
ax1.ylabel("raw")
ax2 = fig.add_subplot(2,1,2)
ax2.ylabel("smooth")
ax1.plot(a)
ax2.plot(smoothdata())
plt.show()
I need to be able to add y axis labels to each of the plots, i know how to do it with just one plot by doing plt.ylabel('raw") but how do i do it with multiple plots?
Axes object do not have method ylabel, use set_ylabel
ylabel() would be valid for matplotlib.pyplot. From the docs:
matplotlib.pyplot.ylabel(ylabel, fontdict=None, labelpad=None, **kwargs)
Example:
import matplotlib.pyplot as plt
plt.plot(x, y)
plt.ylabel("Label on plt")
plt.show()
If you have multiple plots (subplots) you must use set_ylabel() on each subplot axes:
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)
ax1.set_ylabel("raw") ### <---
ax2 = fig.add_subplot(2,1,2)
ax2.set_ylabel("smooth") ### <---
ax1.plot([i for i in range(0, 10)], [i for i in range(0, 10)])
ax2.plot([i for i in range(0, 20)], [i for i in range(0, 20)])
plt.show()
Outputs:

Matplotlib: how to remove spacing between a group of subplots

I have a series of pyplot subplots that I've created using a gridspec. They all have an hspace between them, which is fine, except that I would like to keep three of them without any space. Is there a way to do this? Currently, they look like this:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure()
grid_spec = gridspec.GridSpec(nrows=10, ncols=10)
grid_spec.update(hspace=1.5)
ax1 = plt.subplot(grid_spec[0:4, :])
ax2 = plt.subplot(grid_spec[4:7, :], sharex=ax1)
# I would like to group the next 3 together
# so that they are stacked top to bottom and side by side
ax3 = plt.subplot(grid_spec[7:8, :5])
ax4 = plt.subplot(grid_spec[8:, :5], sharex=ax3)
ax5 = plt.subplot(grid_spec[8:, 5:6], sharey=ax4)
plt.show()
I would like them to be arranged like this so I can plot the following 2-D KDE diagram and have the relevant 1-D diagrams above and to the right (roughly displaying this sort of data crudely drawn in paint):
I appreciate any help with this one. Can't seem to find documentation on this sort of thing. Thanks!
You can use mpl_toolkits.axes_grid1.make_axes_locatable to subdivide the area of a subplot of a 3 x 2 grid.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig = plt.figure()
gs = fig.add_gridspec(nrows=3, ncols=2, hspace=.5,
height_ratios=[4, 3, 3], width_ratios=[7, 4])
ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, :], sharex=ax1)
ax3 = fig.add_subplot(gs[2, 0])
div = make_axes_locatable(ax3)
ax4 = div.append_axes("top", "40%", pad=0.2, sharex=ax3)
ax5 = div.append_axes("right", "25%", pad=0.2, sharey=ax3)
ax4.tick_params(labelbottom=False)
ax5.tick_params(labelleft=False)
plt.show()
Also, you can create a subgridspec, like
import matplotlib.pyplot as plt
from matplotlib import gridspec
fig = plt.figure()
gs = gridspec.GridSpec(nrows=3, ncols=2, hspace=.5,
height_ratios=[4, 3, 3], width_ratios=[7, 4])
ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, :], sharex=ax1)
sub_gs = gridspec.GridSpecFromSubplotSpec(2,2, subplot_spec=gs[2,0], hspace=0.3, wspace=0.1,
height_ratios=[1,3], width_ratios=[3,1])
ax3 = fig.add_subplot(sub_gs[1,0])
ax4 = fig.add_subplot(sub_gs[0,0], sharex=ax3)
ax5 = fig.add_subplot(sub_gs[1,1], sharey=ax3)
ax4.tick_params(labelbottom=False)
ax5.tick_params(labelleft=False)
plt.show()
In both cases you will probably want to fine tune the parameters a bit. In general, the matplotlib gridspec tutorial gives a nice overview with many examples on this matter.

Seaborn plot with second y axis

i wanted to know how to make a plot with two y-axis so that my plot that looks like this :
to something more like this by adding another y-axis :
i'm only using this line of code from my plot in order to get the top 10 EngineVersions from my data frame :
sns.countplot(x='EngineVersion', data=train, order=train.EngineVersion.value_counts().iloc[:10].index);
I think you are looking for something like:
import matplotlib.pyplot as plt
x = [1,2,3,4,5]
y = [1000,2000,500,8000,3000]
y1 = [1050,3000,2000,4000,6000]
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.bar(x, y)
ax2.plot(x, y1, 'o-', color="red" )
ax1.set_xlabel('X data')
ax1.set_ylabel('Counts', color='g')
ax2.set_ylabel('Detection Rates', color='b')
plt.show()
Output:
#gdubs If you want to do this with Seaborn's library, this code set up worked for me. Instead of setting the ax assignment "outside" of the plot function in matplotlib, you do it "inside" of the plot function in Seaborn, where ax is the variable that stores the plot.
import seaborn as sns # Calls in seaborn
# These lines generate the data to be plotted
x = [1,2,3,4,5]
y = [1000,2000,500,8000,3000]
y1 = [1050,3000,2000,4000,6000]
fig, ax1 = plt.subplots() # initializes figure and plots
ax2 = ax1.twinx() # applies twinx to ax2, which is the second y axis.
sns.barplot(x = x, y = y, ax = ax1, color = 'blue') # plots the first set of data, and sets it to ax1.
sns.lineplot(x = x, y = y1, marker = 'o', color = 'red', ax = ax2) # plots the second set, and sets to ax2.
# these lines add the annotations for the plot.
ax1.set_xlabel('X data')
ax1.set_ylabel('Counts', color='g')
ax2.set_ylabel('Detection Rates', color='b')
plt.show(); # shows the plot.
Output:
Seaborn output example
You could try this code to obtain a very similar image to what you originally wanted.
import seaborn as sb
from matplotlib.lines import Line2D
from matplotlib.patches import Rectangle
x = ['1.1','1.2','1.2.1','2.0','2.1(beta)']
y = [1000,2000,500,8000,3000]
y1 = [3,4,1,8,5]
g = sb.barplot(x=x, y=y, color='blue')
g2 = sb.lineplot(x=range(len(x)), y=y1, color='orange', marker='o', ax=g.axes.twinx())
g.set_xticklabels(g.get_xticklabels(), rotation=-30)
g.set_xlabel('EngineVersion')
g.set_ylabel('Counts')
g2.set_ylabel('Detections rate')
g.legend(handles=[Rectangle((0,0), 0, 0, color='blue', label='Nontouch device counts'), Line2D([], [], marker='o', color='orange', label='Detections rate for nontouch devices')], loc=(1.1,0.8))

Only one dataname shows in the legend

I like to display a diagram of two data columns. The problem about it is that the legend shows only the last name l/s.
Here is my diagram:
import pandas as pd
import matplotlib.pyplot as plt
Tab = pd.read_csv('Mst01.csv', delimiter=';')
x = Tab['Nr. ']
y1 = Tab['cm']
y2 = Tab['l/s']
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(x, y1, 'g-', label='cm')
ax2.plot(x, y2, 'b-', label='l/s')
ax1.set_xlabel('Nr.')
ax1.set_ylabel('cm', color='g')
ax2.set_ylabel('l/s', color='b')
plt.title('Mst01')
plt.legend()
plt.show()
If I do
ax1.legend()
ax2.legend()
both legends will displayed but one above the other.
By the way, is there a easyier way the get the spaces for every line of code?
Good evening!
so you got two possibilities either you add the plots together or you use fig.legend()
here is some sample code which yields to the solution
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Create Example Dataframe
dummy_data = np.random.random_sample((100,2))
df = pd.DataFrame(dummy_data, columns=['Col_1', 'Col_2'])
df.Col_2 = df.Col_2*100
# Create Figure
fig, ax = plt.subplots()
col_1 = ax.plot(df.Col_1, label='Col_1', color='green')
ax_2 = ax.twinx()
col_2 = ax_2.plot(df.Col_2, label='Col_2', color='r')
# first solution
lns = col_1+col_2
labs = [l.get_label() for l in lns]
ax.legend(lns, labs, loc='upper right')
# secound solution
fig.legend()
fig
The solution can be derived from this question.
What do you mean by spaces? you mean the indention of e.g. a for loop?

Categories

Resources