0

My aim is to generate something like this aim, but my try looks like this my output

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.

2
  • I have had the same problem quite often. I find it easiest to us pd.merge or pd.concat so that they all share the same index (for merge you can use how="outer" so that all dates will be captured). This should solve the problem. For the vertical line across all, you can create a GridSpec for the figure, then plot a line across all at once, see the answer to this question. Hopefully this helps; let me know if you have any questions! Commented May 31, 2022 at 19:04
  • Thanks for your answer. Can you elaborate more like how can I implement pd.merge in this case? Commented May 31, 2022 at 19:06

1 Answer 1

1

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!

Sign up to request clarification or add additional context in comments.

2 Comments

When I use df3 = pd.merge(df, df1, left_index=True, right_index=True) the small interval data is guiding the x-axis, and when I use yours, the big data interval is guiding, but it gives me 'value' must be an instance of str or bytes, not a float error. I guess it is because epoch is following everything value. For example when I write df_merged['B'], it gives me B value along with epoch, not separately. How to solve this?
Well, I found a way, just use outer in this case. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.