【C#】LINQのAverageメソッド:配列やリストの平均値を算出する方法と空リストの注意点

目次

データの平均値を計算する

統計データの解析や、ゲームのスコア計算、システムログのパフォーマンス分析など、データの「平均値」を求める処理はプログラミングにおいて頻出します。

C#のLINQ(Language Integrated Query)が提供するAverageメソッドを使用すると、forループで合計と個数を管理することなく、簡潔に平均値を算出できます。

この記事では、単純な数値配列の平均から、オブジェクトリスト内の特定プロパティの平均、さらにはリストが空の場合の例外処理について解説します。


1. 単純な数値リストの平均

intlongdoubledecimalなどの数値型のコレクションに対して、引数なしでAverage()メソッドを呼び出すと、その全要素の算術平均が返されます。

戻り値の型は、元の型に応じてdoubleまたはdecimalになります(intの平均はdoubleになります)。

コード例:ダウンロード速度の平均

using System;
using System.Linq; // LINQを使用するために必須

public class AverageBasicExample
{
    public static void Main()
    {
        // 過去5回のダウンロード速度 (Mbps)
        int[] downloadSpeeds = { 120, 95, 110, 105, 130 };

        // 平均値を計算 (int配列だが、戻り値は double になる)
        double averageSpeed = downloadSpeeds.Average();

        Console.WriteLine($"速度ログ: {string.Join(", ", downloadSpeeds)}");
        Console.WriteLine($"平均速度: {averageSpeed} Mbps");
    }
}

出力結果:

速度ログ: 120, 95, 110, 105, 130
平均速度: 112 Mbps

2. オブジェクトリストの特定プロパティの平均

オブジェクトのリストを扱う場合、引数にラムダ式 x => x.Property を指定することで、「どの値の平均を算出するか」を定義できます。

コード例:従業員の平均勤続年数

using System;
using System.Collections.Generic;
using System.Linq;

// 従業員クラス
public class Employee
{
    public string Name { get; set; }
    public int YearsOfService { get; set; } // 勤続年数
}

public class AveragePropertyExample
{
    public static void Main()
    {
        var employees = new List<Employee>
        {
            new Employee { Name = "佐藤", YearsOfService = 5 },
            new Employee { Name = "鈴木", YearsOfService = 12 },
            new Employee { Name = "高橋", YearsOfService = 3 },
            new Employee { Name = "田中", YearsOfService = 8 }
        };

        // YearsOfService (勤続年数) の平均を算出
        double averageYears = employees.Average(e => e.YearsOfService);

        Console.WriteLine($"従業員数: {employees.Count}名");
        Console.WriteLine($"平均勤続年数: {averageYears} 年");
    }
}

出力結果:

従業員数: 4名
平均勤続年数: 7 年

3. 計算式を含めた平均

Averageメソッドのラムダ式内では、単純なプロパティアクセスだけでなく、計算を行うことも可能です。

例えば、各データの「成功数」と「試行数」から「成功率」を計算し、その「平均成功率」を求めることができます。

コード例:メール開封率の平均

using System;
using System.Collections.Generic;
using System.Linq;

public class EmailCampaign
{
    public string Subject { get; set; }
    public int SentCount { get; set; }   // 送信数
    public int OpenedCount { get; set; } // 開封数
}

public class AverageCalculationExample
{
    public static void Main()
    {
        var campaigns = new List<EmailCampaign>
        {
            new EmailCampaign { Subject = "Summer Sale", SentCount = 1000, OpenedCount = 250 },
            new EmailCampaign { Subject = "Winter Sale", SentCount = 2000, OpenedCount = 400 },
            new EmailCampaign { Subject = "New Arrival", SentCount = 1500, OpenedCount = 450 }
        };

        // 各キャンペーンごとの開封率 (Opened / Sent) を計算し、その平均を求める
        // 注意: 整数同士の割り算にならないよう (double) キャストが必要
        double averageOpenRate = campaigns.Average(c => (double)c.OpenedCount / c.SentCount);

        // パーセンテージ表示 (P1)
        Console.WriteLine($"平均開封率: {averageOpenRate:P1}");
    }
}

出力結果:

平均開封率: 25.0%

(計算: 25% + 20% + 30% = 75% / 3 = 25%)


重要な注意点:空のリストと例外

Averageメソッドを使用する際、最も注意すべき点は「要素数が0(空)の場合」の挙動です。

  • 数値型(intなど)のコレクションが空の場合: InvalidOperationException(シーケンスに要素が含まれていません)が発生します。0で割ることになるためです。
  • null許容型(int?など)のコレクションが空、または全てnullの場合: 例外は発生せず、null が返されます。

安全な平均値の算出方法

リストが空になる可能性がある場合は、以下のいずれかの対策が必要です。

  1. 事前に .Any() で要素の存在を確認する。
  2. DefaultIfEmpty() を使用する。
  3. null許容型にキャストして null を受け取れるようにする。
var emptyList = new List<int>();

// 対策例: null許容型にキャストしてから Average を呼ぶ
// リストが空なら null が返り、?? 演算子で 0.0 に変換される
double safeAverage = emptyList.Cast<int?>().Average() ?? 0.0;

Console.WriteLine($"安全な平均値: {safeAverage}");

まとめ

Averageメソッドは、データの傾向を把握するための基本的な集計機能です。

  • collection.Average(): 単純な数値リストの平均。
  • collection.Average(x => x.Prop): オブジェクトリストの特定項目の平均。
  • 注意点: 空のリストに対して実行すると例外が発生するため、データが0件になる可能性がある場合は対策が必要です。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次