Related
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()
I am trying to create an axis plot. I was trying to loop over it as I am plotting the same variable for two different categories. Currently, I have written code two times but I am looking for a smarter way with looping, if possible. Any other suggestion will also be helpful.
zone = ['AB','CD']
plt.style.use('default')
fig,(ax0,ax1) = plt.subplots(2,1, figsize = (18,18), sharex = False)
i = 0
while i < len(zone):
if zone[i] == zone[0]:
ax0.plot(df0['datetime'], df0['pnl1'], color='k', linewidth=1, label ='PnL1')
ax0.plot(df0['datetime'], df0['pnl2'], color='m', linewidth=1, label ='PnL2')
ax00 = ax0.twinx()
ax00.bar(df0['datetime'], df0['qty'], width = 1/96, color='g', align = 'edge', alpha = 0.5, label ='Qty')
elif zone[i] == zone[1]:
ax1.plot(df0['datetime'], df0['pnl1'], color='k', linewidth=1, label ='PnL1')
ax1.plot(df0['datetime'], df0['pnl2'], color='m', linewidth=1, label ='PnL2')
ax01 = ax1.twinx()
ax01.bar(df0['datetime'], df0['hedge'], width = 1/96, color='g', align = 'edge', alpha = 0.5, label ='Qty')
i = i + 1
I want to check if something like below can be done with axis plots or not.
zone = ['AB','CD']
plt.style.use('default')
fig,(ax0,ax1) = plt.subplots(2,1, figsize = (18,18), sharex = False)
i = 0
while i < len(zone):
ax{''}.format(i).plot(df0['datetime'], df0['pnl1'], color='k', linewidth=1, label ='PnL1')
ax{''}.format(i).plot(df0['datetime'], df0['pnl2'], color='m', linewidth=1, label ='PnL2')
ax0{''}.format(i) = ax{''}.format(i).twinx()
ax0{''}.format(i).bar(df0['datetime'], df0['qty'], width = 1/96, color='g', align = 'edge', alpha = 0.5, label ='Qty')
It did not work for me. Any leads to execute axis plot with loop will be helpful.
Here are some ways:
Simply loop over the list of axes
import matplotlib.pyplot as plt
import numpy as np
fig,axes = plt.subplots(2,1)
x = np.linspace(0,5,21)
for ax in axes:
ax.plot(x,np.sin(x))
plt.show()
Works also with index:
for i in range(len(axes)):
axes[i].plot(x,np.sin(x))
For a grid of plot you can use a similar approach:
import matplotlib.pyplot as plt
import numpy as np
fig,axes = plt.subplots(2,2)
x = np.linspace(0,5,21)
for i in range(len(axes)):
for j in range(len(axes[0])):
axes[i][j].plot(x,np.sin(x))
plt.show()
If you don't like double-loops, you can flatten the array with np.ravel()
fig,axes = plt.subplots(2,2)
x = np.linspace(0,5,21)
for ax in np.ravel(axes):
ax.plot(x,np.sin(x))
plt.show()
I have a problem about putting a radar chart and bar graph in the subplot in Python.
I defined 1 row and 2 columns to put each one into each slot.
I tried to handle with this process but I couldn't.
How can I do that?
Here is my radar function shown below.
def radar_chart(values=[]):
labels=np.array(['Crew',
'Length',
'Wingspan',
'Height',
'WingArea'
]
)
angles=np.linspace(0, 2*np.pi, len(labels), endpoint=False)
#print(angles)
fig=plt.figure(figsize=(6,6))
#plt.suptitle(title, y=1.04)
for v in values:
stats=np.array(ww2aircraft_df[ww2aircraft_df["Name"]==v][labels])[0]
#print(stats)
ax = fig.add_subplot(111, polar=True)
ax.plot(angles, stats, 'o-', linewidth=2, label = v)
ax.fill(angles, stats, alpha=0.25)
ax.set_thetagrids(angles * 180/np.pi, labels)
ax.grid(True)
#plt.legend(loc="upper right",bbox_to_anchor=(1.2,1.0))
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.10),
fancybox=True, shadow=True, ncol=1, fontsize=13)
Here is my code snippets shown below.
f,a = plt.subplots(1,2,figsize=(24,10))
radar_chart(values=ww2aircraft_df_top_5["Name"])
graph_1 = sns.barplot(data = ww2aircraft_df_top_5,
x = "MaxSpeed",
y = "Name" , ax = a[1])
show_values_on_bars(graph_1, "h", 0.3)
plt.suptitle('Top 5 fastest of WW2 warplane by their features',
fontsize=20,
fontweight="semibold",
)
plt.tight_layout()
plt.savefig('images/image10.png', bbox_inches = "tight")
plt.show()
Possible solution is the following:
The dataset can be found HERE
# pip install matplotlib
# pip install pandas
# pip install seaborn
import csv
import pandas as pd
import numpy as np
from math import pi
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import seaborn as sns
# read csv to dataframe
df = pd.read_csv('ww2aircraft.csv', sep=';')
# select top-5 rows by 'MaxSpeed' column
df_top5_maxspeed = df.nlargest(5, 'MaxSpeed').reset_index(drop=True)
# convert column values to float type
df_top5_maxspeed['Length'] = df_top5_maxspeed['Length'].astype('float64')
df_top5_maxspeed['Wingspan'] = df_top5_maxspeed['Wingspan'].astype('float64')
# limit dataframe to required columns
df_top5_maxspeed_data = df_top5_maxspeed[["Name","Crew","Length","Wingspan","Height","WingArea","MaxSpeed"]]
df_top5_maxspeed_data
def create_radar_chart(df):
# limit data drame
df = df.iloc[:, :-1]
categories=list(df_top5_maxspeed_data)[1:-1]
N = len(categories)
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]
ax = fig.add_subplot(gs[0, 0], polar=True)
ax.set_theta_offset(pi / 2)
ax.set_theta_direction(-1)
plt.xticks(angles[:-1], categories, size=10)
ax.set_rlabel_position(0)
plt.yticks([10,20,30,40], ["10","20","30","40"], color="grey", size=10)
plt.ylim(0,40)
for row in range(0, len(df.index)):
values=df.loc[row].drop(['Name']).values.flatten().tolist()
values+= values[:1]
ax.plot(angles, values, 'o-', linewidth=2, label = df.loc[row]["Name"])
ax.fill(angles, values, alpha=0.2)
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.10),
fancybox=False, shadow=False, ncol=1, fontsize=10, frameon=False)
def create_bar_chart(df):
ax = fig.add_subplot(gs[0, 1])
df = df[['Name','MaxSpeed']]
df.plot.bar(x='Name', y='MaxSpeed', ax = ax, legend=False)
plt.xlabel("")
# create plots area
fig = plt.figure(figsize=(15, 5))
gs = GridSpec(nrows=1, ncols=2, width_ratios=[1, 1], wspace=0.1)
fig.suptitle('Top 5 fastest of WW2 warplane by their features', fontsize=16)
# add charts
create_radar_chart(df_top5_maxspeed_data)
create_bar_chart(df_top5_maxspeed_data)
# adjust space between title and charts
plt.subplots_adjust(top=0.85)
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))
I want to know if it is possible to synchronize xticks with xticklabels, in this way:
x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
XLabels = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U']
Now on screen 0 5 10 15 20, but on second subplot, there is A B C D E.
I want to see: A F K P U.
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter, FormatStrFormatter, MultipleLocator # format X scale
import numpy as np
x=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)
ax1.plot((np.arange(min(x), max(x)+1, 1.0)), 'b-')
ax2 = fig.add_subplot(2,1,2) # , sharex=ax1)
ax2.plot((np.arange(min(x), max(x)+1, 1.0)), 'r-')
#plt.setp(ax1.get_xticklabels(), visible=False)
ax2.xaxis.set_major_formatter(FormatStrFormatter('%0d'))
ax2.set_xticklabels(['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'], fontsize=12)
plt.show()
How can synchronize, so that I have A F K P U corresponding with 0 5 10 15 20 ?
The easiest option is to set the ticks and ticklabels manually. E.g. if you want to tick every Nth integer, you can choose a subset of the lists ([::N]) to set the ticks and labels to.
import matplotlib.pyplot as plt
import numpy as np
x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
XLabels = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q',
'R','S','T','U']
N = 5
fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)
ax1.plot((np.arange(min(x), max(x)+1, 1.0)), 'b-')
ax1.set_xticks(x[::N])
ax2 = fig.add_subplot(2,1,2) # , sharex=ax1)
ax2.plot((np.arange(min(x), max(x)+1, 1.0)), 'r-')
ax2.set_xticks(x[::N])
ax2.set_xticklabels(XLabels[::N], fontsize=12)
plt.show()
In order to kind of automate this, you can use a FuncFormatter, which selects the correct letter from the XLabels list according to the tick's location.
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter, FuncFormatter, MultipleLocator
import numpy as np
x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
XLabels = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q',
'R','S','T','U']
N = 5
fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)
ax1.plot((np.arange(min(x), max(x)+1, 1.0)), 'b-')
ax1.xaxis.set_major_locator(MultipleLocator(N))
ax2 = fig.add_subplot(2,1,2) # , sharex=ax1)
ax2.plot((np.arange(min(x), max(x)+1, 1.0)), 'r-')
def f(c,pos):
if int(c) in x:
d = dict(zip(x,XLabels))
return d[int(c)]
else:
return ""
ax2.xaxis.set_major_locator(MultipleLocator(N))
ax2.xaxis.set_major_formatter(FuncFormatter(f))
plt.show()
You can filter the list of labels to get the ones matching the x axis, and use set_xticks and set_xticklabels
A simplified example:
import matplotlib.pyplot as plt
x = [0, 5, 10, 15, 20]
labels = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U']
fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)
ax1.plot(x, x, 'b-')
ax2 = fig.add_subplot(2,1,2)
ax2.plot(x, x, 'r-')
ax2.set_xticks(x)
ax2.set_xticklabels([label for index, label in enumerate(labels) if index in x])
plt.show()