🤔

【解説記事】平均値を求めるアルゴリズム

に公開
2

目的

この記事では、統計の 平均値 を求めるアルゴリズムを解説します。🤔

状況

今年は、アルゴリズム統計数理 の技能向上を、抱負に掲げています。
Udemy 岩松 洋氏の 【紙とえんぴつでプログラミング】<初心者向け>プログラムを"作る"ための詳細設計コース を受講し、身近な題材を使って、アルゴリズムを分析する練習をしようと思い立ちました。💪 第一回は、架空の高校のとあるクラスに於ける数学のテストの平均点を求める というお題で、解説を進めます。😤

複雑さ(課題)

多くの統計量は、ギリシャ文字を使って、表されます。計算手順を理解しないと、読み解くことができません。そこで、計算手順を一手ずつ読み解けば、アルゴリズムの技能向上だけでなく、統計の理解も深まる と考え、今回の取り組みを始めました。😁

平均値を求める数式

平均値を求める数式は、\bar{x} = \frac{1}{n} \sum_{i=1}^{n} x_{i} で表されます。

数式の記号の意味

記号 読み方 意味
\bar{x} エックス・バー 標本平均を表します。
n エヌ 標本の大きさ(数)を表します。
\sum_{i=1}^{n} シグマ 合計を求める際に使われる記号です。
x_i エックス・アイ 個々のデータ、i番目のデータを表します。

問い

お題は 平均値を求めるアルゴリズムは、どうなっているか? です。🤔

第一回は、架空の高校のとあるクラスに於ける、数学のテストの平均点を求めるというお題で解説を進めます。

答え

この記事では、以下の手順で、アルゴリズムを解説します。

  1. アルゴリズムの箇条書き
  2. フローチャート化
  3. 詳細設計
  4. プログラム化

結果

1. アルゴリズムの箇条書き

某クラスの数学のテストの平均点を求める手順は、以下の通りです。

  1. 数学のテストを受けた生徒数を数える。
  2. 受験した生徒の点数を足し上げる。
  3. 2.で足し上げた点数を、1.で数えた生徒数で割る。

2. フローチャート化

1.で書き出した箇条書きを、フローチャート化します。
箇条書きをなぞった、一本道のシンプルなアルゴリズム であることが分かります。😎

3. 詳細設計

フローチャート

続いて2. で描いたフローチャートを、プログラミング用に詳細化します。2.のフローチャートと比べると、条件分岐が2回追加 されています。🤔

データ構造

データ データ型 変数名
生徒数 数学のテストを受験した生徒 整数型 students
全生徒数 数学のテストを受験した全生徒 整数型 total_students
テストの点数 生徒毎の数学のテストの点数 整数型 maths_score
テストの合計点 全生徒の数学のテストの合計点 整数型 total_maths_score
テストの平均点 全生徒の数学のテストの平均点 浮動小数点型 average_score

4. プログラム化

詳細設計に基づくプログラミング

最後に、詳細設計を基に、プログラミングをします。言語はPython を使い、Paiza のオンライン・エディタで、動作検証を行いました。🤔

def calculate_maths_average(data_list):
    """
    生徒データのリストから平均点を求める関数
    """
    # 変数を初期化する
    total_students = 0
    total_maths_score = 0
    
    # リスト内の生徒数を数える
    for students in data_list:
        total_students += 1
        total_maths_score += students["maths_score"]
    
    # 平均値を求める (データが空でないことを確認する)
    if total_students == 0:
        return 0, 0, 0  # データがない場合はすべて0を返す
        
    average_score = total_maths_score / total_students
    
    # 結果を返す
    return total_students, total_maths_score, average_score

# --- 関数の実行例 ---
# 1. データの用意
class_data = [
    {"student_id": "001", "maths_score": 50},
    {"student_id": "002", "maths_score": 70},
    {"student_id": "008", "maths_score": 40}
]

# 2. 関数を呼び出し、結果を受け取る
count, total, average = calculate_maths_average(class_data)

# 3. 結果を表示する
print(f"全生徒数: {count}名 / 合計点数: {total}点 / 平均点: {average}点")

リファクタリング

詳細設計に基づくソースコードを研ぎ澄ましたソースコードは、以下の通りです。

  1. 組み込み関数の利用
  2. ジェネレータ式の利用
def calculate_maths_average_final(data_list):
    # 1. 必要なデータ(点数)だけを抽出 (ジェネレータ式でメモリ効率化)
    scores = [student["maths_score"] for student in data_list]
    
    # 2. ガード節 (データが空の場合の早期リターン)
    if not scores:
        return 0, 0, 0.0
    
    # 3. 組み込み関数をフル活用
    total_students = len(scores)
    total_maths_score = sum(scores)
    average_score = total_maths_score / total_students
    
    return total_students, total_maths_score, average_score

# --- 関数の実行例 ---
# 1. データの用意
class_data = [
    {"student_id": "001", "maths_score": 50},
    {"student_id": "002", "maths_score": 70},
    {"student_id": "008", "maths_score": 40}
]

# 2. 関数を呼び出し、結果を受け取る
count, total, average = calculate_maths_average(class_data)

# 3. 結果を表示する
print(f"全生徒数: {count}名 / 合計点数: {total}点 / 平均点: {average}点")

示唆

  • アルゴリズムの箇条書きフローチャート化詳細設計プログラミング とステップを踏み、プログラムを書くことができました。☺️
  • 実際にやってみて、詳細設計が鬼門 だと感じました。プログラミング言語の構文と密接な関係にあり、if 文による条件分岐等、多少なりとも構文に関する知識が必要になるためです。
  • 計算手順の多い統計量は、フローチャート化すると、手順が整理され、理解が深まる と感じました。🤓

結論

  • 算術平均の他に、幾何平均調和平均 もあります。後日、同じ手順で分析してみます。🤔
  • 最小値中央値最大値最頻値 といった、よく使う統計量も取り上げたいと考えています。
  • 又、将来的には マージソートバブルソート 等、代表的なソート・アルゴリズム にも挑戦してみたいです。

出所

Discussion

shiracamusshiracamus

typoがあって、実行するとエラーになります。
アルゴリズムを学ぶのはいいことですが、便利な組込み関数の使い方を覚えるのもいいですよ。

def calculate_maths_average(students: list) -> tuple[int, int, int]:
    """
    生徒データのリストから平均点を求める関数
    """

    # データがあることを確認する
    if not students:
        return 0, 0, 0  # データがない場合はすべて0を返す

    # 全生徒数を数える
    total_students = len(students)

    # 合計点数を求める
    total_maths_score = sum(student["maths_score"] for student in students)

    # 平均点数を求める
    average_score = total_maths_score / total_students

    # 結果を返す
    return total_students, total_maths_score, average_score

# --- 関数の実行例 ---
# 1. データの用意
class_data = [
    {"student_id": "001", "maths_score": 50},
    {"student_id": "002", "maths_score": 70},
    {"student_id": "008", "maths_score": 40}
]

# 2. 関数を呼び出し、結果を受け取る
count, total, average = calculate_maths_average(class_data)

# 3. 結果を表示する
print(f"全生徒数: {count}名 / 合計点数: {total}点 / 平均点: {average:.1f}点")
shokamura1shokamura1

こんばんは。

コメント頂きまして、ありがとうございます。
一部、関数名が不揃いだった箇所を修正しました。

そうですね。
組み込み関数も交えつつ、当面はアルゴリズムの練習を続けたいと考えています。☺️