Pandas 使用散点图自定义图例

Pandas 使用散点图自定义图例,pandas,matplotlib,seaborn,Pandas,Matplotlib,Seaborn,我努力定制我的散点图的传奇。以下是一个快照: 下面是一个代码示例: import pandas as pd import seaborn as sns import matplotlib.pyplot as plt sns.set() my_df = pd.DataFrame([[5, 3, 1], [2, 1, 2], [3, 4, 1], [1, 2, 1]], columns=["DUMMY_CT", "FOO_CT", "CI_CT"])

我努力定制我的散点图的传奇。以下是一个快照:

下面是一个代码示例:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set()

my_df = pd.DataFrame([[5, 3, 1], [2, 1, 2], [3, 4, 1], [1, 2, 1]],
                     columns=["DUMMY_CT", "FOO_CT", "CI_CT"])

g = sns.scatterplot("DUMMY_CT", "FOO_CT", data=my_df, size="CI_CT")
g.set_title("Number of Baz", weight="bold")
g.set_xlabel("Dummy count")
g.set_ylabel("Foo count")
g.get_legend().set_title("Baz count")
此外,如果有帮助的话,我还使用Python3在Jupyter实验室笔记本上工作

红色问题 首先,我想隐藏
CI\u CT
变量的名称(在图片上用红色表示)。在浏览了今天下午的整个文档之后,我找到了
get\u legend\u handlers\u label
方法(请参阅),该方法生成以下内容:

>>> g.get_legend_handles_labels()
([<matplotlib.collections.PathCollection at 0xfaaba4a8>,
  <matplotlib.collections.PathCollection at 0xfaa3ff28>,
  <matplotlib.collections.PathCollection at 0xfaa3f6a0>,
  <matplotlib.collections.PathCollection at 0xfaa3fe48>],
  ['CI_CT', '0', '1', '2'])
结果如下:

这是可行的,但有没有更干净的方法来实现这一点

绿色问题 在此图例中显示
0
级别是不正确的,因为
my\u df
CI\u CT
列中没有零值。因此,这对读者来说是误导性的,他们可能认为较小的点代表0或1的值。我希望设置一个定义的比例,就像人们可以为x轴和y轴设置的那样。然而,我无法做到这一点。有什么想法吗

TL;博士:一个可以解决一切的更广泛的问题 这些冒险让我想知道是否有一种方法可以处理你可以通过
色调
大小
参数以干净的x轴和y轴方式传递到散点图的数据。真的有可能吗


请原谅我的英语,请告诉我问题是否太宽泛或标签不正确。

我终于得到了我想要的结果,但是方法很难看。这可能对某人有用,但我不建议这样做

将比例固定到图例中的解决方案包括将所有
CI\u CT
列值移动到负数(以保持标记大小的顺序和一致性)。然后,图例中显示的值将根据以前的数据更改(灵感来源)进行相应的校正

然而,我没有找到更好的方法,在不留下巨大空白的情况下,让“CI_CT”文本在传说中脱颖而出

下面是代码示例和结果

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set()

my_df = pd.DataFrame([[5, 3, 1], [2, 1, 2], [3, 4, 1], [1, 2, 1]], columns=["DUMMY_CT", "FOO_CT", "CI_CT"])

# Substracting the maximal value of CI_CT for each value
max_val = my_df["CI_CT"].agg("max")
my_df["CI_CT"] = my_df.apply(lambda x : x["CI_CT"] - max_val, axis=1)

# scatterplot declaration
g = sns.scatterplot("DUMMY_CT", "FOO_CT", data=my_df, size=my_df["CI_CT"].values)
g.set_title("Number of Baz", weight="bold")
g.set_xlabel("Dummy count")
g.set_ylabel("Foo count")
g.get_legend().set_title("Baz count")

# Correcting legend values
l = g.legend_
for t in l.texts :
    t.set_text(int(t.get_text()) + max_val)

# Restoring the DF
my_df["CI_CT"] = my_df.apply(lambda x : x["CI_CT"] + max_val, axis=1)

我仍在寻找更好的方法来实现这一点。

通过指定
legend=“full”
可以解决“绿色问题”,即图例条目比大小多一个

“红色事物问题”更为棘手。这里的问题是seaborn误用了一个普通的图例标签作为图例的标题。实际上,一个选项是直接提供值而不是列名,以防止seaborn使用该列名

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set()

my_df = pd.DataFrame([[5, 3, 1], [2, 1, 2], [3, 4, 1], [1, 2, 1]],
                     columns=["DUMMY_CT", "FOO_CT", "CI_CT"])

g = sns.scatterplot("DUMMY_CT", "FOO_CT", data=my_df, size=my_df["CI_CT"].values, legend="full")
g.set_title("Number of Baz", weight="bold")
g.set_xlabel("Dummy count")
g.set_ylabel("Foo count")
g.get_legend().set_title("Baz count")

plt.show()

如果你真的必须使用列名本身,一个很有技巧的解决方案是爬进图例中,删除你不想要的标签

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set()

my_df = pd.DataFrame([[5, 3, 1], [2, 1, 2], [3, 4, 1], [1, 2, 1]],
                     columns=["DUMMY_CT", "FOO_CT", "CI_CT"])

g = sns.scatterplot("DUMMY_CT", "FOO_CT", data=my_df, size="CI_CT", legend="full")
g.set_title("Number of Baz", weight="bold")
g.set_xlabel("Dummy count")
g.set_ylabel("Foo count")
g.get_legend().set_title("Baz count")

#Hack to remove the first legend entry (which is the undesired title)
vpacker = g.get_legend()._legend_handle_box.get_children()[0]
vpacker._children = vpacker.get_children()[1:]

plt.show()

既然您没有提供解决方案,我就不必费心从头开始编写一个有效的解决方案。相反,我可以告诉你。所有这些都显示了如何访问图例句柄和标签并进行设置later@Bazingaa我为这个完整的最小工作示例道歉,我写这篇文章的时候非常累。我会尽快提供,因为我附近没有电脑。我会查看这些链接,谢谢。@Bazingaa我根据您的建议相应地更新了问题。我也在检查你提供的链接。它们真的很有教育意义,很遗憾我之前没有找到它们。谢谢你的回答。这对我会有很大帮助!
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set()

my_df = pd.DataFrame([[5, 3, 1], [2, 1, 2], [3, 4, 1], [1, 2, 1]],
                     columns=["DUMMY_CT", "FOO_CT", "CI_CT"])

g = sns.scatterplot("DUMMY_CT", "FOO_CT", data=my_df, size=my_df["CI_CT"].values, legend="full")
g.set_title("Number of Baz", weight="bold")
g.set_xlabel("Dummy count")
g.set_ylabel("Foo count")
g.get_legend().set_title("Baz count")

plt.show()
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set()

my_df = pd.DataFrame([[5, 3, 1], [2, 1, 2], [3, 4, 1], [1, 2, 1]],
                     columns=["DUMMY_CT", "FOO_CT", "CI_CT"])

g = sns.scatterplot("DUMMY_CT", "FOO_CT", data=my_df, size="CI_CT", legend="full")
g.set_title("Number of Baz", weight="bold")
g.set_xlabel("Dummy count")
g.set_ylabel("Foo count")
g.get_legend().set_title("Baz count")

#Hack to remove the first legend entry (which is the undesired title)
vpacker = g.get_legend()._legend_handle_box.get_children()[0]
vpacker._children = vpacker.get_children()[1:]

plt.show()