(2025-05-31 初稿 - )
ずいぶんと長いこと放置中だったが、以下のページのスクリプトをpythonで作成してみた。
というのも、上記のページに質問をしてくれた奇特な学生さんがいたので、ボケ防止で作成してみた。
最初に言っておくが、統計処理を専門で行うならば、R等の専門ソフトウェアを使う方が100倍も良い。
頭の体操のつもりで見るならば、以下をどうぞ。
統計ソフトでtukey等の多重検定を行うと、気がきいたものならば、アルファベットの符号を付けてくれるが、符号まで付けてくれないものもあるため、そんなときのためのスクリプト。
ちなみに、アルファベットの符号の付け方を、英語では「Letter Grouping」や「Compact Letter Display (CLD)」というらしく、当然のことながら既にpythonライブラリがあるそうなので、統計処理を専門とする方はそちらを参照のこと。
以下のページも大変参考になった。多謝 m(__)m
試験データの前提
以下のような平均値を持つ試験区を多重検定した結果、5%水準で有意差がある組合せが以下のとおりだったとする。
(サンプルデータ)
| A区 | B区 | C区 | D区 | E区 | F区 |
| 50 | 20 | 60 | 40 | 10 | 30 |
(A, B) , (A, E), (B, C), (C, E), (C, F)
アルファベット符号の付け方の考え方
あくまでも筆者の考えた方法であり、正式なものは上記のサイト等で学んでね。
- 各試験区の平均値の大きい順に並べる
- 有意差のある区を文字列にして、その出現数をカウントし配列に
- 隣の区の*数と比較し、同じならばアルファベットは同じ、違ったらアルファベットを一つ増加する(a → b)配列を作成
- 処理しやすいように列方向の入力用対戦表(マトリックス)を作成
- 処理間に有意差がある場合で、隣の処理区より*数が多い場合はアルファベットを入力、ただし、有意差の部分は*を入力
- 処理間に有意差のない場合は、前のアルファベットと同じものを入力
- 最終の結果を見やすいように、対戦表の行と列を入れ替え、'-'と'*'を削除後アルファベットの符号のうち、ユニークなもののみ表示する
作成したスクリプト
最初に適当に書き上げたが、ChatGPTさんにうかがって大分手直しをしていただいた。
スクリプトの信頼性も増したと思われる。便利な時代になったもんだ。
#!/usr/bin/python3
# 有意差のアルファベットを付ける
# ver 0.01 start 2025-05-30
# ver 0.02 2025-05-31 chatgpt による修正
# global
# 各区の平均値(辞書型) ★ これを変更
exp_avg_dic = { "A":50, "B":20, "C":60, "D":40, "E":10, "F":30 }
# 各処理区の平均値の大きい順(文字列)
sorted_exp_str = ""
# 有意差のある組合せ ★ これを変更
sig_list = [ ["A", "B"], ["A", "E"], ["B", "C"], ["C", "E"], ["C", "F"] ]
sig_str = ""
sig_dic = {}
sig_alph = {}
alph_list = []
# 平均値の大きい順にソート
sorted_dic_avg = sorted(exp_avg_dic.items(), key=lambda x:x[1], reverse=True)
#print(sorted_dic_avg)
for i in range(len(sorted_dic_avg)):
sorted_exp_str += sorted_dic_avg[i][0]
#print(sorted_exp_str)
# sig_listを文字列(str)に
sig_str = ''.join([item for pair in sig_list for item in pair])
#print(sig_str)
# sig_strの文字列をカウント
for i in list(sorted_exp_str):
sig_dic[i] = sig_str.count(i)
#print("sig_dic: ",sig_dic)
num_list = list(sig_dic.values())
#print("num_list:", num_list)
# 隣と比較し差があったらアルファベットを増やす
char_num = 96 # アルファベット初期値 'a'-1
for i in range(len(num_list)):
if i == 0 or num_list[i] < num_list[i - 1] or num_list[i] == 0:
char_num += 1
alph_list.append(char_num)
#print("alph_list: ",alph_list)
sig_str = list(sig_dic.keys())
#print(sig_str)
# 初期結果保存用対戦表
rslt_matrix = [[ '-' for j in range(len(sig_str))] for i in range(len(sig_str))]
# 最終結果保存用対戦表
trans_matrix = [[ '-' for j in range(len(sig_str))] for i in range(len(sig_str))]
zero_flag = 0
for i, key in enumerate(sig_str):
sig_num = sig_dic[key]
if sig_num > 0:
for j in range(i, len(sig_str)):
if len(sig_str) - j > sig_num:
rslt_matrix[i][j] = chr(alph_list[i]) # アルファベット保存
else:
rslt_matrix[i][j] = '*' if zero_flag == 0 else chr(alph_list[i])
else:
zero_flag = 1
for j in range(i, len(sig_str)):
rslt_matrix[i][j] = chr(alph_list[i])
#print(rslt_matrix)
# 初期対戦表を最終版対戦表に変換
for i in range(len(rslt_matrix)):
for j in range(len(rslt_matrix[0])):
#print(i,j)
trans_matrix[i][j] = rslt_matrix[j][i]
# Print Matrix
print(" ", ', '.join(sig_str))
for label, row in zip(sig_str, trans_matrix):
uniq = sorted(set(row) - {'-', '*'})
print(f"{label} , {row} {''.join(uniq)}")
少し長いスクリプトになってしまったが、できるだけコメントを入れたつもり。
不明な点は、ChatGPTやGemini等の生成AIに聞く方が良いかもしれない。
それでは、未来ある研究者達に幸多からんことを。(^^)/