18

ギャラリーの例に従って、matplotlib でグループ化された棒グラフを作成しようとしています。私は以下を使用します:

import matplotlib.pyplot as plt
plt.figure(figsize=(7,7), dpi=300)
xticks = [0.1, 1.1]
groups = [[1.04, 0.96],
          [1.69, 4.02]]
group_labels = ["G1", "G2"]
num_items = len(group_labels)
ind = arange(num_items)
width = 0.1
s = plt.subplot(1,1,1)
for num, vals in enumerate(groups):
    print "plotting: ", vals
    group_len = len(vals)
    gene_rects = plt.bar(ind, vals, width,
                         align="center")
    ind = ind + width
num_groups = len(group_labels)
# Make label centered with respect to group of bars
# Is there a less complicated way?
offset = (num_groups / 2.) * width
xticks = arange(num_groups) + offset
s.set_xticks(xticks)
print "xticks: ", xticks
plt.xlim([0 - width, max(xticks) + (num_groups * width)])
s.set_xticklabels(group_labels)

ここに画像の説明を入力

私の質問は次のとおりです。

  1. バーのグループ間のスペースを制御するにはどうすればよいですか? 現在、間隔は大きく、ばかげているように見えます。私はバーを広くしたくないことに注意してください - 私はバーを同じ幅にしたいのですが、互いに近づけたいと思っています。

  2. バーのグループの下にラベルを中央に配置するにはどうすればよいですか? xlabels を適切な場所に配置するためにいくつかの算術計算を考え出そうとしましたが (上記のコードを参照)、まだ少しずれています... プロット ライブラリを使用するのではなく、プロット ライブラリを作成するように感じます。これはどのように修正できますか?(これがデフォルトの動作であるmatplotlibのラッパーまたは組み込みユーティリティはありますか?)

編集: @mlgill に返信: ご回答ありがとうございます。コードは確かにはるかに洗練されていますが、同じ問題、つまり、バーの幅とグループ間の間隔が個別に制御されていないという問題があります。あなたのグラフは正しいように見えますが、バーが広すぎます。Excel グラフのように見えます。バーを細くしたかったのです。

幅とマージンがリンクされるようになったので、試してみると:

margin = 0.60
width = (1.-2.*margin)/num_items

バーは細くなりますが、グループが離れてしまうため、プロットは再び正しく表示されません。

各バーの幅とバー グループ間の間隔の 2 つのパラメーターを取り、コードのように正しくプロットする、グループ化されたバー プロット関数を作成するにはどうすればよいですか?

ユーザーはマージンや幅などの特定の低レベルのレイアウト量を計算する必要があるため、基本的にはまだプロット ライブラリを作成していると思います :)

4

3 に答える 3

22

figsize実際、この問題はとを調整することで最もよく解決されると思いますwidthfigsize=(2,7)とを使用した出力は次のwidth=0.3とおりです。

ここに画像の説明を入力

ちなみに、ラッパーを使用すると、このタイプのことははるかに簡単になりますpandas(ソリューションには必要ない もインポートしましseabornたが、私の意見では、プロットがより美しく、よりモダンに見えます):

import pandas as pd        
import seaborn 
seaborn.set() 

df = pd.DataFrame(groups, index=group_labels)
df.plot(kind='bar', legend=False, width=0.8, figsize=(2,5))
plt.show()

ここに画像の説明を入力

于 2015-07-07T01:35:03.243 に答える
19

両方の質問の秘訣は、Matplotlib の棒グラフが各シリーズ (G1、G2) の合計幅が「1.0」で、両側のマージンをカウントすることを理解することです。したがって、余白を設定し、シリーズごとにいくつあるかに応じて各バーの幅を計算するのがおそらく最も簡単です。あなたの場合、シリーズごとに 2 つのバーがあります。

各バーを中央揃えではなく、左揃えにすると仮定すると、この設定により、x 軸上で 0.0 から 1.0、1.0 から 2.0 などの範囲の系列が生成されます。したがって、ラベルを表示する各シリーズの正確な中心は、0.5、1.5 などになります。

多くの無関係な変数があったため、コードをクリーンアップしました。内のコメントを参照してください。

import matplotlib.pyplot as plt
import numpy as np

plt.figure(figsize=(7,7), dpi=300)

groups = [[1.04, 0.96],
          [1.69, 4.02]]
group_labels = ["G1", "G2"]
num_items = len(group_labels)
# This needs to be a numpy range for xdata calculations
# to work.
ind = np.arange(num_items)

# Bar graphs expect a total width of "1.0" per group
# Thus, you should make the sum of the two margins
# plus the sum of the width for each entry equal 1.0.
# One way of doing that is shown below. You can make
# The margins smaller if they're still too big.
margin = 0.05
width = (1.-2.*margin)/num_items

s = plt.subplot(1,1,1)
for num, vals in enumerate(groups):
    print "plotting: ", vals
    # The position of the xdata must be calculated for each of the two data series
    xdata = ind+margin+(num*width)
    # Removing the "align=center" feature will left align graphs, which is what
    # this method of calculating positions assumes
    gene_rects = plt.bar(xdata, vals, width)


# You should no longer need to manually set the plot limit since everything 
# is scaled to one.
# Also the ticks should be much simpler now that each group of bars extends from
# 0.0 to 1.0, 1.0 to 2.0, and so forth and, thus, are centered at 0.5, 1.5, etc.
s.set_xticks(ind+0.5)
s.set_xticklabels(group_labels)

私のコードからの出力。

于 2012-07-22T20:37:29.823 に答える
3

Paul Ivanov がNabbleに投稿した回答を読みました。これにより、この問題をより簡単に解決できる可能性があります。以下のようにインデックスを設定するだけです。これにより、グループ化された列の間隔が広がります。

ind = np.arange(0,12,2)
于 2014-06-22T19:14:31.830 に答える