Pythonで最小・最大5%の要素を除外した配列の平均値を求める方法
データ分析では、外れ値(極端に大きい、または小さい値)が平均値に与える影響を避けるため、一定割合の要素を除外してから平均を計算することがよくあります。
本記事では、数値のリスト nums が与えられたとき、最小の5%と最大の5%の要素を削除した残りの値の平均(トリム平均)を求めるPythonプログラムを紹介します。
問題の例
例えば、次のような入力を考えてみましょう。
nums = [2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8]
この場合、最小値の 2 と最大値の 8 が削除対象となり、残りの要素はすべて 4 なので、出力は 4.0 になります。
解決の手順
この問題は、以下のステップで解くことができます。
リスト
numsをソートするn := リストの要素数を取得する
per := (n × 5 ÷ 100) の商(切り捨て)を計算し、削除する要素数を求める
l2 := インデックス per から (要素数 − per) までの部分配列を取り出す
x := l2 内の全要素の平均を計算する
x を返す
Pythonでの実装例
以下のコードで実際の動作を確認してみましょう。
def solve(nums):
nums.sort()
n = len(nums)
per = int(n*5/100)
l2 = nums[per:len(nums)-per]
x = sum(l2)/len(l2)
return x
nums = [2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8]
print(solve(nums))入力
[2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8]
出力
4.0
コードの解説
まず sort() メソッドでリストを昇順に並べ替えます。これにより、小さい方から5%分と大きい方から5%分の要素がリストの両端に集まります。
次に int(n*5/100) で削除する要素数を計算します。今回の例では要素数が20なので、20 × 0.05 = 1 となり、両端から1個ずつ削除されます。
スライス nums[per:len(nums)-per] を使うことで、両端の要素を除外した中央部分だけを取り出せます。最後に sum() と len() を使って平均を計算すれば完成です。
なお、Python 3.8以降では標準ライブラリの statistics.trim_mean() 関数を使うことでも同じ結果が得られるため、状況に応じて活用するとよいでしょう。
-
Pythonでリストの隣接しない要素の最大合計を求めるプログラム
数値のリスト nums が与えられたとき、互いに隣接しない要素だけを選んだ場合の最大合計を返す関数を作ることを考えます。リストには 0 や負の数が含まれている場合もあります。 たとえば、入力が [3, 5, 7, 3, 6] のとき、出力は 16 になります。これは、3・7・6 を選ぶことで要素同士が隣接せず、合計 16 を達成できるためです。 解き方の手順 この問題は動的計画法(DP)の考え方を使うと、O(n) の計算量で効率よく解けます。手順は次のとおりです。 リストの長さが 2 以下の場合は、max(nums) をそのまま返す noTake(現在の要素を選ばない場合の最大合計)を 0
-
Pythonで連続する数値の区間を検出するプログラムの書き方
一意な(重複のない)数値のリスト nums が与えられたとします。このとき、nums 内で連続している数値をひとつの包括的な区間としてまとめ、ソート済みの2次元配列として出力することを目標とします。たとえば、入力が nums = [10, 11, 12, 15, 16, 17, 28, 30] の場合、出力は [[10, 12], [15, 17], [28, 28], [30, 30]] となります。これは、10〜12 と 15〜17 がそれぞれ連続した数値のまとまりである一方、28 と 30 は前後の数値とつながっていないため、単独の区間 [28, 28]、[30, 30] として表現され