Python Seaborn 中小平面网格上的箱线图离群值注释
Boxplot outlier annotation over facet grid in Python Seaborn
我正在用 Python Seaborn 包绘制箱线图。我有包含行和列的小平面网格。我已经能够使用 Seaborn 函数 catplot.
我也想注释异常值。我在 SO 找到了一些很好的例子来注释异常值但没有刻面结构。这就是我挣扎的地方。
这是我得到的(大量借用这个 post:Boxplot : Outliers Labels Python):
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.cbook import boxplot_stats
sns.set_style('darkgrid')
Month = np.repeat(np.arange(1, 11), 10)
Id = np.arange(1, 101)
Value = np.random.randn(100)
Row = ["up", "down"]*50
df = pd.DataFrame({'Value': Value, 'Month': Month, 'Id': Id, 'Row': Row})
g = sns.catplot(data=df, x="Month", y="Value", row="Row", kind="box", height=3, aspect=3)
for name, group in df.groupby(["Month", "Row"]):
fliers = [y for stat in boxplot_stats(group["Value"]) for y in stat["fliers"]]
d = group[group["Value"].isin(fliers)]
g.axes.flatten().annotate(d["Id"], xy=(d["Month"] - 1, d["Value"]))
数据框d按补丁收集所有异常值。最后一行旨在将 d 与图 g 补丁相匹配。但是,这不起作用,但我还没有找到一种方法将轴展平到一个列表,其中每个元素都对应于一个分组的数据框元素。
我很高兴听到实现此目的的替代版本。
一种方法:
for name, group in df.groupby(["Month", "Row"]):
fliers = [y for stat in boxplot_stats(group["Value"]) for y in stat["fliers"]]
d = group[group["Value"].isin(fliers)]
for i in range(len(d)):
ngrid = (0 if d.iloc[i,3]=='up' else 1)
g.fig.axes[ngrid].annotate(d.iloc[i, 2], xy=(d.iloc[i, 1] - 1, d.iloc[i, 0]))
您可以循环 g.axes_dict
来访问每个轴。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.cbook import boxplot_stats
sns.set_style('darkgrid')
Month = np.repeat(np.arange(1, 11), 10)
Id = np.arange(1, 101)
Value = np.random.randn(100)
Row = ["up", "down"] * 50
df = pd.DataFrame({'Value': Value, 'Month': Month, 'Id': Id, 'Row': Row})
g = sns.catplot(data=df, x="Month", y="Value", row="Row", kind="box", height=3, aspect=3)
for row, ax in g.axes_dict.items():
for month in np.unique(df["Month"]):
group = df.loc[(df["Row"] == row) & (df["Month"] == month), :]
fliers = boxplot_stats(group["Value"])[0]["fliers"]
if len(fliers) > 0:
for mon, val, id in zip(group["Month"], group["Value"], group["Id"]):
if val in fliers:
ax.annotate(f' {id}', xy=(mon - 1, val))
plt.tight_layout()
plt.show()
我正在用 Python Seaborn 包绘制箱线图。我有包含行和列的小平面网格。我已经能够使用 Seaborn 函数 catplot.
我也想注释异常值。我在 SO 找到了一些很好的例子来注释异常值但没有刻面结构。这就是我挣扎的地方。
这是我得到的(大量借用这个 post:Boxplot : Outliers Labels Python):
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.cbook import boxplot_stats
sns.set_style('darkgrid')
Month = np.repeat(np.arange(1, 11), 10)
Id = np.arange(1, 101)
Value = np.random.randn(100)
Row = ["up", "down"]*50
df = pd.DataFrame({'Value': Value, 'Month': Month, 'Id': Id, 'Row': Row})
g = sns.catplot(data=df, x="Month", y="Value", row="Row", kind="box", height=3, aspect=3)
for name, group in df.groupby(["Month", "Row"]):
fliers = [y for stat in boxplot_stats(group["Value"]) for y in stat["fliers"]]
d = group[group["Value"].isin(fliers)]
g.axes.flatten().annotate(d["Id"], xy=(d["Month"] - 1, d["Value"]))
数据框d按补丁收集所有异常值。最后一行旨在将 d 与图 g 补丁相匹配。但是,这不起作用,但我还没有找到一种方法将轴展平到一个列表,其中每个元素都对应于一个分组的数据框元素。
我很高兴听到实现此目的的替代版本。
一种方法:
for name, group in df.groupby(["Month", "Row"]):
fliers = [y for stat in boxplot_stats(group["Value"]) for y in stat["fliers"]]
d = group[group["Value"].isin(fliers)]
for i in range(len(d)):
ngrid = (0 if d.iloc[i,3]=='up' else 1)
g.fig.axes[ngrid].annotate(d.iloc[i, 2], xy=(d.iloc[i, 1] - 1, d.iloc[i, 0]))
您可以循环 g.axes_dict
来访问每个轴。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.cbook import boxplot_stats
sns.set_style('darkgrid')
Month = np.repeat(np.arange(1, 11), 10)
Id = np.arange(1, 101)
Value = np.random.randn(100)
Row = ["up", "down"] * 50
df = pd.DataFrame({'Value': Value, 'Month': Month, 'Id': Id, 'Row': Row})
g = sns.catplot(data=df, x="Month", y="Value", row="Row", kind="box", height=3, aspect=3)
for row, ax in g.axes_dict.items():
for month in np.unique(df["Month"]):
group = df.loc[(df["Row"] == row) & (df["Month"] == month), :]
fliers = boxplot_stats(group["Value"])[0]["fliers"]
if len(fliers) > 0:
for mon, val, id in zip(group["Month"], group["Value"], group["Id"]):
if val in fliers:
ax.annotate(f' {id}', xy=(mon - 1, val))
plt.tight_layout()
plt.show()