[英]Rounding the marker sizes to a given list of ranges
我的标记大小根据我的地理数据框中的列而变化,但我想要 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')
这就是我得到的:
相反,我想要这样的东西:
您可以创建一个额外的列,其中每个值都四舍五入到所需的界限之一。 该新列可用于sizes
和hue
。 要更新图例,值位于边界列表中; 该值本身和前一个值形成了新图例 label。
以下代码说明了简化测试数据的概念。
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 图例与其他元素结合起来可能会很复杂。 如果你只是在 seaborn 散点图 plot 之上添加一个 pandas plot,它似乎效果很好。 在这种情况下,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()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.