0
1

More than 1 year has passed since last update.

[Python]Matplotlibで対象者数と平均を1つのグラフに表示(x軸が連続値の場合)

Last updated at Posted at 2021-10-17

学術系のデータ分析をPythonで行いました。

データを視覚化するのに便利な関数を作成したので共有します。

投稿内容は個人の見解であり、所属する組織の公式見解ではありません。

記事の対象者

今回の記事は、次の悩みを持つ人を対象に執筆しています。

  • データ分析をPythonで実施したい
  • 連続変数と被説明変数の関係性を可視化したい

この記事を読むうえで、必要な知識

  • Pythonによるデータ分析の基礎知識を習得している
  • Matplotlibの基礎知識を習得している

ざっくりとした要件定義

作成したもの

create_graph関数
(関数名は、改善の余地があるかもしれません。)

Input

  1. x軸の変数(連続変数)の列名
  2. y軸の変数の列名
  3. 対象となるDataFrame
  4. x値を四捨五入で切り捨てする桁数 etc

Output

一定範囲内のx値ごとの、対象者数とy値の平均をグラフとして出力

plt_graph

コード

データセットは、Airbnbが公開しているデータセットの中から、2021年9月29日時点での'Detailed Listings data for Tokyo'を使用しました。
このデータセットの中には、Airbnbに登録されている物件情報が格納されています。
なお今回の分析では、この物件情報の中の'Price'(価格)と'Reviews per month'(月ごとのレビュー値)の関係性を見ていきます。

2021年10月18日時点では、Airbnbのデータセットはこちらから誰でもダウンロードできます。

ライブラリのインポート

import pandas as pd
import matplotlib.pyplot as plt

from matplotlib import font_manager
import japanize_matplotlib

データ前処理のコード

data_dir = 'dataset/'
df=pd.read_csv(data_dir + 'listings.csv')

df_f = df[['price','reviews_per_month']]

def convert_price(df,col):
    '''
    airbnbの'price'列をintに変換するための関数
    '''
    df_temp = df[[col]].copy()
    # 1文字目の'$'と最後の3文字の'.00'を削除
    df_temp['temp'] = df[col].str[1:-3]
    # ','を削除し、intへ変換
    df_temp['temp'] = df_temp['temp'].str.replace(',', '')
    df_temp['temp'] = df_temp['temp'].astype('int')
    return df_temp['temp']

df_f.loc[:,'price'] = convert_price(df_f,'price')

#reviewがついていない物件を削除
df_f = df_f[df_f['reviews_per_month'].notnull()]

前処理後のoutputは次の通りです。

#code
df_f.head()

#output
_   price   reviews_per_month
0   11000   1.50
1   7816    2.33
2   30000   0.78
3   14036   2.73
4   3000    0.98


#code
df_f.shape

#output
(8582, 2)

グラフを表示するコード

def col_rounded(df,col,digit):
    '''
    連続値の列を四捨五入する。
    四捨五入は、1の位より大きい値で行う。
    ex. 百の位で切り捨てる場合、digit=3
    '''
    #切り捨て除算により四捨五入の切り捨てを実施
    df['temp'] = df[col]//(10**digit)
    df['temp'] = df['temp']*(10**digit)
    return df['temp']

def df_grouped(x_col, y_col, col_min=0, col_max=float('inf'), df=df):
    '''
    y軸の平均のdf_mと、対象者カウントのdf_cを作成する。
    '''
    df_f=df[(df[x_col]>=col_min)&(df[x_col]<=col_max)]

    df_m=df_f.groupby(x_col)[[y_col]].mean()
    df_c=df_f.groupby(x_col)[[y_col]].count()
    return df_m, df_c

def show_graph(x_col, y_col, df_m, df_c, g_width, col_min=0, col_max=float('inf'), x_label='x'):
    '''
    対象者数の棒グラフとyの平均の折れ線グラフを表示する。
    '''
    # プロットエリアを作成
    fig, ax1 = plt.subplots(1,1,figsize=(10,8))
    ax2 = ax1.twinx()

    #対象者数の棒グラフを作成
    ax1.bar(df_m.index,df_c[y_col],width=g_width, color='lightblue',label='対象者数')
    #対象者数の一定範囲内での平均を作成
    ax2.plot(df_m[y_col],linestyle='solid',color='k',marker='',label='平均')

    #legendを作成
    handler1, label1 = ax1.get_legend_handles_labels()
    handler2, label2 = ax2.get_legend_handles_labels()
    ax1.legend(handler1+handler2,label1+label2,loc=1)

    #ラベルを作成
    ax1.set_xlabel(x_label)
    ax1.set_ylabel('対象者数')
    ax1.grid(True)
    ax2.set_ylabel('平均')

    plt.title('対象者数と平均')

    #グラフを表示
    fig.show()

def create_graph(x_col, y_col, df, digit, col_min=0, col_max=float('inf'), x_label='x'):
    '''
    関数を組み合わせる。
    dfを入力すると、グラフが表示される。
    '''
    df_temp = df.copy()

    x_col_r = x_col + 'rounded'
    df_temp[x_col_r] = col_rounded(df_temp,x_col,digit)

    df_m, df_c=df_grouped(x_col_r, y_col, col_min, col_max,df_temp)

    g_width = 10**digit - 10**(digit-1)*2
    show_graph(x_col_r, y_col, df_m, df_c, g_width, col_min=col_min, col_max=col_max, x_label=x_label)

create_graph('price', 'reviews_per_month', df_f, 3, col_min=0, col_max=20000, x_label='価格')

このコードを実施すると、次のグラフが表示されます。

plt_graph

まとめ

今回は、x軸が連続値である場合の視覚化方法を提案しました。
学術系のデータ分析では細かい修正が多いので、このような関数を作っておくと便利です。

興味があれば試してみてください!

参考文献

[Python]matplotlibで左右に2つの軸があるグラフを書く方法

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1