LuaTeXで分散の計算の途中の表を自動生成する(データと平均値が整数のみのケース)

データの分析で分散を手計算させることがある。

私が問題を作成するときも、分散計算は単純な値で計算させる。今時、コンピュータで計算させるのが普通であるからである。手で計算するのは、理解を深めるためである。その目的であれば、複雑な数値の計算は一切やらせなくて良い。

複雑な計算でない以上、解答を作成をするときに計算でミスをすることは考えにくい。しかし、途中式に書くあれこれが間違いやすい。

一番ありえるミスが、問題文のデータと途中式のデータが一致しないことである。試験問題を演習プリントに貼り付けて(あるいは逆)、試験問題と演習プリントをいったりきたりするうちに、何箇所かデータがずれる、というのがよくある話である。そこで、データの配列を与えたら途中式の表を作るスクリプトを書いてみた。

以下のようなものを作ることを考える。

f:id:baruku07:20180225201402p:plain

Luaの部分。

function data_to_problem(data) --問題文に表示するデータの整形
 for i=1, #data -1 do
  tex.print(data[i] .. ",")
 end
  tex.print(data[#data])
end

function data_to_mean(data) --平均値を計算する関数
 sum = 0
 for i=1, #data do 
   sum = sum + data[i]
 end
  return sum/#data
end

function repeat_str(rep_str,n) --文字列を繰り返す
  str =""
  for i=1, n do
    str = str .. rep_str
  end
  return str
end

function add_ary_str(ary, str_pre, str_m, str_end,math_chr) --配列の前後に色々とくっつけるための関数
  str = str_pre
  for i=1, #ary -1 do
    str = str ..math_chr .. ary[i] .. math_chr .. str_m
  end
  str = str .. math_chr .. ary[#ary]  .. math_chr .. str_end   
  return(str)
end

function data_to_vartable(data)
 str =""
 -- 表の1行目・2行目の部分
 str = str .. "\\begin{tabular}{|c|" .. repeat_str("c",#data) .. "|c|}" .. "  \\hline \n"  --\nの前にhlineでないとエラー
 str = str .. add_ary_str(data,"x &","& ","&合計","$") .. "\\\\" .. "\\hline "  .."\n"  --データを並べた列
 -- 表の3・4行目に必要となる値と配列を計算
 x_minus_m ={}
 x_minus_m_square = {}
 sum_square = 0
 for i =1, #data do
  x_minus_m[i] = data[i] - data_to_mean(data)
  x_minus_m_square[i] = (x_minus_m[i])^2
  sum_square = sum_square + x_minus_m_square[i]
  end
  -- 表の3行目・(x-\bar{x})
 str = str .. add_ary_str(x_minus_m, "$x-\\bar{x}$ &", "&", "&","$") .. "\\\\ \\hline \n"
  -- 表の4行目・(x-\bar{x})^2
 str = str .. add_ary_str(x_minus_m_square, "$(x-\\bar{x})^2$ &", "&","&" .. sum_square,"$") .. "\\\\  \\hline "
 --hlineの後で改行を入れると一行追加になってしまうので入れない。
 str = str .. "\\end{tabular}"
 tex.print(str)
end

TeXの部分

\documentclass{ltjsarticle}
\usepackage{luacode}
\usepackage{amsmath}
\usepackage{tcolorbox}
\begin{luacode*}
--ここに上のluaのコードが入る
\end{luacode*}


\begin{document}
\def\xa{{1,2,3,4,5,6,7}}
次のデータについて、分散および標準偏差の値を求めよ。
\[
\luaexec{data_to_problem(\xa)}
\]
 \begin{tcolorbox}[colframe=white,colback=white,visible] %
\begin{center}
\luaexec{data_to_vartable(\xa)}
\end{center}
\end{tcolorbox}

問題部分はdata_to_problemで作っている。文字列を少し加工しているだけである。

表の部分でいろいろとややこしいことをしている。文字列の加工に関しては

  1. ccccの部分を作るためのrepeat_str
  2. & $ary[1]$ &ary[2] ... を作るためのadd_ary_str

の2つの関数を使って作っている。

表は最初と最後に例外が色々ある。それに対応させるため、2.のadd_ary_str色々と面倒なことをしている。そして、2.のadd_ary_strに、あらかじめ必要な計算をした配列とオプションを与えて、表の各行の文字列を生成している。

&$ary[1]$の部分は、関数を引数にとらせる関数を作れ美しくできそうなのはなんとなくわかっている。ただ、現在はまだうまくいっていない。よって、強引に処理している(今後の課題)。

その他の課題は、分数への対応である。今回、計算結果を自動表示するものを書かなかったのも、この対応ができなかったからである。色々な問題の自動生成をする以上、有理数を統一的にうまく扱う仕組みは早く考えてしまわないとまずいのはわかっているが・・・