使用 matplotlib 绘制两个不同大小的列表的问题
Problem with plotting two lists with different sizes using matplotlib
我对 matplotlib 非常陌生,我正在尝试在 python 中创建一个 discord 机器人,它只记录服务器 activity 并将其显示为基于时间的折线图服务器最活跃(每 10 秒消息/一天中的时间)。问题是,一天中 99.99% 的时间消息数量与秒数不同,因此 2 个列表不匹配,我得到
ValueError: x and y must have same first dimension,
我的列表是这样的:
instances= [(6209, 10), (42906, 20), (70182, 23), (30422, 18), (70503, 21), (8426, 12), (78322, 22), (27038, 17), (1453, 2), (36138, 3)]
times= [0, 3600, 7200, 10800, 14400, 18000, 21600, 25200, 28800, 32400, 36000, 39600, 43200, 46800, 50400, 54000, 57600, 61200, 64800, 68400, 72000, 75600, 79200]
所以我有一个列表(什么时间,多少条消息)和一个以秒为单位的一天中每个小时的列表,所以我可以将它们绘制成 在这个时间发生了这么多条消息天。
我如何将它们绘制到单个图形上,因为 ax.plot (instances, times)
给我错误。我搜索了其他答案,但 none 对我有帮助。
- 在这种情况下,数据显示为条形图效果更好。
- 从
instances
中提取秒和值以分隔变量
- 将秒数转换为
H:M:S
的标准时间格式
- 似乎不需要
times
。
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import timedelta
instances= [(6209, 10), (42906, 20), (70182, 23), (30422, 18), (70503, 21), (8426, 12), (78322, 22), (27038, 17), (1453, 2), (36138, 3)]
# separate out x and convert from seconds to H:M:S
x = [timedelta(seconds=v[0]) for v in instances]
# separate out the y values
y = [v[1] for v in instances]
# sort x and y, based on time
x, y = zip(*sorted(zip(x, y)))
# convert from tuples to lists because barplot won't work with tuples
x, y = list(x), list(y)
# plot
fig = plt.figure(figsize=(10, 5))
p = sns.barplot(x=x, y=y)
p.set(xlabel='Observation Time', ylabel='Activity Count', title='Messages')
# annotate
p.bar_label(p.containers[0], label_type='edge', padding=1)
# pad the spacing between the number and the edge of the figure
p.margins(y=0.1)
- 绘制为线图
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from datetime import timedelta
instances= [(6209, 10), (42906, 20), (70182, 23), (30422, 18), (70503, 21), (8426, 12), (78322, 22), (27038, 17), (1453, 2), (36138, 3)]
# separate out the x values
x = [v[0] for v in instances]
# separate out the y values
y = [v[1] for v in instances]
# sort x and y, based on time
x, y = zip(*sorted(zip(x, y)))
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(x, y, marker='o')
# fixing xticks with matplotlib.ticker "FixedLocator"
xticks_loc = ax.get_xticks()
ax.xaxis.set_major_locator(mticker.FixedLocator(xticks_loc))
_ = ax.set_xticklabels([timedelta(seconds=tm) for tm in xticks_loc])
- 如果你想在 x 轴上有更多的时间,而不是使用
ax.get_xticks
,传递 list
个值,或使用 range
) xticks_loc = range(0, 86400, 3600)
并添加 ax.set_xlim(0, 86400)
- 大概增加图的宽度
fig, ax = plt.subplots(figsize=(15, 5))
- 旋转 x 轴标签
_ = ax.set_xticklabels([timedelta(seconds=tm) for tm in xticks_loc], rotation=45)
# fixing xticks with matplotlib.ticker "FixedLocator"
ax.set_xlim(0, 86400)
xticks_loc = range(0, 86400, 3600)
ax.xaxis.set_major_locator(mticker.FixedLocator(xticks_loc))
_ = ax.set_xticklabels([timedelta(seconds=tm) for tm in xticks_loc], rotation=45)
我对 matplotlib 非常陌生,我正在尝试在 python 中创建一个 discord 机器人,它只记录服务器 activity 并将其显示为基于时间的折线图服务器最活跃(每 10 秒消息/一天中的时间)。问题是,一天中 99.99% 的时间消息数量与秒数不同,因此 2 个列表不匹配,我得到
ValueError: x and y must have same first dimension,
我的列表是这样的:
instances= [(6209, 10), (42906, 20), (70182, 23), (30422, 18), (70503, 21), (8426, 12), (78322, 22), (27038, 17), (1453, 2), (36138, 3)]
times= [0, 3600, 7200, 10800, 14400, 18000, 21600, 25200, 28800, 32400, 36000, 39600, 43200, 46800, 50400, 54000, 57600, 61200, 64800, 68400, 72000, 75600, 79200]
所以我有一个列表(什么时间,多少条消息)和一个以秒为单位的一天中每个小时的列表,所以我可以将它们绘制成 在这个时间发生了这么多条消息天。
我如何将它们绘制到单个图形上,因为 ax.plot (instances, times)
给我错误。我搜索了其他答案,但 none 对我有帮助。
- 在这种情况下,数据显示为条形图效果更好。
- 从
instances
中提取秒和值以分隔变量 - 将秒数转换为
H:M:S
的标准时间格式
- 似乎不需要
times
。
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import timedelta
instances= [(6209, 10), (42906, 20), (70182, 23), (30422, 18), (70503, 21), (8426, 12), (78322, 22), (27038, 17), (1453, 2), (36138, 3)]
# separate out x and convert from seconds to H:M:S
x = [timedelta(seconds=v[0]) for v in instances]
# separate out the y values
y = [v[1] for v in instances]
# sort x and y, based on time
x, y = zip(*sorted(zip(x, y)))
# convert from tuples to lists because barplot won't work with tuples
x, y = list(x), list(y)
# plot
fig = plt.figure(figsize=(10, 5))
p = sns.barplot(x=x, y=y)
p.set(xlabel='Observation Time', ylabel='Activity Count', title='Messages')
# annotate
p.bar_label(p.containers[0], label_type='edge', padding=1)
# pad the spacing between the number and the edge of the figure
p.margins(y=0.1)
- 绘制为线图
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from datetime import timedelta
instances= [(6209, 10), (42906, 20), (70182, 23), (30422, 18), (70503, 21), (8426, 12), (78322, 22), (27038, 17), (1453, 2), (36138, 3)]
# separate out the x values
x = [v[0] for v in instances]
# separate out the y values
y = [v[1] for v in instances]
# sort x and y, based on time
x, y = zip(*sorted(zip(x, y)))
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(x, y, marker='o')
# fixing xticks with matplotlib.ticker "FixedLocator"
xticks_loc = ax.get_xticks()
ax.xaxis.set_major_locator(mticker.FixedLocator(xticks_loc))
_ = ax.set_xticklabels([timedelta(seconds=tm) for tm in xticks_loc])
- 如果你想在 x 轴上有更多的时间,而不是使用
ax.get_xticks
,传递list
个值,或使用range
)xticks_loc = range(0, 86400, 3600)
并添加ax.set_xlim(0, 86400)
- 大概增加图的宽度
fig, ax = plt.subplots(figsize=(15, 5))
- 旋转 x 轴标签
_ = ax.set_xticklabels([timedelta(seconds=tm) for tm in xticks_loc], rotation=45)
# fixing xticks with matplotlib.ticker "FixedLocator"
ax.set_xlim(0, 86400)
xticks_loc = range(0, 86400, 3600)
ax.xaxis.set_major_locator(mticker.FixedLocator(xticks_loc))
_ = ax.set_xticklabels([timedelta(seconds=tm) for tm in xticks_loc], rotation=45)