如何旋转 Seaborn 折线图

3

我该如何旋转一个seaborn.lineplot使得结果基于y而不是x。

例如,以下代码:

import pandas as pd
import seaborn as sns
df = pd.DataFrame([[0,1],[0,2],[0,1.5],[1,1],[1,5]], columns=['group','val'])
sns.lineplot(x='group',y='val',data=df)

创建这个图表:

enter image description here

但是有没有一种方法可以将图表旋转90°?这样我们就会在X轴上有“val”,在Y轴上有“group”,并且std将从左到右而不是从下到上。
谢谢
编辑:我已在seaborn中开了一个票,以请求此功能:https://github.com/mwaskom/seaborn/issues/1661
2个回答

2
根据seaborn文档中关于lineplot的说明,传递给data的数据框必须是整洁(“长格式”)的数据框,其中每个列都是一个变量,每一行都是一个观察值。这似乎意味着即使通过操纵数据,也没有办法强制切换轴。如果有方法可以做到这一点,我还没有找到它 - 我相信有更优雅的方法来解决这个问题,但你可以手动处理。像这样做就可以了:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
df = pd.DataFrame([[0,1],[0,2],[0,1.5],[1,1],[1,5]], columns=['group','val'])
group = df['group'].tolist()
val = df['val'].tolist()
yl = list()
yu = list()
avg = list()
ii = 0
while ii < len(group):   #Loop through all the groups
    g = group[ii]
    y0 = val[ii]
    y1 = val[ii]
    s = 0
    jj = ii
    while (jj < len(group) and group[jj] == g):
        s += val[jj]
        #This takes the min and max, but could easily take the standard deviation
        if val[jj] > y1:
            y1 = val[jj]
        if val[jj] < y0:
            y0 = val[jj]
        jj += 1
    avg.append(s/(jj - ii))
    ii = jj
    yl.append(y0)
    yu.append(y1)

x = np.linspace(min(group), max(group), len(yl))
plt.ylabel(df.columns[0])
plt.xlabel(df.columns[1])
plt.plot(avg, x, color="#5a9edd", linestyle="-", linewidth=1.5)
plt.fill_betweenx(x, yl, yu, alpha=0.3)

这将为您提供以下图表:
enter image description here
为了简洁起见,此处使用每个组的最小值和最大值来给出误差带,但可以根据需要轻松更改为标准误差或标准偏差。

1
考虑如果不使用seaborn会怎样做。您需要计算均值和标准差,并将其作为组的函数绘制出来。现在,非常容易通过plot(x,y)交换x和y:plot(y,x)。对于填充区域,您可以使用fill_betweenx而不是fill_between
下面是两种情况的比较。
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame([[0,1],[0,2],[0,1.5],[1,1],[1,5]], columns=['group','val'])

mean = df.groupby("group").mean()
std = df.groupby("group").std()

fig, (ax, ax2) = plt.subplots(ncols=2)

ax.plot(mean.index, mean["val"].values)
ax.fill_between(mean.index, (mean-std)["val"].values, (mean+std)["val"].values, alpha=.5)
ax.set(xlabel="group", ylabel="val")

ax2.plot(mean["val"].values, mean.index)
ax2.fill_betweenx(mean.index, (mean-std)["val"].values, (mean+std)["val"].values, alpha=.5)
ax2.set(ylabel="group", xlabel="val")

fig.tight_layout()
plt.show()

enter image description here


1
谢谢,如果您(130k rep)说从seaborn内部不可能实现,我明白我必须找到一个解决方法。谢谢。 - Oren
嗯,解决方法是(例如)这个答案。还要考虑到即使在“未转置”情况下,数据聚合和绘图的分离也有很多优点。总之,可能的替代方案是这个答案,其中从图中提取并转置了数据。 - ImportanceOfBeingErnest
1
谢谢,由于seaborn中不存在这个功能,我会接受你的答案。 - Oren
如果一开始就说明Seaborn中不存在这个功能,那么这个答案会更清晰明了。 - semblable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接