Python 如何在matplotlib中按不同组绘制直方图?
我有一张像这样的桌子:Python 如何在matplotlib中按不同组绘制直方图?,python,pandas,matplotlib,plot,histogram,Python,Pandas,Matplotlib,Plot,Histogram,我有一张像这样的桌子: value type 10 0 12 1 13 1 14 2 生成虚拟数据: import numpy as np value = np.random.randint(1, 20, 10) type = np.random.choice([0, 1, 2], 10) 我想使用matplotlib(v1.4)在Python 3中完成一项任务: 绘制值的直方图 按类型分组,即使用不同的颜色来区分类型 “栏”的位置应
value type
10 0
12 1
13 1
14 2
生成虚拟数据:
import numpy as np
value = np.random.randint(1, 20, 10)
type = np.random.choice([0, 1, 2], 10)
我想使用matplotlib(v1.4)在Python 3中完成一项任务:
- 绘制
值的直方图
- 按
,即使用不同的颜色来区分类型类型分组
- “栏”的位置应为“道奇”,即并排
- 由于值的范围很小,我将使用
来表示箱子,即箱子的宽度为1identity
- 如何根据
的值为条形图指定颜色,并从colormap(例如类型
或matplotlib中的其他cmap)绘制颜色?我不想使用命名颜色(即重音
)'b','k','r'
- 我的直方图中的条相互重叠,如何“闪避”这些条
注意
matplotlib.pyplot
可以完成这项任务,而无需导入一堆模块,例如matplotlib.cm
,matplotlib.colors
对于第一个问题,我们可以创建一个等于1的虚拟列,然后通过对该列求和生成计数,并按值和类型分组 对于第二个问题,您可以使用
colormap
参数将colormap直接传递到plot
:
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import seaborn
seaborn.set() #make the plots look pretty
df = pd.DataFrame({'value': value, 'type': type})
df['dummy'] = 1
ag = df.groupby(['value','type']).sum().unstack()
ag.columns = ag.columns.droplevel()
ag.plot(kind = 'bar', colormap = cm.Accent, width = 1)
plt.show()
每当需要绘制一个由另一个变量分组的变量(使用颜色)时,seaborn通常提供比matplotlib或pandas更方便的方法。下面是一个使用seaborn函数的解决方案:
import numpy as np # v 1.19.2
import pandas as pd # v 1.1.3
import matplotlib.pyplot as plt # v 3.3.2
import seaborn as sns # v 0.11.0
# Set parameters for random data
rng = np.random.default_rng(seed=1) # random number generator
size = 50
xmin = 1
xmax = 20
# Create random dataframe
df = pd.DataFrame(dict(value = rng.integers(xmin, xmax, size=size),
val_type = rng.choice([0, 1, 2], size=size)))
# Create histogram with discrete bins (bin width is 1), colored by type
fig, ax = plt.subplots(figsize=(10,4))
sns.histplot(data=df, x='value', hue='val_type', multiple='dodge', discrete=True,
edgecolor='white', palette=plt.cm.Accent, alpha=1)
# Create x ticks covering the range of all integer values of df['value']
ax.set_xticks(np.arange(df['value'].min(), df['value'].max()+1))
# Additional formatting
sns.despine()
ax.get_legend().set_frame_on(False)
plt.show()
# For some reason the palette argument in countplot is not processed the
# same way as in histplot so here I fetch the colors from the previous
# example to make it easier to compare them
colors = [c for c in set([patch.get_facecolor() for patch in ax.patches])]
# Create bar chart of counts of each value grouped by type
fig, ax = plt.subplots(figsize=(10,4))
sns.countplot(data=df, x='value', hue='val_type', palette=colors,
saturation=1, edgecolor='white')
# Additional formatting
sns.despine()
ax.get_legend().set_frame_on(False)
plt.show()
正如您所注意到的,这是一个柱状图而不是条形图,除了数据集中不存在x轴的值(如值12和14)之外,条形图之间没有空间
鉴于pandas中提供的公认答案为条形图,并且条形图可能是在某些情况下显示直方图的相关选择,以下是如何使用函数创建seaborn柱状图:
import numpy as np # v 1.19.2
import pandas as pd # v 1.1.3
import matplotlib.pyplot as plt # v 3.3.2
import seaborn as sns # v 0.11.0
# Set parameters for random data
rng = np.random.default_rng(seed=1) # random number generator
size = 50
xmin = 1
xmax = 20
# Create random dataframe
df = pd.DataFrame(dict(value = rng.integers(xmin, xmax, size=size),
val_type = rng.choice([0, 1, 2], size=size)))
# Create histogram with discrete bins (bin width is 1), colored by type
fig, ax = plt.subplots(figsize=(10,4))
sns.histplot(data=df, x='value', hue='val_type', multiple='dodge', discrete=True,
edgecolor='white', palette=plt.cm.Accent, alpha=1)
# Create x ticks covering the range of all integer values of df['value']
ax.set_xticks(np.arange(df['value'].min(), df['value'].max()+1))
# Additional formatting
sns.despine()
ax.get_legend().set_frame_on(False)
plt.show()
# For some reason the palette argument in countplot is not processed the
# same way as in histplot so here I fetch the colors from the previous
# example to make it easier to compare them
colors = [c for c in set([patch.get_facecolor() for patch in ax.patches])]
# Create bar chart of counts of each value grouped by type
fig, ax = plt.subplots(figsize=(10,4))
sns.countplot(data=df, x='value', hue='val_type', palette=colors,
saturation=1, edgecolor='white')
# Additional formatting
sns.despine()
ax.get_legend().set_frame_on(False)
plt.show()
由于这是条形图,因此不包括值12和14,这会产生一个有点虚假的图,因为没有为这些值显示空白。另一方面,每组条形图之间有一定的间距,便于查看每个条形图所属的值。谢谢。我可以使用
hist
来获得相同的结果,而不按枢轴计数吗?嗯,我不确定你如何使用hist
来实现这一点,我只使用hist来绘制单个序列。