【问题标题】:Rounding the marker sizes to a given list of ranges将标记大小四舍五入到给定的范围列表
【发布时间】:2022-12-11 14:36:06
【问题描述】:

我的标记大小根据我的地理数据框中的列而变化,但我想要 5 组的大小。我不希望每个值都有自己的大小,而是希望一系列值具有一个标记大小。

这是代码:

fig, ax = mpl.pyplot.subplots(1, figsize = (10,10))

sns.scatterplot(
    data=fishpts_clip, x="Lon", y="Lat", color='Green', size='SpeciesCatch',
    sizes=(100, 300), legend="full"
)

plt.legend(loc='center left', bbox_to_anchor=(1.05, 0.5), ncol=1, title='Sizes')

这就是我得到的:

相反,我想要这样的东西:

【问题讨论】:

  • 你的问题很有趣,但给出答案就像在黑暗中射击。特别是,您的图例有点不寻常,有人想知道是什么代码产生的。请edit 你的问题,包括你使用的 matplotlib 代码(复制粘贴,如果可能,不要截图)。提亚。

标签: python matplotlib seaborn


【解决方案1】:

您可以创建一个额外的列,其中每个值都四舍五入到所需的界限之一。该新列可用于 sizeshue。要更新图例,值位于边界列表中;该值本身和前一个值构成了新的图例标签。

以下代码说明了简化测试数据的概念。

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

df = pd.DataFrame({'val': np.arange(1, 61),
                   'x': np.arange(60) % 10,
                   'y': np.arange(60) // 10 * 10})

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(16, 5))

sns.scatterplot(data=df, x="x", y="y", hue='val', palette='flare',
                size='val', sizes=(100, 300), legend='full', ax=ax1)
sns.move_legend(ax1, loc='center left', bbox_to_anchor=(1.01, 0.5), ncol=6, title='Sizes')
ax1.set_title('using the given values')

# create an extra column with the values rounded up towards one of the bounds
bounds = [0, 5, 10, 20, 40, 60]
round_to_bound = interpolate.interp1d(bounds, bounds, kind='next', fill_value='extrapolate', bounds_error=False)
df['rounded'] = round_to_bound(df['val']).astype(int)

sns.scatterplot(data=df, x="x", y="y", hue='rounded', palette='flare',
                size='rounded', sizes=(100, 300), ax=ax2)
sns.move_legend(ax2, loc='center left', bbox_to_anchor=(1.01, 0.5), ncol=1, title='Sizes')
for t in ax2.legend_.texts:
     v = int(t.get_text())
     t.set_text(f"{bounds[bounds.index(v) - 1]} - {v}")
ax2.set_title('rounding up the values towards given bounds')
sns.despine()
plt.tight_layout()
plt.show()

视情况而定,将海上传说与其他元素结合起来可能会很复杂。如果你只是在 seaborn 散点图之上添加一个熊猫图,它似乎效果很好。在这种情况下,pandas 向现有图例添加了一个新元素,可以在末尾通过sns.move_legend() 移动它。

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

df = pd.DataFrame({'val': np.arange(1, 61),
                   'x': np.arange(60) % 10,
                   'y': np.arange(60) // 10 * 10})

fig, ax = plt.subplots(figsize=(16, 5))

# create an extra column with the values rounded up towards one of the bounds
bounds = [0, 5, 10, 20, 40, 60]
round_to_bound = interpolate.interp1d(bounds, bounds, kind='next', fill_value='extrapolate', bounds_error=False)
df['rounded'] = round_to_bound(df['val']).astype(int)

sns.scatterplot(data=df, x="x", y="y", hue='rounded', palette='flare',
                size='rounded', sizes=(100, 300), ax=ax)
for t in ax.legend_.texts:
    v = int(t.get_text())
    t.set_text(f"{bounds[bounds.index(v) - 1]} - {v}")

# add a pandas plot on top, which extends the legend
xs = np.linspace(0, 9, 200)
ys = np.random.randn(len(xs)).cumsum() * 2 + 25
dams_clip = pd.DataFrame({'dams_ys': ys}, index=xs)
dams_clip.plot(ax=ax, color="Red", linewidth=0.5, markersize=150, zorder=3)
sns.move_legend(ax, loc='center left', bbox_to_anchor=(1.01, 0.5), ncol=1, title='Sizes')

sns.despine()
plt.tight_layout()
plt.show()

【讨论】:

  • 谢谢@JohanC。我会试试你的方法。
  • 它有效@JohanC,再次感谢你。如何调整颜色?我希望它是单一颜色
  • 您已经在您的示例中这样做了:color='green'而不是palette='flare'。您还需要删除hue=...
  • 谢谢@JohanC。很抱歉打扰您,但是您知道如何使图例标记的颜色与地图中使用的颜色相同吗?使用您的示例并将标记颜色更改为绿色只会更改地图上的颜色,而图例仅为黑色
  • 似乎 seaborn 总是将 size 的图例项目着色为黑色。解决方法可能是for h in ax2.legend_.legendHandles: h.set_color('green')
猜你喜欢
  • 1970-01-01
  • 2015-06-17
  • 2021-08-01
  • 2020-10-22
  • 2021-08-10
  • 2021-05-17
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
相关资源
最近更新 更多