如何根据列值绘制带标记的散点图

3
我正在尝试绘制一个带有分组的散点图。它们是按列group分组的,我希望它们基于不同的组具有不同的标记样式

最小工作代码

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

colors = ['r','g','b','y']
markers = ['o', '^', 's', 'P']

df = pd.DataFrame()
df["index"] = list(range(100))
df["data"] = np.random.randint(100, size=100)
df["group"] = np.random.randint(4, size=100)
df["color"] = df.apply(lambda x: colors[x["group"]], axis=1)
df["marker"] = df.apply(lambda x: markers[x["group"]], axis=1)

plt.scatter(x=df["index"], y=df["data"], c=df["color"])
# What I thought would have worked
# plt.scatter(x=df["index"], y=df["data"], c=df["color"], marker=df["marker"])
plt.show()

example_output

我想要什么

我希望不同的分组有不同的标记样式。例如,红色条目将具有标记“o”(大点),绿色条目将具有标记“^”(向上三角形)等。

我尝试了什么

我认为

plt.scatter(x=df["index"], y=df["data"], c=df["color"], marker=df["marker"])

"本来可以工作的,但不行..."
TypeError: 'Series' objects are mutable, thus they cannot be hashed

我可以使用 for 循环遍历 DataFrame,并按其 group 对条目进行分组。然后使用设置为定义的列表的 marker 参数来绘制它们(例如 plt.scatter(..., marker=markers[group]))。这将导致 4 个 plt.scatter(...),因为总共有 4 个组。但是,在我看来,逐行循环 DataFrame 是不好看的,我坚信有更好的方法。

提前致谢!


1
我尝试着看是否可以在列表中支持各种散点图标记,但似乎仍然不可能。最好的方法是将其作为一个函数实现,具体描述见此答案 - r-beginners
2
作为一种替代方法,如果您使用Seaborn,以下代码可以解决问题。 sns.scatterplot(x=df["index"], y=df["data"], c=df["color"],style=df['marker']) - r-beginners
@r-beginners 让我来看看Seaborn :D - Henry Fung
1个回答

5

matplotlib

在我看来,通过逐行循环DataFrame是丑陋的,我强烈认为有更好的方法。

使用matplotlib,我认为没有比循环更好的方法。请注意,如果您将标记groupby,它不会逐行循环,只会按组分组(在此情况下为4次)。

这将调用plt.scatter 4次(每个标记一次):

for marker, d in df.groupby('marker'):
    plt.scatter(x=d['index'], y=d['data'], c=d['color'], marker=marker, label=marker)
plt.legend()


seaborn

正如r-beginners所评论的那样,sns.scatterplot通过style支持多个标记:

sns.scatterplot(x=df['index'], y=df['data'], c=df['color'], style=df['marker'])


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