【Python初心者でも分かる】データサイエンティスト協会の100本ノックを解説|グループ分け

スポンサーリンク
Python
ゼロ知識の初心者がデータサイエンスを完全無料で学習する方法5選
データサイエンスの知識や技術、またはPythonについて学びたい。でも「大学に行くほど本気度がない」、「スクールに行くほどお金がない」、なんせ「時間がない」という方も多いはずです。というよりほとんどの方がそうだと思います(当然わたし...
初心者に人気のプログラミング言語Pythonは独学可能か?
Pythonは非常に人気のあるプログラミング言語で、まったくの初心者でも独学が可能と言われています。 Pythonはさまざまな目的に使える、汎用性のあるプログラミング言語です。 プログラミングは「独学が難しい」と言われていま...

データサイエンティスト協会の100本ノックがGitHubに公開しているデータとPythonコードを初心者にでも分かるように解説していきます。

今回は21~35本です。内容は主に、「グループ分けする方法」について解説していきます。

Pythonの環境設定は以下の記事を参考にして下さい。

【2021年最新】M1 mac でanacondaをインストールする方法

【2021年最新】WindowsでAnacondaをインストールする方法

  1. グループ分けする方法
    1. P-021: レシート明細データフレーム(df_receipt)に対し、件数をカウントせよ。
    2. P-022: レシート明細データフレーム(df_receipt)の顧客ID(customer_id)に対し、ユニーク件数をカウントせよ。
    3. P-023: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)と売上数量(quantity)を合計せよ。
    4. P-024: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上日(sales_ymd)を求め、10件表示せよ。
    5. P-025: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに最も古い売上日(sales_ymd)を求め、10件表示せよ。
    6. P-026: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上日(sales_ymd)と古い売上日を求め、両者が異なるデータを10件表示せよ。
    7. P-027: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、降順でTOP5を表示せよ。
    8. P-028: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の中央値を計算し、降順でTOP5を表示せよ。
    9. P-029: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに商品コード(product_cd)の最頻値を求めよ。
    10. P-030: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の標本分散を計算し、降順でTOP5を表示せよ。
    11. P-031: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の標本標準偏差を計算し、降順でTOP5を表示せよ。
    12. P-032: レシート明細データフレーム(df_receipt)の売上金額(amount)について、25%刻みでパーセンタイル値を求めよ。
    13. P-033: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、330以上のものを抽出せよ。
    14. P-034: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求めよ。ただし、顧客IDが”Z”から始まるのものは非会員を表すため、除外して計算すること。
    15. P-035: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求め、平均以上に買い物をしている顧客を抽出せよ。ただし、顧客IDが”Z”から始まるのものは非会員を表すため、除外して計算すること。なお、データは10件だけ表示させれば良い。

グループ分けする方法

まずは、以下からダウンロードして下さい。

GitHubからデータをダウンロードする方法

P-021: レシート明細データフレーム(df_receipt)に対し、件数をカウントせよ。

import pandas as pd
df_receipt = pd.read_csv("receipt.csv")

len(df_receipt)

出力:
104681

件数のカウントは、行数のことなので、len() を使えば分かりますね。

P-022: レシート明細データフレーム(df_receipt)の顧客ID(customer_id)に対し、ユニーク件数をカウントせよ。

len(df_receipt["customer_id"].unique())

出力:
8307

unique() は重複していない、唯一のデータという意味です。つまり、重複していないdf_receiot[“customer_id”] の件数を出力してくれます。

P-023: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)と売上数量(quantity)を合計せよ。

df_receipt.groupby('store_cd').agg({'amount':'sum', 'quantity':'sum'}).reset_index()

データフレームに .agg({ }) 内に、”変数”:” ” 内に計算方法を指定すると、変数の計算をしてくれます。つまり、”amount” の ”sum” (合計数)、”quantity” の “sum” (合計数)を出力します。

df_receipt.agg({"amount":"sum","quantity":"sum"})

出力:
amount 33556550
quantity 105862
dtype: int64

変数.sum() でも同様の計算結果になります。

print(df_receipt["amount"].sum())
print(df_receipt["quantity"].sum())

出力:
33556550
105862

これをデータフレームを使って、グループ分けした後に使うと、以下のような結果になります。

df_receipt.groupby('store_cd').agg({'amount':'sum', 'quantity':'sum'})

インデックスとカラムが階層になっているため、reset_index() で形を整えた結果が答えになります。

P-024: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上日(sales_ymd)を求め、10件表示せよ。

df_receipt.groupby("customer_id").sales_ymd.max().reset_index().head(10)

P-025: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに最も古い売上日(sales_ymd)を求め、10件表示せよ。

df_receipt.groupby("customer_id").agg({"sales_ymd":"min"}).reset_index().head(10)

P-024とP-025は計算方法が、max() か min() の違いだけですが、コードの書き方が違います。

変数が1つの計算の場合は、P-024の方が分かりやすく、変数が2つ以上の計算の場合は、P-025の .agg を使ったほうが分かりやすいですね。

次の、P-026では変数が2つ以上の計算の場合です。

P-026: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上日(sales_ymd)と古い売上日を求め、両者が異なるデータを10件表示せよ。

df_26 = df_receipt.groupby("customer_id").agg({"sales_ymd":["max","min"]}).reset_index()
df_26.columns = ["_".join(i) for i in df_26.columns]   # カラム名を指定
df_26.query("sales_ymd_max != sales_ymd_min").head(10) # データ抽出の条件を指定


出力:

コードの意味をそれぞれ確認していきましょう。

df_26 = df_receipt.groupby("customer_id").agg({"sales_ymd":["max","min"]}).reset_index()
df_26

カラムが階層になっているので、カラムを整えたいですね。まずは、カラムを確認してみましょう。

df_26.columns

出力:
MultiIndex([(‘customer_id’, ”),
( ‘sales_ymd’, ‘max’),
( ‘sales_ymd’, ‘min’)],

カラムの階層をくっつけて、1つのカラムにします。

["_".join(i) for i in df_26.columns]

出力:
[‘customer_id_’, ‘sales_ymd_max’, ‘sales_ymd_min’]

カラム名がくっつき、1つになりました。

なので、以下のような答えの形の整ったことになります。

P-027: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、降順でTOP5を表示せよ。

並び替えは、sort_values() を使います。

df_receipt.groupby("store_cd").agg({"amount":"mean"}).reset_index().\
    sort_values("amount",ascending=False).head(5)

P-028: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の中央値を計算し、降順でTOP5を表示せよ。

df_receipt.groupby("store_cd").agg({"amount":"median"}).reset_index().\
    sort_values("amount",ascending=False).head(5)

P-029: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに商品コード(product_cd)の最頻値を求めよ。

df_receipt.groupby('store_cd').product_cd.apply(lambda x: x.mode()).reset_index()

lambda は計算式を指定して実行します。上のコードでは、変数である “product_cd” をxとして、x.mode() を実行します。つまり、product_cd.mode() と同じ意味です。

P-030: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の標本分散を計算し、降順でTOP5を表示せよ。

df_receipt.groupby("store_cd").amount.var(ddof=0).reset_index().\
    sort_values("amount",ascending=False).head(5)

P-031: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の標本標準偏差を計算し、降順でTOP5を表示せよ。

df_receipt.groupby("store_cd").amount.std(ddof=0).reset_index().\
    sort_values("amount",ascending=False).head(5)

P-032: レシート明細データフレーム(df_receipt)の売上金額(amount)について、25%刻みでパーセンタイル値を求めよ。

import numpy as np
# コード例1
np.percentile(df_receipt['amount'], q=[25, 50, 75,100])

出力:
array([ 102., 170., 288., 10925.])

np.percentile() は、パーセンタイルの値を出力します。パーセンタイルの値を q=[ ] で指定します。

# コード例2
df_receipt.amount.quantile(q=np.arange(5)/4)

出力:
0.00  10.0
0.25  102.0
0.50  170.0
0.75  288.0
1.00  10925.0
Name: amount, dtype: float64

quantile() でも同様にパーセンタイルが出力されます。

df_receipt["amount"].describe()[3:,]

出力:
min  10.0
25%  102.0
50%  170.0
75%  288.0
max  10925.0
Name: amount, dtype: float64

describe() を使ったほうが、多くの統計量が出力されます。ここでは、パーセンタイルだけなので、[3:,] を指定しています。

P-033: レシート明細データフレーム(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、330以上のものを抽出せよ。

df_receipt.groupby("store_cd").amount.mean().reset_index().query("amount>=330")

グループ分け、平均値の計算、条件して抽出を同じコードで表しています。

P-034: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求めよ。ただし、顧客IDが”Z”から始まるのものは非会員を表すため、除外して計算すること。

df_receipt[~df_receipt["customer_id"].str.startswith("Z")].\
    groupby("customer_id").amount.sum().mean()

出力:
2547.742234529256

~は、not と同じで、「指定した条件以外」という意味です。

df_receipt.query("not customer_id.str.startswith('Z')",engine="python").\
    groupby("customer_id").amount.sum().mean()

出力:
2547.742234529256

P-035: レシート明細データフレーム(df_receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求め、平均以上に買い物をしている顧客を抽出せよ。ただし、顧客IDが”Z”から始まるのものは非会員を表すため、除外して計算すること。なお、データは10件だけ表示させれば良い。

mean = df_receipt.query("not customer_id.str.startswith('Z')",engine="python").\
    groupby("customer_id").amount.sum().mean()
df_35 = df_receipt.groupby("customer_id").amount.sum().reset_index()
df_35[df_35["amount"]>=mean].head(10)


少しややこしくなってきましたが、1つ1つは難しくありません。

何をしているか分からなくなったら、コードを1つ1つ実行していきながら確認してみると、理解できると思います。

【Python初心者でも分かる】データサイエンティスト協会の100本ノックを解説|データの抽出
データサイエンティスト協会の100本ノックがGitHubに公開しているデータとPythonコードを初心者にでも分かるように解説していきます。 今回は1~9本です。内容は主に、「データの抽出方法」について解説していきます...
【Python初心者でも分かる】データサイエンティスト協会の100本ノックを解説|変数の一部を使ってデータを抽出する
データサイエンティスト協会の100本ノックがGitHubに公開しているデータとPythonコードを初心者にでも分かるように解説していきます。 今回は10~16本です。内容は主に、「変数の一部を使ってデータを抽出する方法...
【Python初心者でも分かる】データサイエンティスト協会の100本ノックを解説|ソート(順序で整列)
データサイエンティスト協会の100本ノックがGitHubに公開しているデータとPythonコードを初心者にでも分かるように解説していきます。 今回は17~20本です。内容は主に、「ソート(順序で整列)の方法」について解...



コメント

タイトルとURLをコピーしました