My aim is to generate something like this , but my try looks like this
The problem is I am using two CSV data and even though their time range is the same, one of them has many time intervals like around 2399 and the other one is 73. I'm using sharex="All" command and whatever I can found from internet as well, but it gives runtime error "Locator attempting to generate 119857 ticks ([-113.5, ..., 2383.5]), which exceeds Locator.MAXTICKS (1000)"
My output generating code is following :
fig, (ax1, ax2,ax3,ax4) = plt.subplots(4, 1,figsize=(10,7), sharex="all")
fig.subplots_adjust(bottom=0.2)
ax1.plot( df.time, df['B'], color='k')
ax1.plot( df.time, df['Bx'], color='r')
ax1.plot( df.time, df['By'], color='b')
ax1.plot( df.time, df['Bz'], color='g')
ax1.xaxis.grid(True,alpha=0.3)
ax1.set_ylabel('Bx,By,Bz,B[nT]')
ax2.plot(df1.time, df1['v_total'],color='k')
ax2.plot(df1.time, df1['Vx'],color='r')
ax2.plot(df1.time, df1['Vy'],color='b')
ax2.plot(df1.time, df1['Vz'],color='g')
ax2.xaxis.grid(True,alpha=0.3)
ax2.set_ylabel('Vx,Vy,Vz,V[km/s]')
ax3.plot(df1.time, df1['n'],color='k')
ax3.xaxis.grid(True,alpha=0.3)
ax3.set_ylabel('Np[1/cm^3]')
ax4.plot(df1.time, df1['T'],color='k')
ax4.xaxis.grid(True,alpha=0.3)
ax4.set_ylabel('T[k]')
minutes = mdates.MinuteLocator(byminute=np.arange(0,60,15),interval=2)
minutes_fmt = mdates.DateFormatter('%H:%M')
ax4.xaxis.set_major_locator(minutes)
ax4.xaxis.set_major_formatter(minutes_fmt)
ax4.tick_params(axis='x', labelrotation=45)
fig.suptitle('FF shock May 07 2007')
plt.savefig('WindIP.png')
plt.savefig('WindIP.pdf')
plt.show()
My two data are: https://drive.google.com/file/d/1uqmynE78dMM_23ITVBsdu7-5tPbnQ9gC/view?usp=sharing https://drive.google.com/file/d/17kj8MM-agNkS22J5sRGGicdQHCK5EGYL/view?usp=sharing
I used following command to change from epoch to time
df['epoch'] = pd.to_datetime(df.epoch, format='%Y-%m-%dT%H:%M:%S.%f')
df['time'] = df['epoch'].dt.strftime('%H:%M:%S')
df1['epoch'] = pd.to_datetime(df1.epoch, format='%Y-%m-%dT%H:%M:%S.%f')
df1['time'] = df1['epoch'].dt.strftime('%H:%M:%S')
and for T value
m_p=1.6726219*10** -27
K_b=1.38064852*10** -23
df1['nVth']=1000*df1['V_th']
df1['T']=(df1['nVth']**2*m_p)/(2*K_b)
So, how to reduce ticks as well as align two time intervals and show one time interval as x-axis? And another minor problem is how put red vertical line like in the my aim figure? I tried axvline, but no success. Thanks for your consideration and help.
CodePudding user response:
Moving to an answer so I can write more clearly, you can merge the dataframes like this (taking from your question that epoch
is the same in both and pd.to_datetime()
has already been applied):
df_merged = df.set_index("epoch").merge(df1.set_index("epoch"),
left_index=True, right_index=True,
how="outer")
Then using df_merged.index
as the x-axis, and df_merged["B"]
etc. as the columns, everything should align. (EDIT: thinking this through, it might be easier to merge on the time
column, as this will not be so specific, so will not create duplicate rows for the two dataframes for the same day.)
Then again for the line across all charts, the answer from @bb1 here gives the answer, by using:
gs = fig.add_gridspec(3, 2)
# ...
# background axes object for plotting the vertical line
ax = fig.add_subplot(gs[:, :], sharex = ax1)
# set background color to transparent and turn off the frame
ax.patch.set_alpha(0)
ax.axis("off")
# plot the vertical line
ax.axvline(20, c='r')
You can play around with this to get it to suit your specific requirements. You can easily duplicate the last line and use ls="--"
to plot the dashed lines too!