Hello, I need to build a graphic with axis y in minutes:seconds:fractions of a seconds but I can't

Viewed 31

I have 7 storms with a time difference between IC (intracloud lightning) GC(lightning cloud ground) and I need to plot this time in a bar graph but I can't plot the minutes (y axis). Can someone help me? Some storms the difference is given by millisecond and I need to plot on x axis (storms) and y axis (time (minutes)).I'm trying to plot but the minutes are all zero

These are my data:

Storms (1 2 3 4 5 6 7)
time (00:00:00:131.73, 00:00:00:87.57, 00:03:23, 00:00:00:17.13, 00:08:23, 00:07:51, 00:40:41)

My code is like this:

import matplotlib.pyplot as plt
import matplotlib.dates as dates
from datetime import datetime, timedelta

x = ['1','2','3','4','5','6','7']
y = [00131.73, 087.57, 323, 1713, 823, 751, 4041]

fig, ax = plt.subplots(figsize=(8, 5))
plt.gca().yaxis.set_major_formatter(dates.DateFormatter('%M:%S.%f'))
plt.bar(x, y)
ax.set_title('a) Diferença de tempo entre o primeiro relâmpago IN e NS', fontsize=18)
ax.set_ylabel('Tempo (minutos)', fontsize=14)
ax.set_xlabel('Tempestades', fontsize=14)
plt.gcf().autofmt_xdate()
plt.show()

Current result:

enter image description here

1 Answers

There are two problems in your code

  • 3:23 is NOT 323 but 3*60 + 23 because minute has 60 seconds

  • you have to convert seconds to datetime - i.e using datetime.fromtimestamp(seconds) (but here I found small problem - it automatically sets 1970.01.01 01:00 and you have to remove hour 01 to get correct result - .replace(hour=0))

BTW: you have values much bigger than few seconds so for your data it always display .0000 for millisecond - and I skip .%f in code to make plot more readable.

from datetime import datetime, time
import matplotlib.pyplot as plt
import matplotlib.dates as dates

x = ['1','2','3','4','5','6','7']
y = [131.73, 87.57, 3*60+23, 17*60+13, 8*60+23, 7*60+51, 40*60+41]

y = [datetime.fromtimestamp(s).replace(hour=0) for s in y]

fig, ax = plt.subplots(figsize=(8, 5))
ax.yaxis.set_major_formatter(dates.DateFormatter('%M:%S'))
plt.bar(x, y)
plt.show()

enter image description here


If you would have all times as string with the same data - always hours, minutes, seconds, milliseconds - then you could use strptime() (string parse time) to convert string to datetime)

Eventually you could try to use modules like dateutil to parse strings


EDIT:

OR you could use split() to convert it to total seconds.

And later you can convert it to datetime using the same

datetime.fromtimestap(total_seconds).replace(hour=0)
import datetime

y = ['00:00:00:131.73', '00:00:00:87.57', '00:03:23', '00:00:00:17.13', '00:08:23', '00:07:51', '00:40:41']

for s in y:
    parts = s.split('.')
    
    if len(parts) > 1:
        millisecond = float('.' + parts[-1])
    else:
        millisecond = 0.0
        
    other = parts[0].split(':')
    
    if len(other) > 0:
        seconds = int(other[-1])
    else:
        seconds = 0

    if len(other) > 1:
        minutes = int(other[-2])
    else:
        minutes = 0

    if len(other) > 2:
        hours = int(other[-3])
    else:
        hours = 0

    total_seconds = hours*3600 + minutes*60 + seconds + millisecond

    dt = datetime.datetime.fromtimestamp(total_seconds).replace(hour=0)

    print(f'hours: {hours:3} | minutes: {minutes:3} | seconds: {seconds:3} | millisecond: {millisecond: .02f} | total: {total_seconds: 10.2f} | dt: {dt.strftime("%M:%S.%f")}')

Result:

hours:   0 | minutes:   0 | seconds: 131 | millisecond:  0.73 | total:     131.73 | dt: 02:11.730000
hours:   0 | minutes:   0 | seconds:  87 | millisecond:  0.57 | total:      87.57 | dt: 01:27.570000
hours:   0 | minutes:   3 | seconds:  23 | millisecond:  0.00 | total:     203.00 | dt: 03:23.000000
hours:   0 | minutes:   0 | seconds:  17 | millisecond:  0.13 | total:      17.13 | dt: 00:17.130000
hours:   0 | minutes:   8 | seconds:  23 | millisecond:  0.00 | total:     503.00 | dt: 08:23.000000
hours:   0 | minutes:   7 | seconds:  51 | millisecond:  0.00 | total:     471.00 | dt: 07:51.000000
hours:   0 | minutes:  40 | seconds:  41 | millisecond:  0.00 | total:    2441.00 | dt: 40:41.000000
Related