I am trying to plot mammalian feeding data on time points on a polar plot. In the example below, there is only one day, but each day will eventually be plotted on the same graph (via different axes). I currently have all of the aesthetics worked out, but my data is not graphing correctly. How do I get the hours to plot correctly?
I assume that the solution will likely have to do with pd.datetime and np.deg2rad, but I have not found the correct combo.
I am importing my data from csv, and filtering each day based on the date as follows:
#Filtered portion:
Day1 = df[df.Day == '5/22']
This gives me the following data:
Day Time Feeding_Quality Feed_Num
0 5/22 16:15 G 2
1 5/22 19:50 G 2
2 5/22 20:15 G 2
3 5/22 21:00 F 1
4 5/22 23:30 G 2
Here is the code:
fig = plt.figure(figsize=(7,7))
ax = plt.subplot(111, projection = 'polar')
ax.bar(Day1['Time'], Day1['Feed_Num'], width = 0.1, alpha=0.3, color='red', label='Day 1')
# Make the labels go clockwise
ax.set_theta_direction(-1)
#Place Zero at Top
ax.set_theta_offset(np.pi/2)
#Set the circumference ticks
ax.set_xticks(np.linspace(0, 2*np.pi, 24, endpoint=False))
# set the label names
ticks = ['12 AM', '1 AM', '2 AM', '3 AM', '4 AM', '5 AM', '6 AM', '7 AM','8 AM','9 AM','10 AM','11 AM','12 PM', '1 PM', '2 PM', '3 PM', '4 PM', '5 PM', '6 PM', '7 PM', '8 PM', '9 PM', '10 PM', '11 PM' ]
ax.set_xticklabels(ticks)
# suppress the radial labels
plt.setp(ax.get_yticklabels(), visible=False)
#Bars to the wall
plt.ylim(0,2)
plt.legend(bbox_to_anchor=(1,0), fancybox=True, shadow=True)
plt.show()
As you can assume from the data, all bars plotted would be in the afternoon, but as you can see from the graph output, the data is all over the place.

import numpy as np
from matplotlib import pyplot as plt
import datetime
df = pd.DataFrame({'Day': {0: '5/22', 1: '5/22', 2: '5/22', 3: '5/22', 4: '5/22'},
'Time': {0: '16:15', 1: '19:50', 2: '20:15', 3: '21:00', 4: '23:30'},
'Feeding_Quality': {0: 'G', 1: 'G', 2: 'G', 3: 'F', 4: 'G'},
'Feed_Num': {0: 2, 1: 2, 2: 2, 3: 1, 4: 2}})
Create a series of datetime.datetime objects from the 'Time' column; transform that into percentages of 24 hours; transform that into radians.
xs = pd.to_datetime(df['Time'],format= '%H:%M' )
xs = xs - datetime.datetime.strptime('00:00:00', '%H:%M:%S')
xs = xs.dt.seconds / (24 * 3600)
xs = xs * 2 * np.pi
Use that as the x values for the plot
fig = plt.figure(figsize=(7,7))
ax = plt.subplot(111, projection = 'polar')
ax.bar(xs, df['Feed_Num'], width = 0.1, alpha=0.3, color='red', label='Day 1')
# Make the labels go clockwise
ax.set_theta_direction(-1)
#Place Zero at Top
ax.set_theta_offset(np.pi/2)
#Set the circumference ticks
ax.set_xticks(np.linspace(0, 2*np.pi, 24, endpoint=False))
# set the label names
ticks = ['12 AM', '1 AM', '2 AM', '3 AM', '4 AM', '5 AM', '6 AM', '7 AM','8 AM','9 AM','10 AM','11 AM','12 PM', '1 PM', '2 PM', '3 PM', '4 PM', '5 PM', '6 PM', '7 PM', '8 PM', '9 PM', '10 PM', '11 PM' ]
ax.set_xticklabels(ticks)
# suppress the radial labels
plt.setp(ax.get_yticklabels(), visible=False)
#Bars to the wall
plt.ylim(0,2)
plt.legend(bbox_to_anchor=(1,0), fancybox=True, shadow=True)
plt.show()
The 'Time' column could also be transformed to radians with
def trans(x):
h,m = map(int,x)
return 2 * np.pi * (h + m/60)/24
xs = df['Time'].str.split(':')
xs = xs.apply(trans)
Which is probably a little better than using timedelta's - that seemed a little convoluted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With