質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

11072閲覧

seabornを使ったグラフで、任意のy軸上の位置に横線を引く

yu_2_8_2

総合スコア34

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2019/06/24 07:17

編集2019/06/24 14:45

seabornのbarplotを使い、以下のようなグラフを作成したのですが、
イメージ説明

このグラフ中に、任意のpriceの位置に横棒を引きたいのですが、調べてもよくわからなかったので質問致します。

イメージ説明
イメージとしては上のような感じにしたいです。

どなたかご教授の程、よろしくお願いします。


以下追記

今回動かしているコードは以下になります。(ここで使っている配列は実際使っているものを簡略化したもの)

Python3

1from io import StringIO 2 3import pandas as pd 4import matplotlib.pyplot as plt 5import seaborn as sns 6 7sns.set(style="whitegrid") 8 9# データフレーム作成 10num_samples = 100 11data = pd.DataFrame( 12 { 13 "price": np.arange(855000, 855000 + num_samples), 14 "sell": np.random.uniform(0, 10, num_samples), 15 "buy": np.random.uniform(0, 10, num_samples), 16 } 17) 18 19# 描画する。 20fig, ax = plt.subplots(figsize=(7, 5)) 21 22# 棒グラフのデフォルトは右方向→ 23# sell の値は符号を反転させることで左方向←に棒グラフが作成されるようにする。 24copied = data.copy() # 元のデータを変更しないようにコピーしておく。 25copied["sell"] *= -1 26 27colors = ["#60D394", "#FFD97D"] # 色 28names = ["sell", "buy"] # 列名 29 30for name, color in zip(names, colors): 31 sns.barplot( 32 x=name, 33 y="price", 34 data=copied, 35 color=color, 36 label=name, 37 orient="h", 38 order=copied["price"].iloc[::-1], 39 ax=ax, 40 ) 41 42ax.set_xlabel("") # x 軸のラベル 43ax.set_ylabel("Price", fontsize=12) # y 軸のラベル 44# x 軸の範囲を左右対称になるように調整する。 45max_val = data[["sell", "buy"]].values.max() * 1.1 46ax.set_xlim(-max_val, max_val) 47 48# y 軸の目盛りの間隔を10個おきに調整する。 49yticks = ax.get_yticks() 50yticklabels = ax.get_yticklabels() 51ax.set_yticks(yticks[::10]) 52ax.set_yticklabels(yticklabels[::10]) 53 54ax.axhline(2000, c="r") # 新しく追加 55 56ax.legend() # 凡例追加 57 58plt.show()

これにより出力されるグラフが以下のようになり、(使っているデータが違いのでイメージ図)
イメージ説明
引きたい箇所からずれたところに線が引かれてしまっています。
(ax.axhline(1100000, c="r")とすると大きくずれたところに横線が引かれグラフが崩れる。
ax.axhline(2000, c="r")とすると上のグラフのように描画している範囲に横線が引かれる。)
axhlineで指定しているyとbarplotのyがずれているようなのですが、どのように解決したらよいでしょうか?
ご教授頂けると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

横線は hayataka2049 さんが記述されている通り axhline()で書けます。

で、横線を引くポジションが合わないのは、実際のY軸の座標とラベル名の数値が別に設定されており合致してしていないからですね。
(seabornのbarplotの仕様かな?)

ラベルが書かれている実際の座標は 質問内のコードでも使用されている、

Python

1ax.get_yticks()

で取得でき、同じくラベル名も質問内のコードでも使用されている、

Python

1ax.get_yticklabels()

にて取得できますので、これらのデータを使用して、ラベル名に対応する実際のy座標を取得することにより意図した場所線を引くことが
できるかと思います。

以下は質問にあるサンプルコードを修正したものです。
とりあえず、55050 の箇所に横線を引いております。

Python

1import pandas as pd 2import numpy as np 3import matplotlib.pyplot as plt 4import seaborn as sns 5 6sns.set(style="whitegrid") 7 8# データフレーム作成 9num_samples = 100 10data = pd.DataFrame( 11 { 12 "price": np.arange(855000, 855000 + num_samples), 13 "sell": np.random.uniform(0, 10, num_samples), 14 "buy": np.random.uniform(0, 10, num_samples), 15 } 16) 17 18# 描画する。 19fig, ax = plt.subplots(figsize=(7, 5)) 20 21# 棒グラフのデフォルトは右方向→ 22# sell の値は符号を反転させることで左方向←に棒グラフが作成されるようにする。 23copied = data.copy() # 元のデータを変更しないようにコピーしておく。 24copied["sell"] *= -1 25 26colors = ["#60D394", "#FFD97D"] # 色 27names = ["sell", "buy"] # 列名 28 29for name, color in zip(names, colors): 30 sns.barplot( 31 x=name, 32 y="price", 33 data=copied, 34 color=color, 35 label=name, 36 orient="h", 37 order=copied["price"].iloc[::-1], 38 ax=ax, 39 ) 40 41ax.set_xlabel("") # x 軸のラベル 42ax.set_ylabel("Price", fontsize=12) # y 軸のラベル 43# x 軸の範囲を左右対称になるように調整する。 44max_val = data[["sell", "buy"]].values.max() * 1.1 45ax.set_xlim(-max_val, max_val) 46 47# y 軸の目盛りの間隔を10個おきに調整する。 48yticks = ax.get_yticks() 49yticklabels = ax.get_yticklabels() 50 51# ラベル名に対応した、Y座標を取得するためのdict 52# 10個置きに間引かれる前のデータを使い、ラベルはIntに変換しておく 53conv_tbl = {int(label.get_text()): pos for label, pos in zip(yticklabels, yticks)} 54 55ax.set_yticks(yticks[::10]) 56ax.set_yticklabels(yticklabels[::10]) 57 58# 追加 (変換テーブルにてY座標に変換) 59ax.axhline(conv_tbl[855050], c="r") 60 61ax.legend() # 凡例追加 62 63plt.show()

投稿2019/06/25 03:05

編集2019/06/25 03:06
magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2019/06/25 03:17 編集

厄介な仕様ですね。まあget_yticksで取れるならいいか(get系のあまり使わないので把握していませんでした)
magichan

2019/06/25 04:25

調べておりませんので想像なのですが、Y軸が数値ではなく文字列のリストとして扱われているのではないですかね。
yu_2_8_2

2019/06/25 05:51

ありがとうございます! さっそくやってみます
guest

0

使ったコードはこちらのものでしょうか。

Matplotlib - Python3のmatplotlibを使ったヒストグラムの作図|teratail

axに対して線を引くメソッドを呼べば良いです。

matplotlib.pyplot.axhline — Matplotlib 3.1.0 documentation

これを好きな位置(axを作ってからplt.show()を呼ぶまでの間)に入れてください。

python

1ax.axhline(4, -40, 40, c="r")

投稿2019/06/24 11:32

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yu_2_8_2

2019/06/24 14:44

回答ありがとうございます。いろいろ試したのですが、以下のような問題が発生してしまいました。 (質問文中にも追記) ax.axhline(1100000, c="r")とすると大きくずれたところに横線が引かれグラフが崩れる。 ax.axhline(2000, c="r")とすると上のグラフのように描画している範囲に横線が引かれる。 axhlineで指定しているyとbarplotのyがずれているようなのですが、どのように解決したらよいでしょうか? ご教授頂けると幸いです。
hayataka2049

2019/06/24 14:54 編集

ラベルに表示されている値と実際に内部で持っている座標が違うのでしょう。最初から合致するようにプロットするか、それが難しければ適当に換算する必要があります。取り急ぎこれだけ。追ってまたなにかコメントします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問