我很难自定义散布图的图例。这是快照:
这是一个代码示例:
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")
此外,如果有帮助,我可以在Jupyter实验室的笔记本中使用Python 3。
首先,我想隐藏CI_CT
变量的名称(图片上以红色显示)。在探究了整个下午的全部文档之后,我发现了get_legend_handlers_label
方法(请参阅here),该方法产生以下结果:
>>> 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'])
在哪里可以找到我亲爱的CI_CT
字符串。但是,我无法更改此名称或将其完全隐藏。我发现了一种肮脏的方式,该方式主要是没有有效地使用作为data
参数传递的数据帧。这是scatterplot
调用:
g = sns.scatterplot("DUMMY_CT", "FOO_CT", data=my_df, size=my_df["CI_CT"].values)
结果在这里:
它可以工作,但是有没有 cleaner 方法来实现这一目标?
在此图例中显示0
级别是不正确的,因为CI_CT
的{{1}}列中没有零值。因此,这对于读者可能会产生误导,他们可能会认为较小的点代表0或1的值。我希望设置一种已定义的比例尺,以这种方式可以针对x和y轴进行设置。但是,我无法实现。有想法吗?
那些冒险使我想知道是否有一种方法可以处理您可以使用my_df
和hue
参数以清晰的x轴和x轴方式传递给散点图的数据。真的有可能吗?
请原谅我的英语,如果问题过于广泛或标签不正确,请告诉我。
答案 0 :(得分:1)
通过指定legend="full"
解决了“绿色问题”,即图例条目多于大小条目。
g = sns.scatterplot(..., 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()
答案 1 :(得分:0)
我终于设法获得了想要的结果,但是采用了丑陋的方式。这对某人可能有用,但我不建议这样做。
将比例尺固定在图例中的解决方案包括将所有CI_CT
列值移至负值(以保持标记大小的顺序和一致性)。然后,图例中显示的值将根据先前的数据更改(来自here的启发)进行校正。
但是,我没有找到一种更好的方法来使图例中的“ 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)
我仍在寻找实现这一目标的更好方法。