matplotlib 散点图,不连续的 yaxis 刻度,数据类型为整数

matplotlib scatter plotting with noncontiguous yaxis ticks with datatype as integer

我的问题: 在绘制数据框中的 x 和 y 值时,如果我们将 y 值作为离散数字表示,id_number 或类别。如果我们使用散点图,它会给出线性间隔的 yaxis 刻度,根据我们的原始值的间距,绘制的值之间可能有很大的垂直间距。

我需要的是在散点图中根据时间事件 (xaxis) 绘制一些类别值(固定离散值),但 table 中的值只是整数而不是字符串。由于我对如何执行此操作没有任何深刻的想法,以下是我所取得的成就,但使用修改后的原始 table 和字符串值。这是我的测试数据(原始数据很大)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as mtic
import matplotlib.category as mcat

np.random.seed(432987435)

nofpoints = 160

xval = np.arange(nofpoints)
disc = [ 200, 240, 250, 290 ]

yval = np.random.choice( disc , nofpoints)
yval_str = yval.astype(str)
yval , yval_str

cval = np.random.random( nofpoints )
df = pd.DataFrame( { 'xval': xval , 'yval':yval , 'cval': cval })
df_str = pd.DataFrame( { 'xval': xval , 'yval':yval_str , 'cval': cval })

使用通常的绘图方法

fig = plt.figure(dpi=128 , figsize=(12,6))
ax1 = fig.add_subplot(111) 
# here we are using the original dataframe(df), without any string field inside.
#ax1.grid(True)
ax1.scatter( 'xval' , 'yval' , data=df , marker='o', facecolor='None' , edgecolor='g')
plt.show()

这就是我们得到的 看到值之间的大间距和每个绘图点不反对刻度值。 (我不想使用图例来显示使用颜色图的类别,因为它被保留用于其他目的) 修改后的数据框将字符串作为 yaxis 值

fig = plt.figure(dpi=128 , figsize=(12,6))
ax2 = fig.add_subplot(111) 
# dataframe used is modified one with a string field inside.
# as we can see the order is shuffled.
ax2.scatter( 'xval' , 'yval' , data=df_str , marker='o', facecolor='None' , edgecolor='k')
plt.show()

避免洗牌

fig = plt.figure(dpi=128 , figsize=(12,6))
ax3 = fig.add_subplot(111) 
# to maintain the same order and avoid shuffling we used matplotlib.category
#ax3.grid(True)
disc_str = [ str(x) for x in disc ]
units = mcat.UnitData(sorted(disc_str))
ax3.yaxis.set_units(units)
ax3.yaxis.set_major_locator( mcat.StrCategoryLocator(units._mapping))
ax3.yaxis.set_major_formatter( mcat.StrCategoryFormatter(units._mapping))
ax3.scatter( 'xval' , 'yval' , data=df_str , marker='o', facecolor='None' , edgecolor='y')
plt.show()

有什么方法可以实现这个,而不修改原来的 table,我的意思是将整数类别值绘制为 yaxis 值。

您可以将 ax1.scatter 替换为 seaborn.stripplot:

sns.stripplot(ax = ax1, data = df, x = 'xval', y = 'yval_str', marker = 'o', color = 'white', edgecolor = 'green', linewidth = 1)

在你这样做之前,如果你想要 y 轴的特定顺序,你应该对你的 df 进行排序:

df = pd.DataFrame({'xval': xval, 'yval': yval, 'yval_str': yval_str, 'cval': cval}).sort_values(by = 'yval', ascending = False)

完整代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

np.random.seed(432987435)

nofpoints = 160

xval = np.arange(nofpoints)
disc = [200, 240, 250, 290]

yval = np.random.choice(disc, nofpoints)
yval_str = yval.astype(str)

cval = np.random.random(nofpoints)
df = pd.DataFrame({'xval': xval, 'yval': yval, 'yval_str': yval_str, 'cval': cval}).sort_values(by = 'yval', ascending = False)

fig = plt.figure(dpi = 128, figsize = (12, 6))
ax1 = fig.add_subplot(111)
sns.stripplot(ax = ax1, data = df, x = 'xval', y = 'yval_str', marker = 'o', color = 'white', edgecolor = 'green', linewidth = 1)
plt.show()

如果你想要完全水平对齐的点,你必须将 jitter = False 传递给 sns.stripplot:

sns.stripplot(ax = ax1, data = df, x = 'xval', y = 'yval_str', marker = 'o', color = 'white', edgecolor = 'green', linewidth = 1, jitter = False)