我一生无法找到与此类似的问题,因此我一直在努力寻找解决办法。看来这应该很简单!
设置:我将一些X vs Y数据分组到了bin中,每个bin中都包含X和Y数据点。对于每个垃圾箱,我想绘制X的平均值与Y的平均值以及它们各自的标准差,并且最重要的是:使用Seaborn的“色盲”调色板对每个垃圾箱进行颜色编码(这是强制性的)。
我尝试过的事情:阳光下的一切。线图,散点图,猫图,绘图点。而且当所有这些都不起作用时,我尝试使用matplotlib的“ errorbars”,但是我似乎似乎无法将Seaborn的“ colorblind”调色板导出到matplotlib,因此也很失败。
一些伪代码:
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
some_data = pd.DataFrame({'X':[9,10,11,12,39,40,41,42], 'Y':[99,100,110,111,499,500,510,511], 'Bin':[1,1,1,1,2,2,2,2]})
一些尝试的结果:
sns.pointplot(x="X", y="Y", data=some_data, legend='full', hue='Bin')
Scatterplot完全拧紧了x轴刻度,所以这是我无法解决的另一个问题。
sns.lineplot(x="X", y="Y", data=some_data, legend='full', hue='Bin', err_style="band", estimator="mean", ci='sd')
更好,但是它只是在两点之间画一条线,而不是计算均值和标准差,我认为当我指定估计量和置信区间方法时,它将这样做!!!
sns.scatterplot(x="X", y="Y", data=some_data, legend='full', hue='Bin')
散点图很好,但是它不具备 estimator 功能,所以我只是在绘制原始数据。
我完全不知道该怎么办。我整晚都在这。现在是凌晨4:30,过去几天晚上我几乎没睡。任何帮助将不胜感激!
答案 0 :(得分:3)
以下方法使用均值和sdevs绘制椭圆:
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import pandas as pd
import seaborn as sns
df = pd.DataFrame({'X':[9,10,11,12,39,40,41,42], 'Y':[99,100,110,111,499,500,510,511], 'Bin':[1,1,1,1,2,2,2,2]})
means = df.groupby('Bin').mean()
sdevs = df.groupby('Bin').std()
fig, ax = plt.subplots()
colors = ['crimson', 'dodgerblue']
sns.scatterplot(x='X', y='Y', hue='Bin', palette=colors, data=df, ax=ax)
sns.scatterplot(x='X', y='Y', data=means, color='limegreen', label='means', ax=ax)
for (_, mean), (_, sdev), color in zip(means.iterrows(), sdevs.iterrows(), colors):
ellipse = Ellipse((mean['X'], mean['Y']), width=2*sdev['X'], height=2*sdev['Y'],
facecolor=color, alpha=0.3)
ax.add_patch(ellipse)
plt.show()
这是一个更详细的示例,显示椭圆为标准偏差的1、2和3倍。
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import pandas as pd
import numpy as np
import seaborn as sns
K = 5
N = 100
df = pd.DataFrame({'X': np.random.normal(np.tile(np.random.uniform(10, 40, K), N), np.tile([3, 4, 7, 9, 10], N)),
'Y': np.random.normal(np.tile(np.random.uniform(90, 500, K), N), np.tile([20, 25, 8, 22, 18], N)),
'Bin': np.tile(np.arange(1, K + 1), N)})
means = df.groupby('Bin').mean()
sdevs = df.groupby('Bin').std()
fig, axes = plt.subplots(ncols=2, figsize=(12, 4))
colors = ['crimson', 'dodgerblue', 'limegreen', 'turquoise', 'gold']
for ax in axes:
sns.scatterplot(x='X', y='Y', hue='Bin', palette=colors, s=5, ec='none', data=df, ax=ax)
sns.scatterplot(x='X', y='Y', marker='o', s=50, fc='none', ec='black', label='means', data=means, ax=ax)
if ax == axes[1]:
for (_, mean), (_, sdev), color in zip(means.iterrows(), sdevs.iterrows(), colors):
for sdev_mult in [1, 2, 3]:
ellipse = Ellipse((mean['X'], mean['Y']), width=2 * sdev['X'] * sdev_mult,
height=2 * sdev['Y'] * sdev_mult,
facecolor=color, alpha=0.2 if sdev_mult == 1 else 0.1)
ax.add_patch(ellipse)
plt.show()
答案 1 :(得分:1)
我承认这不是完整的答案-但我希望它对数据统计有所帮助,并为您提供有关绘图的方向。我对matplot / seaborn并不十分满意,因此,为了解决这个问题,我迅速将其绘制成图。我希望它至少可以为您提供一些指导...
import pandas as pd
from plotly.offline import iplot
x = [9, 10, 11, 12, 39, 40, 41, 42]
y = [99, 100, 110, 111, 499, 500, 510, 511]
b = [1, 1, 1, 1, 2, 2, 2, 2]
df = pd.DataFrame({'x': x, 'y': y, 'bin': b})
df = df.groupby(['bin']).agg(['mean', 'std'])
df.columns = ['_'.join(c).rstrip('_') for c in df.columns.to_list()]
df.reset_index(inplace=True)
bin x_mean x_std y_mean y_std
0 1 10.5 1.290994 105 6.377042
1 2 40.5 1.290994 505 6.377042
data = []
for row in df.itertuples():
data.append({'x': [row.x_mean],
'y': [row.y_mean],
'mode': 'markers',
'name': '{} mean'.format(row.bin),
'marker': {'size': 25}})
data.append({'x': [row.x_std],
'y': [row.y_std],
'mode': 'markers',
'name': '{} std'.format(row.bin),
'marker': {'size': 25}})
iplot({'data': data})
请注意,由于标准品相同,红色/紫色点相互重叠。
我希望这会有所帮助...