I’ve got a sort of timeline plot. I’m drawing rectangles all over it, which is easy to do when time is in milliseconds. But then the x axis labels come out numerical, and I’d rather they be dates. I can convert my timestamps with df['timestamp'] = pandas.to_datetime(df['timestamp'])
to fix the x axis labels, but then my rectangle drawing math breaks, because I can’t subtract milliseconds from a datetime like rect = [(t - 59000, h - 0.4), (t - 59000, h + 0.4), (t, h + 0.4), (t, h - 0.4), (t - 59000, h - 0.4)]; bars.append(rect); bars = PolyCollection(bars)
I think it would be easiest to just change the way my axis is labeled. How can I make it quit trying to plot massively long numbers and instead plot pretty date strings?
I just want to show the x axis labels as datetimes instead of these horribly unreadable numbers.
import pandas from matplotlib import pyplot from matplotlib.collections import PolyCollection from matplotlib.ticker import MultipleLocator df = pandas.read_csv('thing.csv') vert = {"upright":1, "supine":2, "lying_left":3, "prone":4, "lying_right":5, "unknown":6} fig, (ax1) = pyplot.subplots(1, 1, figsize=(15,5)) # first plot of positions over time # get the computed body positions as bars bars = [] colors = [] for i,row in df.iterrows(): h = vert[row['body_position']] t = row['timestamp'] rect = [(t - 59000, h - 0.4), (t - 59000, h + 0.4), (t, h + 0.4), (t, h - 0.4), (t - 59000, h - 0.4)] bars.append(rect) colors.append("C" + str(h-1)) bars = PolyCollection(bars, facecolors=colors) ax1.add_collection(bars) ax1.autoscale() ax1.xaxis.set_major_locator(MultipleLocator(60000)) #ax1.set_xticklabels([''], rotation=90) #ax1.xaxis.set_major_formatter(dates.DateFormatter("%B-%dn%H:%M")) ax1.set_yticks(sorted(vert.values())) ax1.set_yticklabels(sorted(vert, key=vert.get)) pyplot.tight_layout() pyplot.show()
Here is some example data used to generate the plot:
timestamp,incline_angle,rotation_angle,body_position 1631311140000,,,unknown 1631311200000,,,unknown 1631311260000,2.698802523069221,175.23174346257375,upright 1631311320000,3.79042308483573,167.83999245871857,upright 1631311380000,1.5175027051794074,179.61841112309935,upright 1631311440000,3.975208379737314,171.42631984353366,upright 1631311500000,1.1885374082444298,86.49027321064233,upright 1631311560000,4.810193480680129,21.462454182905063,upright 1631311620000,,,unknown 1631311680000,88.69449620162857,-178.52467261213772,supine 1631311740000,76.13842375737948,-176.28409623055694,supine 1631311800000,56.72313055674839,-171.72681198213715,supine 1631311860000,,,unknown 1631311920000,77.82676616765237,-72.18362857622509,lying_right 1631311980000,81.8046648695628,-46.69883607858903,lying_right 1631312040000,90.30495291582416,-11.324002429040227,prone 1631312100000,,,unknown 1631312160000,108.06979339334902,108.76621826399024,lying_left 1631312220000,,,unknown 1631312280000,,,unknown 1631312340000,,,unknown 1631312400000,117.55244721818904,165.87088640221413,unknown 1631312460000,0.5689364636363466,171.6313935247612,upright 1631312520000,10.566662943419471,-10.860907998962931,upright 1631312580000,24.244743971818696,-3.2077664692605854,upright 1631312640000,24.790924330066783,-5.473576795955548,upright 1631312700000,27.581635762266146,-6.965410020736653,upright
Advertisement
Answer
Alright, great! I was able to reproduce your code and I added a couple of lines to get the outcome you are looking for @PavelKomarov
import pandas from matplotlib import pyplot from matplotlib.collections import PolyCollection from matplotlib.ticker import MultipleLocator import matplotlib.pyplot as plt df = pandas.read_csv('thing.csv') vert = {"upright":1, "supine":2, "lying_left":3, "prone":4, "lying_right":5, "unknown":6} fig, (ax1) = pyplot.subplots(1, 1, figsize=(15,5)) # first plot of positions over time # get the computed body positions as bars bars = [] colors = [] for i,row in df.iterrows(): h = vert[row['body_position']] t = row['timestamp'] rect = [(t - 59000, h - 0.4), (t - 59000, h + 0.4), (t, h + 0.4), (t, h - 0.4), (t - 59000, h - 0.4)] bars.append(rect) colors.append("C" + str(h-1)) bars = PolyCollection(bars, facecolors=colors) ax1.add_collection(bars) ax1.autoscale() ax1.xaxis.set_major_locator(MultipleLocator(60000)) ax1.set_yticks(sorted(vert.values())) ax1.set_yticklabels(sorted(vert, key=vert.get)) ax1.set_xticklabels([pd.to_datetime(x).strftime("%Y/%m/%d") for x in ax1.get_xticks()]) plt.xticks(rotation=90) pyplot.tight_layout() pyplot.show()
The 2 extra lines I added were:
ax1.set_xticklabels([pd.to_datetime(x).strftime("%Y/%m/%d") for x in ax1.get_xticks()]) plt.xticks(rotation=90)
The timestamps on the xaxis were down to the milliseconds so I formatted them to be in YYYY/MM/DD you can change the format using this.
Let me know if this is what you were looking for.