見出し画像

【Python・Tableau基礎 | PythonでData saber】Order3 HandsOn-Intermediate l 前編(1/2) /w shohei time!

これから、新しいord3のintermediateの部分になります!
本題に入る前に、久しぶりに雑談させてください!
野球好きな男子として、最近は毎朝メジャーリーグを余裕あれば生放送で見ていますが、朝早く起きるその原動力は大谷翔平選手の記録づくりです!
前人未到の成果50-50!いや、あれはアメリカのRedditをみても現地も非常に騒いでいましたね。。
ピッチャーでメジャーで上級の選手が、一刀流になると、どのようなバッターになるのか、その歴史的な瞬間をずっと見ています!40-40達成がそんなに以前のことではない日であったと思いきやマイアミを相手に3ホーマー2盗塁で達成はもう異次元すぎます。。野球やって人として、ホームランって非常にうちにくいものですが、それほどのパワーを持ち俊敏の速さは、、漫画でもリアリティ欠如で、そう描きません。

ではOrd3の課題に入ろうと思います!


Q1(北海道を除き、赤字の1都道府県を除けば劇的に利益が向上する地域の担当マネージャーを教えてください。) #pd.merge(),複数データフレームの統合

既存に使われていたファイルに付け加えて新しいファイルのデータを読み込み、統合する必要が出ています。
そのファイルも同様以前アップロードしたURLからダウンロードすることができます。
▼URL
https://drive.google.com/drive/u/0/folders/1kXSb3fqPTt3VcPjGUSgOmrztlRfvvpMH)

#Indexの確認
#関係者シートの読み込み
df_relation = pd.read_excel("/content/drive/MyDrive/Data saber/ord1/サンプル - スーパーストア.xls", sheet_name="関係者")
pd.unique(df_relation["地域"])

公開したファイルを読み込んで一部のデータを確認してみました。
さて、本作業であるデータフレームの前処理や編集を行います。

#グループ化(地域、都道府県、利益)
region_margin = df_store.groupby(['地域','都道府県'])['利益'].sum().reset_index()
#北海道除去+利益昇順
region_margin = region_margin[region_margin['地域'] != '北海道']
region_margin = region_margin.sort_values(by='利益', ascending=True)
#各地域別に、利益が最も低い都道府県
region_margin2 = region_margin.groupby('地域').first().reset_index()
print(region_margin2)

#region全体売上(地域、利益のみ)
region_sales = df_store.groupby(['地域'])['利益'].sum().reset_index()
region_sales = region_sales.sort_values(by='利益', ascending=False)
print(region_sales)

 #データフレームのマージ region_sales = pd.merge(region_sales, region_margin2, on='地域')
#都道府県列を2番目の列に
region_sales = region_sales[['地域', '都道府県', '利益_x', '利益_y']]
#利益_yの値が、正の値であるものは除去
region_sales = region_sales[region_sales['利益_y'] < 0]
#利益_xと利益_yの値を足した列を追加
region_sales['利益'] = region_sales['利益_x'] + region_sales['利益_y']
#利益の昇順
region_sales = region_sales.sort_values(by='利益', ascending=False)
print(region_sales)

▼結果物

地域データが入っている新しいデータフレームを参照にして、突合させ、赤字の都道府県を特定し、その値を抜いたデータフレームに変更しています。
この数字だと売上の変化量がわかりづらいので、前後をの結果を棒グラフを作成して確認してみます。

# グラフの作成
fig, ax = plt.subplots(figsize=(10, 6))

# 棒の幅
bar_width = 0.35

# X軸の位置
index = np.arange(len(region_sales['地域']))

# 利益_xの棒を作成
bar1 = ax.bar(index, region_sales['利益_x'], bar_width, label='利益_x')

# 利益の棒を作成(利益_xの棒の右隣に配置)
bar2 = ax.bar(index + bar_width, region_sales['利益'], bar_width, label='利益')

# X軸のラベルを設定
ax.set_xlabel('地域')
ax.set_ylabel('利益')
ax.set_title('地域ごとの利益の比較')
ax.set_xticks(index + bar_width / 2)
ax.set_xticklabels(region_sales['地域'])

# 凡例を追加
ax.legend()

# グラフを表示
plt.tight_layout()
plt.show()

▼結果物

可視化してみると、関東地方の方が非常に差が出ていることが確認できますね!
関東地方の担当者を、地域担当者を説明しているデータフレームから確認します。

#関東地方のデータ確認
df_relation[df_relation["地域"] == "関東地方"]

▼結果物

関東地域の担当マネージャーは、中吉さんであることがわかりました!

Q2利益が赤字になっているメーカの特徴

今回は、メーカーの情報をもったcsvから特定のキーワードを基に本来使っているデータに突合するような問題になります。Excelで例えるとVlookup,Xlookupのような機能を使う必要があります。先データの突合にはpandasのmerge()メッソドを使われることを学んだので、それを使いやります。

#メーカーデータCSV読み込み
df_maker = pd.read_csv("/content/drive/MyDrive/Data saber/ord1/サンプル - スーパーストア - メーカー情報.csv")
#製品Idを製品IDに変更する
df_maker = df_maker.rename(columns={'製品 Id': '製品 ID'})
#製品 IDを軸にマージdf_storeから売上と利益のみを持ってくる
df_maker2 = pd.merge(df_store[['製品 ID', '売上', '利益']], df_maker, on='製品 ID')
df_maker2.head()
# split関数を使用してカテゴリのみを抽出
df_maker2['カテゴリ'] = df_maker2['製品 ID'].apply(lambda x: x.split('-')[0])
df_maker2.head()

▼結果物


製品IDが両ファイルとも同じくキーとして使用されていたので、それを持ち突合させたものになります。
データの統合は終えているので、利益をgroupbyで集計させて、赤字を出しているメーカーを把握します。

 #メーカ別に利益を確認する maker_margin = df_maker2.groupby(['メーカー','カテゴリ'])[['利益','売上']].sum().reset_index()
#降順
maker_margin = maker_margin.sort_values(by='利益', ascending=True)
#赤字のみのデータ
maker_margin = maker_margin[maker_margin['利益'] < 0]
print(maker_margin)

▼結果物

最終的に、こちら処理されたデータを特徴把握がしやすいよう可視化したいと思います。データのバラツキからその特徴を把握したい場合には、散布図がよさそうな気がするので、散布図を作成してみます

# 散布図の作成
plt.figure(figsize=(12, 8))
scatter = sns.scatterplot(data=maker_margin, x='売上', y='利益', hue='カテゴリ', s=100, palette='Set1')

# 各点にメーカー名を表示
for i in maker_margin.index:
    scatter.text(maker_margin.loc[i, '売上'], maker_margin.loc[i, '利益'], maker_margin.loc[i, 'メーカー'],
                 horizontalalignment='left', size='medium', color='black', weight='semibold')

# グラフのタイトルと軸ラベルを設定
plt.title('売上と利益の散布図(カテゴリ別色分け)')
plt.xlabel('売上')
plt.ylabel('利益')

# 凡例を表示
plt.legend(title='カテゴリ', bbox_to_anchor=(1.05, 1), loc='upper left')

# グラフを表示
plt.tight_layout()
plt.show()

▼結果物

見てみると、事務用と家電に関しては、家具に比べて売上が低くかつ赤字を出しているといえるでしょうあ。ただ、家電の場合は、その傾向が顕著に表されていることでしょうね。。。なぜ赤字になったのか個人的にはその背景を追求したいところですが、この課題のデータではわかることが困難なので、残念ながらここまでのようです。

Q3.1年前の売上を目標金額としたとき、2016年の売上が目標未達成だったカテゴリを教えてください。#データフレーム上での計算,shift()

問題を紐解くと各年の前年度の売上といった目標の数値を新しく挿入する必要がありそうです。まずは、年度別の売上を集計して、各年度の前年分の売上実績を表示するセールを新たに作成してみます。

#年間の売上作成

# 年の列を追加
df_store['年'] = df_store['オーダー日'].dt.year

# 年とカテゴリ別に売上を集計
category_sales_all_years = df_store.groupby(['年', 'カテゴリ'])['売上'].sum().reset_index()

#目標売上列(前年度のうりあげ)の作成
category_sales_all_years['目標売上'] = category_sales_all_years.groupby('カテゴリ')['売上'].shift(1)
category_sales_all_years.head()

▼結果物


ここでは、shiftメッソドを利用してデータを指定した数(ここでは1年)だけ前にシフトさせています。
因数を指定することで、シフトの方向と数を指定することができます。
比較対象となる、二つの値がそろったので、二つ凡例を持つ棒グラフで

# 年度ごとのユニークな値を取得
years = category_sales_all_years['年'].unique()

# サブプロットを作成
fig, axes = plt.subplots(1, len(years), figsize=(20, 6), sharey=True)

# 各年度ごとの棒グラフを作成
for i, year in enumerate(years):
    year_data = category_sales_all_years[category_sales_all_years['年'] == year]
    index = np.arange(len(year_data['カテゴリ']))
    bar_width = 0.35
    
    # 売上の棒を作成
    bar1 = axes[i].bar(index, year_data['売上'], bar_width, label='売上')
    
    # 目標売上の棒を作成(売上の棒の右隣に配置)
    bar2 = axes[i].bar(index + bar_width, year_data['目標売上'], bar_width, label='目標売上')
    
    # X軸のラベルを設定
    axes[i].set_xlabel('カテゴリ')
    axes[i].set_ylabel('売上')
    axes[i].set_title(f'{year}年の売上と目標売上')
    axes[i].set_xticks(index + bar_width / 2)
    axes[i].set_xticklabels(year_data['カテゴリ'])
    
    # 凡例を追加
    axes[i].legend()

# グラフを表示
plt.tight_layout()
plt.show()

▼結果物

前回紹介したsubplotを連結させるenumerateを使い、各年度の棒グラフを突合させました。
問題になっているのは、2016年度の目標売上に達成していないカテゴリは、事務用品と家電になっています。

Q4. 1行単位で記録されている1商品取引ごとの利益を見たとき、最も大きな利益を出している商品取引のあるサブカテゴリはどれですか? また、そのサブカテゴリの合計利益は 他のサブカテゴリに比べ好調でしょうか?#idxmax

各行で格納されているデータの中で、特定条件に合致するデータを照会する問題になります。
良くエクセルで例えるとindex関数を使い、該当の行のシリアルナンバーからもってくることが実業務から思い浮かびます。
データフレームから特定の行データをもってくるloc[]や、最も高い値を持つ行のインデックス(行番号)を返すidxmax()を組み、抜き取ってみます。

 #利益列の中で 、最も高い値になる行を表示
df_max = df_store.loc[df_store['利益'].idxmax()]
print(df_max["サブカテゴリ"])

▼結果物
電話機

あっという間に、すべての取引があった事項の中で、利益が最も高かったサブカテゴリを特徴することができました!
次の問題は、次回でお会いできればと思います!

この記事が気に入ったらサポートをしてみませんか?