我在同一张图上绘制了seaborn中的几个点图。 x轴是序数,而不是数字;每个点图的序数值相同。我想将每个绘图稍微移到一边,pointplot(dodge = ...)参数的方式在单个绘图中的多行内,但在这种情况下,绘制在彼此之上的多个不同绘图。我怎么能这样做?
理想情况下,我喜欢一种适用于任何matplotlib情节的技术,而不仅仅是seaborn。为数据添加偏移量很容易,因为数据不是数字。
显示重叠图并使其难以阅读的示例(每个图中的闪避效果正常)
import pandas as pd
import seaborn as sns
df1 = pd.DataFrame({'x':list('ffffssss'), 'y':[1,2,3,4,5,6,7,8], 'h':list('abababab')})
df2 = df1.copy()
df2['y'] = df2['y']+0.5
sns.pointplot(data=df1, x='x', y='y', hue='h', ci='sd', errwidth=2, capsize=0.05, dodge=0.1, markers='<')
sns.pointplot(data=df2, x='x', y='y', hue='h', ci='sd', errwidth=2, capsize=0.05, dodge=0.1, markers='>')
我可以使用除了seaborn以外的其他东西,但自动置信度/误差栏非常方便,所以我更喜欢在这里坚持使用seaborn。
答案 0 :(得分:3)
首先回答最常见的情况。
可以通过将图中的艺术家移动一些量来实现躲闪。使用点作为该班次的单位可能是有用的。例如。你可能想把你在地块上的标记移动5点
这种转变可以通过向艺术家的数据转换添加翻译来实现。在这里,我建议ScaledTranslation
。
现在为了保持这一点,我们可以编写一个函数,它将绘图方法,轴和数据作为输入,另外还有一些闪避应用,例如
draw_dodge(ax.errorbar, X, y, yerr =y/4., ax=ax, dodge=d, marker="d" )
完整的功能代码:
import matplotlib.pyplot as plt
from matplotlib import transforms
import numpy as np
import pandas as pd
def draw_dodge(*args, **kwargs):
func = args[0]
dodge = kwargs.pop("dodge", 0)
ax = kwargs.pop("ax", plt.gca())
trans = ax.transData + transforms.ScaledTranslation(dodge/72., 0,
ax.figure.dpi_scale_trans)
artist = func(*args[1:], **kwargs)
def iterate(artist):
if hasattr(artist, '__iter__'):
for obj in artist:
iterate(obj)
else:
artist.set_transform(trans)
iterate(artist)
return artist
X = ["a", "b"]
Y = np.array([[1,2],[2,2],[3,2],[1,4]])
Dodge = np.arange(len(Y),dtype=float)*10
Dodge -= Dodge.mean()
fig, ax = plt.subplots()
for y,d in zip(Y,Dodge):
draw_dodge(ax.errorbar, X, y, yerr =y/4., ax=ax, dodge=d, marker="d" )
ax.margins(x=0.4)
plt.show()
您可以将其与ax.plot
,ax.scatter
等一起使用。但不能使用任何seaborn函数,因为它们不会返回任何有用的艺术家。
现在针对相关案例,剩下的问题是以有用的格式获取数据。一种选择如下。
df1 = pd.DataFrame({'x':list('ffffssss'),
'y':[1,2,3,4,5,6,7,8],
'h':list('abababab')})
df2 = df1.copy()
df2['y'] = df2['y']+0.5
N = len(np.unique(df1["x"].values))*len([df1,df2])
Dodge = np.linspace(-N,N,N)/N*10
fig, ax = plt.subplots()
k = 0
for df in [df1,df2]:
for (n, grp) in df.groupby("h"):
x = grp.groupby("x").mean()
std = grp.groupby("x").std()
draw_dodge(ax.errorbar, x.index, x.values,
yerr =std.values.flatten(), ax=ax,
dodge=Dodge[k], marker="o", label=n)
k+=1
ax.legend()
ax.margins(x=0.4)
plt.show()
答案 1 :(得分:0)
您可以使用linspace轻松地将图形移动到希望它们开始和结束的位置。该功能还使缩放图形变得非常容易,因此它们在视觉上的宽度相同
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
start_offset = 3
end_offset = start_offset
y1 = np.random.randint(0, 10, 20) ##y1 has 20 random ints from 0 to 10
y2 = np.random.randint(0, 10, 10) ##y2 has 10 random ints from 0 to 10
x1 = np.linspace(0, 20, y1.size) ##create a number of steps from 0 to 20 equal to y1 array size-1
x2 = np.linspace(0, 20, y2.size)
plt.plot(x1, y1)
plt.plot(x2, y2)
plt.show()