带有多个标记的分组条形图

时间:2021-04-13 10:17:47

标签: python pandas matplotlib

我正在使用 pandas.plot 创建分组条形图。我想用每个数据点的两个不同标记覆盖该图表。 IRL 标记代表来自先前时间段的相同数据。我知道如何使用 kind='line'linestyle='None' 创建标记,但我不知道如何让它们与条形对齐。所需的输出将为每个数据点(来自下面 MRE 中的 df)提供一个彩色条,并且与该条对齐的是两个可区分的标记,分别代表 df2df3

我想创建另一个仅使用标记的条形图,但 AFAIK 是不可能的。我还陷入了使用 yerr 的兔子洞,如本例所示: How can I add markers on a bar graph in python?

但似乎不可能为上/下误差生成两个单独的标记,这在此处是必要的。

这是我想要实现的一个简单示例,唯一的问题是标记的 x 对齐。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.figure import Figure

df_data = {'A':np.random.randint(20, 50, 5),
            'B':np.random.randint(10, 50, 5),
            'C':np.random.randint(30, 50, 5),
            'D':np.random.randint(30, 100, 5)}

df2_data = {'A':np.random.randint(20, 50, 5),
            'B':np.random.randint(10, 50, 5),
            'C':np.random.randint(30, 50, 5),
            'D':np.random.randint(30, 100, 5)} 

df3_data = {'A':np.random.randint(20, 50, 5),
            'B':np.random.randint(10, 50, 5),
            'C':np.random.randint(30, 50, 5),
            'D':np.random.randint(30, 100, 5)} 

df = pd.DataFrame(data=df_data)
df2 = pd.DataFrame(data=df2_data)
df3 = pd.DataFrame(data=df3_data)

fig = plt.figure()
bar_colors = ['red', 'blue', 'green', 'goldenrod']
ax = fig.gca()
df2.plot(kind='line', ax=ax, linestyle='None', marker='^',
        color=bar_colors,
        markerfacecolor='white', legend=False)
df3.plot(kind='line', ax=ax, linestyle='None', marker='o',
        color=bar_colors,
        markerfacecolor='white', legend=False)
df.plot(kind='bar', ax=ax, color=bar_colors, width=0.8, rot=0)

plt.show()

2 个答案:

答案 0 :(得分:1)

使用 seaborn 的 pointplot,您可以使用 dodge= 来展开标记,类似于条形。但是,对 pointplotbarplot 使用的闪避宽度的解释是不同的。此宽度可以按照 this github issue 中的注释进行调整。

似乎还没有选项可以将面部颜色与标记边缘颜色分开调整。但它们可以在之后更改。此外,图例将包含所有元素,并且可以更改为仅包含最后 4 个。

由于 seaborn 更喜欢 "long form" 中的数据帧,因此需要使用 melt。以及为原始索引创建显式列。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

df_data = {'A': np.random.randint(20, 50, 5),
           'B': np.random.randint(10, 50, 5),
           'C': np.random.randint(30, 50, 5),
           'D': np.random.randint(30, 100, 5)}
df2_data = {'A': np.random.randint(20, 50, 5),
            'B': np.random.randint(10, 50, 5),
            'C': np.random.randint(30, 50, 5),
            'D': np.random.randint(30, 100, 5)}
df3_data = {'A': np.random.randint(20, 50, 5),
            'B': np.random.randint(10, 50, 5),
            'C': np.random.randint(30, 50, 5),
            'D': np.random.randint(30, 100, 5)}
df = pd.DataFrame(data=df_data)
df2 = pd.DataFrame(data=df2_data)
df3 = pd.DataFrame(data=df3_data)

bar_colors = ['red', 'blue', 'green', 'goldenrod']
dogde_width = .8 - .8 / len(bar_colors)
ax = sns.pointplot(data=df2.melt(ignore_index=False).reset_index(),
                   x='index', y='value', hue='variable', linestyles='', markers='^',
                   palette=bar_colors, dodge=dogde_width)
sns.pointplot(data=df3.melt(ignore_index=False).reset_index(),
              x='index', y='value', hue='variable', linestyles='', markers='o',
              palette=bar_colors, dodge=dogde_width, ax=ax)
sns.barplot(data=df.melt(ignore_index=False).reset_index(),
            x='index', y='value', hue='variable',
            palette=bar_colors, dodge=True, ax=ax)
handles, labels = ax.get_legend_handles_labels()
leg_num = len(bar_colors)
ax.legend(handles[-leg_num:], labels[-leg_num:])  # use only four last elements for the legend
for markers in ax.collections:
    markers.set_facecolor('white')
    markers.set_linewidth(1)
plt.show()

seaborn barplot combined with pointplots

答案 1 :(得分:1)

使用 matplotlibs bar() 和 scatter() 我想出了这个解决方案:

#Exchange 2010 Script
$fwds = get-mailbox | Where-Object { $_.ForwardingAddress -ne $null } | select Name, ForwardingAddress, DeliverToMailboxAndForward

foreach ($fwd in $fwds) 
{

    $ErrorActionPreference = "SilentlyContinue"
    $fwd | add-member -membertype noteproperty -name "ContactAddress" -value (get-contact $fwd.ForwardingAddress).WindowsEmailAddress
    $ErrorActionPreference = "Continue"


    #Maakt objecten aan die in C# uit te lezen zijn

    if($fwd.ContactAddress)
    {
        $properties = @{
        Name = $fwd.Name
        ContactAddress = $fwd.ContactAddress
        DeliverToMailboxAndForward = $fwd.DeliverToMailboxAndForward
        }
        $o = New-Object psobject -Property $properties;

        # Dit zet het object bruikbaar als object in c#
        Write-Output $o
    }
}

这应该是这样的:

enter image description here

您可以尝试不同的标记和颜色。