如何在Python Matplotlib“ Clock” Polar Plot上绘制时间戳HH:MM

时间:2019-06-02 19:06:21

标签: python matplotlib

我正在尝试在极坐标图上按时间点绘制哺乳动物的喂养数据。在下面的示例中,只有一天,但是最终每天都会在同一张图表上(通过不同的坐标轴)进行绘制。目前,我已经解决了所有美学问题,但是我的数据无法正确绘制图形。如何获得可以正确绘图的时间?

我认为解决方案可能与pd.datetime和np.deg2rad有关,但是我没有找到正确的组合。

我正在从csv导入数据,并根据以下日期每天进行过滤:

#Filtered portion:
Day1 = df[df.Day == '5/22']

这给了我以下数据:

    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

代码如下:

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()

您可以从数据中假设,绘制的所有条形图都是在下午,但是从图形输出中可以看到,数据遍布整个地方。

polar clock plot

1 个答案:

答案 0 :(得分:1)

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}})

'Time'列中创建一系列datetime.datetime对象;将其转换为24小时的百分比;将其转换为弧度。

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

将其用作绘图的 x

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()

'Time'列也可以通过以下方式转换为弧度

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)

这可能比使用timedelta的方法好一点-似乎有点令人费解。