I'm trying to left align the y ticks on a barh
plot following the ad hoc matplotlib documentaion. However, I get 2 sets of xticks labelling: a character type one (wanted) and a numerical one (unwanted). How can I remove the numerical ticks?
Here is the script:
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt#Read Data from schedule.csv
import pdb
import mpl_toolkits.axisartist as axisartist
plot_bool = "yes"
df = pd.read_csv("so.csv")
c_dict={
'invitro_exp2_exp1_exp': '#b9f1ac',
'invitro_exp2_exp1_writing': '#2faa12',
'invitro_exp2_exp3_exp': '#d0daff',
'invitro_exp2_exp3_writing': '#1030fa',
'clinical': '#ffa4a4',
'writing_clinical': '#ff0000',
'clinical_GPU': '#d0d0d0',
'writing_clinical_GPU': '#7a7a7a',
}
df.start=pd.to_datetime(df.start, format='%d-%m-%y')
df.end=pd.to_datetime(df.end, format='%d-%m-%y')#Add Duration
df['duration']=df.end-df.start
df.duration=df.duration.apply(lambda x: x.days+1)#sort in ascending order of start date
df=df.sort_values(by='start', ascending=True)#project level variables
p_start=df.start.min()
p_end=df.end.max()
p_duration=(p_end-p_start).days+1#Add relative date
df['rel_start']=df.start.apply(lambda x: (x-p_start).days)#Create custom x-ticks and x-tick labels
x_ticks=[i for i in range(p_duration+1)]
x_labels_full=[(p_start+dt.timedelta(days=i)).strftime('%d-%m-%Y')
for i in x_ticks]###### PLOTTING GANTT CHART ######
x_labels=[(p_start+dt.timedelta(days=i)).strftime('%b-%Y')
for i in x_ticks]###### PLOTTING GANTT CHART ######
idxlist = []
chosen_dates = [
"01-02-2023",
"01-05-2023",
"01-08-2023",
"01-11-2023",
"01-02-2024",
"01-05-2024",
"01-08-2024",
"01-11-2024",
"01-01-2025",
]
for count, date in enumerate(x_labels_full):
if date in chosen_dates:
idxlist.append(count)
x_ticks_display = list( x_ticks[i] for i in idxlist )
x_labels_display = list( x_labels[i] for i in idxlist )
fig = plt.figure(figsize=(8,4))
ax = fig.add_subplot(111, axes_class=axisartist.Axes)
for i in range(df.shape[0]):
color=c_dict[df.Department[i]]
#plt.barh(y=df.Task[i],
ax.barh(y=df.Task[i],
left=df.rel_start[i],
height=0.3,
width=df.duration[i],
alpha=1,
color=color,
)
ax.axis["left"].major_ticklabels.set_ha("left")
ax.tick_params(axis='y', labelsize=7)
plt.gca().invert_yaxis()
ax.set_xticklabels(x_labels_display, fontsize=7)
ax.set_xticks(idxlist, x_labels_display, fontsize=4)
ax.grid( alpha = 0.4)
plt.tight_layout()
plt.savefig("figures/milestones.png", dpi = 200)
if plot_bool == "yes":
plt.show()
if plot_bool == "no":
plt.show(block=False)
plt.close()
Here is the so.csv
,Task,start,end,Department
0,exp1 vs exp2: Adjusting setup,01-02-23,01-04-23,invitro_exp2_exp1_exp
1,exp1 vs exp2: Modify code for exp2,01-02-23,01-05-23,invitro_exp2_exp1_exp
1,exp1 vs exp2: Acquiring data,01-04-23,01-07-23,invitro_exp2_exp1_exp
1,exp1 vs exp2: Analyzing data,01-06-23,01-09-23,invitro_exp2_exp1_exp
4,exp1 vs exp2: Writing manuscript,01-08-23,01-11-23,invitro_exp2_exp1_writing
1,exp2 vs exp3: Modify code for exp3,01-05-23,01-08-23,invitro_exp2_exp3_exp
1,exp2 vs exp3: Acquiring data,01-08-23,01-11-23,invitro_exp2_exp3_exp
1,exp2 vs exp3: Analyzing data,01-10-23,01-01-24,invitro_exp2_exp3_exp
4,exp2 vs exp3: Writing manuscript,01-11-23,01-02-24,invitro_exp2_exp3_writing
2,Clinical exp4: Writing ethic protocol,28-07-23,01-11-23,clinical
3,Clinical exp4: Recruit 40 patients,01-11-23,01-04-24,clinical
4,Clinical exp4: Analyze clinical data,01-03-24,01-06-24,clinical
4,Clinical exp4: Writing manuscript,01-05-24,01-08-24,writing_clinical
2,Clinical exp4: Writing code,01-12-23,01-03-24,clinical_GPU
2,Clinical exp4: Writing ethic protocol 2,01-02-24,01-07-24,clinical_GPU
4,Clinical exp4: Recruit 20 patients,28-06-24,01-11-24,clinical_GPU
4,Clinical exp4: Analyze data,01-08-24,01-11-24,clinical_GPU
4,Clinical exp4: Writing manuscript 2,01-10-24,01-01-25,writing_clinical_GPU
Edit 2
I edited the code by adding for tick in ax.get_yticklabels(): tick.set_ha("left")
and removing the axisartist
dependencies. Much better: I could left align the yticks but now yticks are inside the plot
The code is as follows:
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt#Read Data from schedule.csv
import pdb
plot_bool = "yes"
df = pd.read_csv("so.csv")
c_dict={
'invitro_exp2_exp1_exp': '#b9f1ac',
'invitro_exp2_exp1_writing': '#2faa12',
'invitro_exp2_exp3_exp': '#d0daff',
'invitro_exp2_exp3_writing': '#1030fa',
'clinical': '#ffa4a4',
'writing_clinical': '#ff0000',
'clinical_GPU': '#d0d0d0',
'writing_clinical_GPU': '#7a7a7a',
}
df.start=pd.to_datetime(df.start, format='%d-%m-%y')
df.end=pd.to_datetime(df.end, format='%d-%m-%y')#Add Duration
df['duration']=df.end-df.start
df.duration=df.duration.apply(lambda x: x.days+1)#sort in ascending order of start date
df=df.sort_values(by='start', ascending=True)#project level variables
p_start=df.start.min()
p_end=df.end.max()
p_duration=(p_end-p_start).days+1#Add relative date
df['rel_start']=df.start.apply(lambda x: (x-p_start).days)#Create custom x-ticks and x-tick labels
x_ticks=[i for i in range(p_duration+1)]
x_labels_full=[(p_start+dt.timedelta(days=i)).strftime('%d-%m-%Y')
for i in x_ticks]###### PLOTTING GANTT CHART ######
x_labels=[(p_start+dt.timedelta(days=i)).strftime('%b-%Y')
for i in x_ticks]###### PLOTTING GANTT CHART ######
idxlist = []
chosen_dates = [
"01-02-2023",
"01-05-2023",
"01-08-2023",
"01-11-2023",
"01-02-2024",
"01-05-2024",
"01-08-2024",
"01-11-2024",
"01-01-2025",
]
for count, date in enumerate(x_labels_full):
if date in chosen_dates:
idxlist.append(count)
x_ticks_display = list( x_ticks[i] for i in idxlist )
x_labels_display = list( x_labels[i] for i in idxlist )
fig = plt.figure(figsize=(8,4))
ax = fig.add_subplot(111)
for i in range(df.shape[0]):
color=c_dict[df.Department[i]]
#plt.barh(y=df.Task[i],
ax.barh(y=df.Task[i],
left=df.rel_start[i],
height=0.3,
width=df.duration[i],
alpha=1,
color=color,
)
ax.tick_params(axis='y', labelsize=6, direction='out')
ax.invert_yaxis()
ax.set_xticks(idxlist, x_labels_display, fontsize = 6)
for tick in ax.get_yticklabels(): tick.set_ha("left")
ax.grid( alpha = 0.4)
plt.tight_layout()
plt.savefig("figures/milestones.png", dpi = 200)
if plot_bool == "yes":
plt.show()
if plot_bool == "no":
plt.show(block=False)
plt.close()