当使用分类值时,如何保留散点图轴的顺序?

4

我希望创建一个散点图,将我的数据总结到ntiles中。由于散点图无法将区间类型作为坐标轴参数进行处理,因此我将值转换为字符串,但这样会导致区间的顺序丢失。请注意,下面的x轴未按从低到高排序。如何保留顺序?

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np


n_tile = 5
np.random.seed(0)
x = np.random.normal(150, 70, 3000,)
y = np.random.normal(1, 0.3, 3000)
r = np.random.normal(0.4, 0.1, 3000)

plot_data = pd.DataFrame({
            'x': x,
            'y': y,
            'r': r
                })
plot_data['x_group'] = pd.qcut(plot_data['x'], n_tile, duplicates='drop')
plot_data['y_group'] = pd.qcut(plot_data['y'], n_tile, duplicates='drop')
plot_data_grouped = plot_data.groupby(['x_group','y_group'], as_index=False).agg({'r':['mean','count']})
plot_data_grouped.columns = ['x','y','mean','count']

cmap = plt.cm.rainbow
norm = matplotlib.colors.Normalize(vmin=0, vmax=1)

plt.figure(figsize=(10,10))
plt.scatter(x=[str(x) for x in plot_data_grouped['x']], 
            y=[str(x) for x in plot_data_grouped['y']], 
            s=plot_data_grouped["count"], 
            c=plot_data_grouped['mean'], cmap="RdYlGn", edgecolors="black")
plt.show()

enter image description here


你尝试在传递给 plt.scatter 之前对数据进行排序了吗? - William Miller
是的,它已经排序了。但是scatter似乎在事后按字母顺序对标签进行排序。 - wilsonm2
1
我无法重现您所得到的行为(我的结果)。您使用的matplotlib版本是什么? - William Miller
matplotlib==2.1.1 - wilsonm2
已升级至最新版本的matplotlib,并获得与您相同的输出。不知道有什么更新可以改变这种行为。感谢您的帮助。 - wilsonm2
2个回答

4
有时,升级当前的开发包可能更好。由于您的虚拟环境已安装了本地的matplotlib,请在激活后升级matplotlib。

为此,使用具有 管理员 权限的 终端命令提示符 并尝试使用以下命令升级 pipmatplotlib 版本:

  • python -m pip install --upgrade pip
  • python -m pip install --upgrade matplotlib

另一方面,使用 matplotlib,您可以 获取设置 任一轴(即 x 轴y 轴)的当前刻度位置和标签。


我将给您一个非常简单的例子,让您可以按照顺序在两个轴上绘制给定数据。为了保留上的顺序,您可以简单地使用以下代码:

您可以使用这种技术来解决您的问题,无论是否升级matplotlib。特别是对于您指定的matplotlib==2.1.1版本。


import matplotlib.pyplot as plt

x_axis_values = ['(-68.18100000000001, 89.754]', '(89.754, 130.42]', '(130.42, 165.601]', '(165.601, 205.456]',
                 '(205.456, 371.968]']

y_axis_values = ['(-0.123, 0.749]', '(0.749, 0.922]', '(0.922, 1.068]', '(1.068, 1.253]', '(1.253, 2.14]']

# Try to sort the values, before passing to [xticks, yticks]
# or in which order, you want them along axes
plt.xticks(ticks=range(len(x_axis_values)), labels=x_axis_values)
plt.yticks(ticks=range(len(y_axis_values)), labels=y_axis_values)

# plt.scatter(x_axis_values, y_axis_values)
plt.xlabel('Values')
plt.ylabel('Indices')

plt.show()

这是简单示例的输出。您可以看到沿着x轴y轴的值。给定图形的目的仅在于指定及其两个

enter image description here


针对您提供的代码,我已经进行了以下更新:

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np

n_tile = 5
np.random.seed(0)
x = np.random.normal(150, 70, 3000, )
y = np.random.normal(1, 0.3, 3000)
r = np.random.normal(0.4, 0.1, 3000)

plot_data = pd.DataFrame({
    'x': x,
    'y': y,
    'r': r
})
plot_data['x_group'] = pd.qcut(plot_data['x'], n_tile, duplicates='drop')
plot_data['y_group'] = pd.qcut(plot_data['y'], n_tile, duplicates='drop')
plot_data_grouped = plot_data.groupby(['x_group', 'y_group'], as_index=False).agg({'r': ['mean', 'count']})
plot_data_grouped.columns = ['x', 'y', 'mean', 'count']

cmap = plt.cm.rainbow
norm = matplotlib.colors.Normalize(vmin=0, vmax=1)

########################################################
##########  Updated Portion of the Code ################

x_axis_values = [str(x) for x in plot_data_grouped['x']]
y_axis_values = [str(x) for x in plot_data_grouped['y']]

plt.figure(figsize=(10, 10))
# Unique Values have only length == 5
plt.xticks(ticks=range(5), labels=sorted(np.unique(x_axis_values)))
plt.yticks(ticks=range(5), labels=sorted(np.unique(y_axis_values)))

plt.scatter(x=x_axis_values,
            y=y_axis_values,
            s=plot_data_grouped["count"],
            c=plot_data_grouped['mean'], cmap="RdYlGn", edgecolors="black")

plt.show()
########################################################

现在您可以看到输出结果如所需:

enter image description here


@wilsonm2,我已更新了我的答案。请看一下并确认,如果还能再帮到您,请告诉我。 - Muhammad Usman Bashir

3

这里有两种解决方案。更简单(也更好的)方法是将matplotlib升级到新版本。

如果那不是选项,则首选替代方案是将散点绘图和刻度标签处理分开,这可以很容易地完成。例如:

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np

n_tile = 5
np.random.seed(0)
x = np.random.normal(150, 70, 3000,)
y = np.random.normal(1, 0.3, 3000)
r = np.random.normal(0.4, 0.1, 3000)

plot_data = pd.DataFrame({'x': x, 'y': y, 'r': r})
plot_data['x_group'] = pd.qcut(plot_data['x'], n_tile, duplicates='drop')
plot_data['y_group'] = pd.qcut(plot_data['y'], n_tile, duplicates='drop')
plot_data_grouped = plot_data.groupby(['x_group','y_group'], as_index=False).agg({'r':['mean','count']})
plot_data_grouped.columns = ['x','y','mean','count']

cmap = plt.cm.rainbow
norm = matplotlib.colors.Normalize(vmin=0, vmax=1)

plt.figure(figsize=(10,10))
x = range(len(plot_data_grouped['x']))
y = range(len(plot_data_grouped['y']))
X, Y = np.meshgrid(x, y)
plt.scatter(x=X.flatten(), 
            y=Y.flatten(), 
            s=plot_data_grouped["count"], 
            c=plot_data_grouped['mean'], cmap="RdYlGn", edgecolors="black")
plt.xticks(x, [str(e) for e in plot_data_grouped['x']])
plt.yticks(y, [str(e) for e in plot_data_grouped['y']])
plt.show()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接