2

I am trying to plot blood pressure readings, each of which has a datetime timestamp with the day and hour:minute:second of the reading.

As many Seaborn regression plots (lmplot, regplot etc) do not support datetime timestamps I resorted to creating a new data frame column with a numeric ordinal like below:

from datetime import date
df['date_ordinal'] = pd.to_datetime(df['date']).apply(lambda date: date.toordinal())

this works, but the problem is that multiple readings taken in the same day are all stacked on the same x-axis point.

Are there better functions than to ordinal to achieve separating readings taken on a same day with decimal values after the day ordinal?

Robert Alexander
  • 875
  • 9
  • 24
  • Is this what you are expecting ? https://stackoverflow.com/questions/48860428/passing-datetime-like-object-to-seaborn-lmplot – heretolearn Jul 22 '21 at 16:52
  • No. that posts tells you how to plot values on a x-axis with datetime values, which is not supported as per that post. I go around this problem converting a datetime timestamp to an integer (days from 01 Jan 1970) using the toordinal() function, but this gives an integer with the day and discards the h:mm:ss part – Robert Alexander Jul 22 '21 at 16:56

2 Answers2

2

You can calculate the timedeltas between every datetime in the date column and the oldest datetime, then use the timedelta's seconds. This means calculating the relative time (in seconds) since the oldest timestamp:

df['seconds_since_start'] = df['date'].apply(lambda date: (date - df['date'].min()).seconds)

From here, you can convert the seconds to days (with decimal values) using basic math:

df['days_since_start'] = df['seconds_since_start'] / (60 * 60 * 24)
jfaccioni
  • 7,099
  • 1
  • 9
  • 25
0

Thanks to @jfaccioni for hinting towards the right direction :) Here's what I did.

First of all to convert a datetime object to a float, so that it could be used by seaborn's scatterplot.

I used the timestamp function which converts a datetime to an epoch (seconds from 01-jan-1970):

df['date_ordinal'] = pd.to_datetime(df['Measurement Date']).apply(lambda date: date.timestamp())

with that I have solved my need. Just to help someone with similar requirements here's a second part.

How to transform back those large seconds numbers back to date strings so they can be used as labels for my seaborn x-axis plot:

# now convert the epoch values back to a YYYY-MM-DD string for the x labels
# localtime converts the epoch into a datetime object abd strftime converts it into a string
new_labels = [time.strftime('%Y-%m-%d',time.localtime(item)) for item in ax.get_xticks()]
ax.set_xticklabels(new_labels)
Robert Alexander
  • 875
  • 9
  • 24