Matplotlib:space 分类 x 轴按数值刻度

Matplotlib: space categorical x axis ticks by numerical value

我有数据要绘制成这样的垂直分组散点图:

q = pd.DataFrame({'time': ['1', '1', '1'], 'velocity': [2, 3, 4]})
q2 = pd.DataFrame({'time': ['3', '3', '3'], 'velocity': [1, 2, 3]})
q3 = pd.DataFrame({'time': ['10', '10', '10'], 'velocity': [2, 1, 4]})

fig, ax = plt.subplots()
ax.scatter(q['time'], q['velocity'], c='green')
ax.scatter(q2['time'], q2['velocity'], c='blue')
ax.scatter(q3['time'], q3['velocity'], c='red')
ax.set_xticks([1, 3, 10])
ax.legend()

但是,我希望 x 轴上的类别根据类别名称间隔开。在这种情况下,'time' 来自数据,data_2 和 data_3 是,比方说,填充了重复“1”、“3”、“10”的向量。

我希望类别“1”和“3”之间的距离为 2 个刻度,“3”到“10”的距离为 7 个刻度。

尝试过:

ax.set_xticks(np.arange(0, 11, 1))
ax.set_xticklabels( [i if str(i) in ['1', '3', '10'] else 0 for i in range(11) ] )

但这只会创建空值,并且仍将类别位置设置为 0、1、2。

我是否需要重新构造我的数据以将空值合并到间隙类别中,还是有其他方法?

我想这就是你想要做的:

在这种情况下,您真正​​需要做的唯一一件事就是将 time 值从字符串更改为数字。

q = pd.DataFrame({'time': [1, 1, 1], 'velocity': [2, 3, 4]})
q2 = pd.DataFrame({'time': [3, 3, 3], 'velocity': [1, 2, 3]})
q3 = pd.DataFrame({'time': [10, 10, 10], 'velocity': [2, 1, 4]})

如果你这样做,并将你的 xticklabels 命令更改为

ax.set_xticklabels( [i if i in [1, 3, 10] else 0 for i in range(11) ] )

那我想你的形象会如你所愿。

或者,如果您希望 dataframe 保留字符串值,您可以编写一个函数,将 returns 值作为绘图的数字:

import pandas as pd
import matplotlib.pyplot as plt

def str2num(mylist):
    return([float(i) for i in mylist])

q = pd.DataFrame({'time': ['1', '1', '1'], 'velocity': [2, 3, 4]})
q2 = pd.DataFrame({'time': ['3', '3', '3'], 'velocity': [1, 2, 3]})
q3 = pd.DataFrame({'time': ['10', '10', '10'], 'velocity': [2, 1, 4]})

fig, ax = plt.subplots()

ax.scatter(str2num(q['time']), q['velocity'], c='green')
ax.scatter(str2num(q2['time']), q2['velocity'], c='blue')
ax.scatter(str2num(q3['time']), q3['velocity'], c='red')
ax.set_xticks(range(11))
ax.set_xticklabels( [i if i in [1, 3, 10] else 0 for i in range(11) ] )