rrxutil.rb および rrx ver 1.03,1.04 の追加機能について

最終更新日: 2013/11/09

    

 rrxutil.rbでは、kramdownを利用するためのメソッドが定義されています。

 kramdownは、markdown記法で書かれた原稿をhtml | LaTeX に変換する機能を持つrubyライブラリです。Rで作った表をmarkdownの原稿に組み入れやすくするために、rrxutil.rb を作りました。これには次の4つのメソッドが入っています。

 これらメソッドは、モジュールRrxに追加組込みする形にしてあります。呼び出す時は Rrx::array2table(……) のようにします。

 rrxutil.rbの中で rrxwin.rb または rrx.rb をrequireしているので、rubyスクリプトで「require "rrxutil"」と書いてあれば、「require "rrxwin"」あるいは「require "rrx"」を書く必要はありません。

 以下、rrxutilで定義されているメソッドについて記します。

 また、rrx ver 1.03,1.04 で新たに設けたメソッドなどについても記します。


《目次》


1. rrxutilで定義されているメソッド

 array2table, matrix2table の2つのメソッドについて説明する前に、まず、Rにおける1次元のarrayおよび2次元のmatrixのことを記します。

(1) Rにおける1次元のarrayおよび2次元のmatrix

 array2table() と matrix2table() の2つのメソッドは、引数の与え方が同じです。第1引数として、Rから受け取った array または matrix を与えます。

 Rプログラムにおいて1次元のarrayとして生成されたものは、array2tableで処理します。2次元であれば array であれ matrix であれ、matrix2tableで処理します。

 1次元のarrayというのは、例えば次のようなものです。Rプログラムを示します。

    

xx <- array(c(117, 177, 116, 171))
names(xx) <- c("時報", "天気予報", "電話の移転等相談", "伝言ダイヤル")
print(xx)

    

 上を実行すると下の出力が得られます。

    

        時報         天気予報 電話の移転等相談     伝言ダイヤル
         117              177              116              171

    

 見出しがあるので2行になっていますが、中身は1行のみです。つまり1次元のarrayです。

 print() で出力すると横に広がる形で表示されますが、このarrayは、実は4列ではなく4行です。本来なら縦に広がるはずですが、print() が横向きに調整しているのだと思います。

 このxxをrubyで受け取ると次のようになります。

    

                    x
  時報               117
  天気予報           177
  電話の移転等相談   116
  伝言ダイヤル       171

    

 左上端は空欄ですが、rubyの値でいうと nil です。その右隣が x という、特に意味を持たない文字になっています。

 これをRの print() と同じような出力にしたければ、1行目を削除して、縦・横逆転すればいいわけです。

 そうした調整をした上で、markdownのルールに即した表を出力するのが array2table() です。

    

 次に、2次元のmatrixについて記します。

 1次元のarrayのようなクセはありませんが、rubyで受け取った時に、行の通し番号が入ってしまう場合があります。

 例えば下のようなRプログラムを実行してみます。都道府県の人口、面積、人口密度を示すものです。人口の多い4つの都府県を取り上げます。

    

  xx <- rbind(c("東京都", 13216221, 2188.67, 6038.47),
      c("神奈川県", 9072133, 2415.86, 3755.24),
      c("大阪府", 8863324, 1901.42, 4661.42),
      c("愛知県", 7425952, 5165.14, 1437.71),
      c("全国", 127532028, 372923.77, 341.98))
  colnames(xx) <- c("都道府県", "人口", "面積", "人口密度")
  print(xx)

    

 上のxxをrubyで受け取ると、下のような2次元配列になります。最も左の列が行番号になっています。

    

    都道府県   人口        面積        人口密度
1    東京都     13216221    2188.67     6038.47
2    神奈川県   9072133     2415.86     3755.24
3    大阪府     8863324     1901.42     4661.42
4    愛知県     7425952     5165.14     1437.71
5    全国       127532028   372923.77   341.98

    

 上のような行番号(通し番号)を削除した上で、markdown記法に従った表を出力するのが matrix2table() です。

    

△ 目次に戻る


(2) array2tableを利用するサンプルスクリプト

 下に、1次元のarrayを扱うサンプルスクリプトを掲げます。都道府県の人口を表にするものです。人口の多い4都府県を取り上げます。

 markdownの原稿、html、LaTeXの3種類を標準出力に出力します。

 htmlとLaTeXは、完全なもの(kramdownのマニュアルでは stand-alone と表現されている)ではなく、部分的なものです。それだけではブラウザで閲覧したり、LaTeXの関連コマンドで処理したりできません。

    

−−−− util01.rb ここから
#! ruby -Ks
  # arrayを表に(markdown→html|tex)  (coding: Windows-31J)
require "rubygems"
require "kramdown"
require "rrxutil"
        ## Rプログラムの設定
rpro = <<EOS
xx <- array(c(13216221, 9072133, 8863324, 7425952))  # 都道府県の人口
names(xx) <- c("東京都", "神奈川県", "大阪府", "愛知県")
robj(xx)
EOS
        ## Rの実行,htmlとLaTeXへの変換
hs = Rrx.rexec(rpro)
xx = hs["robj1"]["self"]
md_str = Rrx.array2table(xx)
puts "** markdown\n" + md_str + "\n"
enc = (RUBY_VERSION >= "1.9") ? __ENCODING__ : $KCODE  # 現在の文字コード
kdoc = Kramdown::Document.new(md_str)  # Kramdownオブジェクトの生成
html_str = Rrx.nkfex(kdoc.to_html, enc)  # html生成と文字コード変換
puts "** html\n" + html_str + "\n"
tex_str = Rrx.nkfex(kdoc.to_latex, enc)  # LaTeX原本生成と文字コード変換
puts "** LaTeX\n" + tex_str + "\n"
−−−− util01.rb ここまで

    

 上のスクリプトを実行すると、次のような出力が得られます。

    

−−−− util01.rb の出力結果 ここから
** markdown
|東京都|神奈川県|大阪府|愛知県
|----|----|----|----
|13216221|9072133|8863324|7425952

** html
<table>
  <thead>
    <tr>
      <th>東京都</th>
      <th>神奈川県</th>
      <th>大阪府</th>
      <th>愛知県</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>13216221</td>
      <td>9072133</td>
      <td>8863324</td>
      <td>7425952</td>
    </tr>
  </tbody>
</table>

** LaTeX
\begin{longtable}{|l|l|l|l|}
\hline
東京都 & 神奈川県 & 大阪府 & 愛知県\\
\hline
13216221 & 9072133 & 8863324 & 7425952\\
\hline
\end{longtable}
−−−− util01.rb の出力結果 ここまで

    

 markdownの表は、csvのカンマの代わりに '|' を書くような感じです。array2tableは、rubyの配列をこのmarkdown記法の表に変換します。

 markdownの中に出てくる「|—-|—-|—-|—-」というのは、1行目の見出し(thead)と2行目以降の本体(tbody)を区切るものです。

 array2tableは、引数xxが2行以上からなる場合に、この「区切り」を自動的に挿入します。

    

 先にも書いたように、上記の html | LaTeX は、スタンドアロンではありません。これをスタンドアロンにする1つの方法は、自前で必要な情報を書き加えてやることです。

 煩雑になるのでここには掲げませんが、同梱の util01b.rb, util01c.rb を実行すると、スタンドアロンのファイル result.htm, result.tex が書き出されます。前者はブラウザで閲覧できます。

 後者の result.tex の方は、LaTeX関連のコマンドがインストールされているなら、下の2回のコマンド実行でpdfファイルを作成できます。

  platex result.tex [enter]  → result.dvi が作成される
  dvipdfmx result.dvi [enter]  → result.pdf が作成される

    

△ 目次に戻る


(3) matrix2tableを利用するサンプルスクリプト

 matrix2tableの使い方は、array2tableと同じです。

 ここでは、第1引数だけでなく、第2〜第4引数も与えるケースを取り上げます。

 4つの都府県の人口・面積・人口密度を示す表を作成します。最後の行には「全国」の人口等も示します。

 サンプルスクリプト util02.rb は、markdownの原稿と、それをhtmlに変換したものを標準出力に出力します。

 以下にスクリプトとその出力結果を掲げます。

    

−−−− util02.rb ここから
#! ruby -Ks
  # matrixを表に(markdown→html)  (coding: Windows-31J)
require "rubygems"
require "kramdown"
require "rrxutil"
        ## Rプログラムの設定
rpro = <<EOS
xx <- rbind(c("東京都", 13216221, 2188.67, 6038.47),
    c("神奈川県", 9072133, 2415.86, 3755.24),
    c("大阪府", 8863324, 1901.42, 4661.42),
    c("愛知県", 7425952, 5165.14, 1437.71),
    c("全国", 127532028, 372923.77, 341.98))
colnames(xx) <- c("都道府県", "人口", "面積", "人口密度")
robj(xx)
EOS
        ## Rの実行,htmlとLaTeXへの変換
hs = Rrx.rexec(rpro)
xx = hs["robj1"]["self"]
sep1 = [":--"] + ["--:"] * 3  # 最左列を左寄せ・他は右寄せ
sep2 = ["==="]  # 最下行をtfootにするための区切り指定
tblopt = 'border="1"'  # <table border="1"> にするための指定
md_str = Rrx.matrix2table(xx, sep1, sep2, tblopt)
puts "** markdown\n" + md_str + "\n"
enc = (RUBY_VERSION >= "1.9") ? __ENCODING__ : $KCODE  # 現在の文字コード
kdoc = Kramdown::Document.new(md_str)  # Kramdownオブジェクトの生成
html_str = Rrx.nkfex(kdoc.to_html, enc)  # html生成と文字コード変換
puts "** html\n" + html_str
−−−− util02.rb ここまで

    

−−−− util02.rb の出力結果 ここから
** markdown
|都道府県|人口|面積|人口密度
|:--|--:|--:|--:
|東京都|13216221|2188.67|6038.47
|神奈川県|9072133|2415.86|3755.24
|大阪府|8863324|1901.42|4661.42
|愛知県|7425952|5165.14|1437.71
|=====
|全国|127532028|372923.77|341.98
{: border="1"}

** html
<table border="1">
  <thead>
    <tr>
      <th style="text-align: left">都道府県</th>
      <th style="text-align: right">人口</th>
      (中略)
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left">東京都</td>
      <td style="text-align: right">13216221</td>
      <td style="text-align: right">2188.67</td>
      <td style="text-align: right">6038.47</td>
    </tr>
    (中略)
  </tbody>
  <tfoot>
    <tr>
      <td style="text-align: left">全国</td>
      <td style="text-align: right">127532028</td>
      (中略)
    </tr>
  </tfoot>
</table>
−−−− util02.rb の出力結果 ここまで

    

 上のスクリプトと出力結果をみていただければ、matrix2tableの引数がどんな意味を持つか予想できると思いますが、次項で少し説明を記します。

    

△ 目次に戻る


(4) array2table, matrix2table に与える引数

 array2table(), matrix2table() に与える第1引数は、Rで生成された1次元のarray、あるいは2次元のarrayやmatrixです。これは必ず与えます。

 それ以外の引数を与えることもできます。以下、それについて記します。

    

○ 表の見出しと本体の「区切り」

 markdownの中に出てくる「|—-|—-|……」といった記述は、1行目の見出し(thead)と2行目以降の本体(tbody)を区切るものです。この書き方によって、各々の列のデータ位置を左寄せ・中寄せ・右寄せに調整できます。

 ":—" だと左寄せ、":–:" なら中寄せ、"—:" であれば右寄せです。こうした文字列を列の個数に合わせて指定します。

 array2tableのサンプルである util01.rb では、この「区切り」を指定していません。なので、すべての列が "—-" になっていますが、もし全列を右寄せにしたければ次のようにします。

    

  md_str = Rrx.array2table(xx, ["---:"]*4)

    

 「区切り」は、必ず配列で与えます。その要素の個数が表の列の個数と合致するようにします。

 サンプルの場合、4列からなる表なので「["—:"]*4」のように書きます。

 1列目が左寄せで、2〜4列目は右寄せという場合は、下のような配列を与えます。2番目のサンプルである util02.rb ではそうなっています。

  [":---"] + ["---:"]*3

 文字列中のマイナス記号の個数は適当でかまいません。

    

 なお、見出し(thead)と本体(tbody)の区別をしたくない時は、あえて空配列 [] を指定します。これを引数として与えると、htmlに変換された時に thead がなくなり、tbody だけになります。

 引数として [] を与えないと、「["—-"]*4」(数字は実際の列の個数に置き換えられる)が与えられたものとみなされて、thead, tbody が設けられます。

    

○ tableの属性指定(枠線を表示する方法)

 markdownの表をhtmlに変換したとき、属性を何も指定しなければ「<table> …… </table>」になります。

 枠線を表示したければ、「<table border="1">」のようにborder属性を指定する必要があります。

 この指定は、array2table, matrix2table に文字列の引数として与えます。

    

  md_str = Rrx.matrix2table(xx, 'border="1"')

    

 上のように書くと、md_strの最後に次の1行が追加されます。

  {: border="1"}

 これがあると、kramdownは、単なる「<table>」ではなく「<table border="1">」に変換してくれます。

    

 array2table, matrix2table の引数として、先の「区切り」は配列で与え、borderなどの属性の指定は文字列で与えます。

 つまり、引数の種類(rubyの用語でいうclass)によって、何の指定なのかを識別できます。なので、引数を与える順番は任意です。

 第1引数は、Rから受け取ったオブジェクトでなければなりませんが、2番目以降の引数は、「区切り」と「属性」の順番を問いません。どちらを先に持ってくるかは自由です。

    

 余談ですが、border属性(枠線)と合わせてrules属性(内罫線)を指定すると、内罫線のあり方を調整できます。

  border="1" rules="rows"    → 横罫線のみ表示
  border="1" rules="cols"    → 縦罫線のみ表示

 「rules="all"」は、内罫線をすべて表示する指定ですが、枠線のborder属性を指定すると、「rules="all"」も指定されたものとみなされるようです。

    

○ tfootを設けるための指定

 kramdownは、htmlのtableを生成する場合、基本的に thead, tbody, tfoot の3つの部分を設けます。

 先述した「区切り」があると、1行目をthead、2行目以降をtbodyにします。

 そして、markdown記法の表の中で、最後の行の前に「|=====」という行が挿入されていると、kramdownの変換によって、最後の行が tfoot になります。

 「|=====」という行が挿入されてないと、最後の行も tbody になります。つまり tfoot は設けられません。

    

 引数として、「["===="]」(イコール記号の個数は任意)を指定すると、markdownにした時に「|=====」が挿入され、htmlに変換した時に tfoot が設けられます。

 「["===="]」のように、配列の要素を必ず1つだけにして、その要素がイコール記号だけからなる文字列にします。その条件に合致しない配列は、「区切り」とみなされてしまいます。

 配列を記述するのが面倒なら、"===" のような文字列でもかまいません。イコール記号だけからなる文字列は、borderなどの「属性」の指定ではなく、tfootにまつわる指定と解釈されます。

    

△ 目次に戻る


(5) html_template() によるスタンドアロンの作成

 掲載を省略しましたが、util01b.rb は、スタンドアロンのhtmlを作成する1つの例です。自前で必要な記述を挿入する方法でやっています。

 その他に、kramdownで変換する時に、テンプレートを指定する方法があります。

    

  kdoc = Kramdown::Document.new(md_str, {:template=>"./template.txt"})
  html_str = kdoc.to_html

    

 上のようにすると、カレントディレクトリにある template.txt というファイルをテンプレートにして、スタンドアロンのhtmlを生成することができます。

 template.txt の中身は、例えば次のようなものです。

    

<html>
<head>
<title>test page</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<%= @body %>
</body>
</html>

    

 kramdownによってhtmlに変換されたものは、@body に代入されてテンプレートに組み込まれます。組み込みは erb で行われます。

 rrxutil.rb で定義されている html_template() は、このようなテンプレートファイルを書き出すメソッドです。

 ファイルは、tempfileとして書き出され、tempfileオブジェクトが戻り値として返されます。

    

  tfile = Rrx.html_template("euc-jp")  # 引数は charset の指定
  print File.open(tfile.path) {|ff| ff.read}  # ファイルの内容を表示
  tfile.unlink  # テンプレートファイル(tempfile)を削除

    

 html_template() には引数を2つ与えることができます。

 第1引数では、htmlの charset を指定します。日本語なら "utf-8", "euc-jp", "Shift_JIS" などです。指定しなかった時は、素材データの文字コードに対応するものになります(ruby ver 1.8系の場合は $KCODE に応じて設定されます)。

 当然ながら、kramdownの変換を経て得られたhtmlの文字コードをこのcharset指定と同じものにしなければなりません。

 第2引数は、数式を扱いたい時に :mathjax を指定します。そうすると MathJax のためのhtml記述が挿入されます。

 もし第2引数として文字列を与えると、その文字列が「</head>」の前に挿入されます。

    

 html_template() のテンプレートには次の特徴があります。

 markdownの原稿で最初に出てくるヘッダ(h1など)をhtmlのtitleとして用います。

 markdown記法では、行等に '#'(半角のシャープ記号)があると、<h1>……</h1> などに変換されますが、最初の該当部分をhtmlのtitleとして用います。

    

 以下にサンプルスクリプト util03.rb を掲げます。

 Rプログラム部分は util02.rb と同じなので [中略] にします。

    

−−−− util03.rb ここから
#! ruby -Ks
  # templateでstand-aloneのhtmlを作成  (coding: Windows-31J)
require "rubygems"
require "kramdown"
require "spreadsheet"
require "rrxutil"
        ## Rプログラムの設定
rpro = <<EOS
  [中略]
EOS
        ## Rの実行,htmlへの変換
hs = Rrx.rexec(rpro)  # Rの実行
xx = hs["robj1"]["self"]
md_str = <<EOS2
# 都道府県の人口・面積・人口密度\n
 都道府県の人口(人)、面積(平方km)、人口密度(人/平方km)は次のとおり。\n
 人口の多い順に、4都府県のみ示す。\n
#{Rrx.matrix2table(xx, ["==="], 'border="1"')}
# ぜんぜん関係ないけど数式の例
分数の計算:
$$ \\frac{1}{2} + \\frac{1}{3} = \\frac{3 + 2}{6} = \\frac{5}{6} $$\n
相加平均の計算は次のとおり。\n
$$
\\begin{equation*}
μ = \\frac{1}{n}\\sum_{i=1}^{n} x_i = 
\\frac{x_1 + x_2 + \\cdots + x_n}{n}
\\end{equation*}
$$
EOS2
        ## kramdownによるhtmlの生成
charset = "euc-jp"  # これから作るhtmlの文字コード
tfile = Rrx.html_template(charset, :mathjax)  # テンプレート生成(tempfile)
kdoc = Kramdown::Document.new(md_str, {:template=>tfile.path})
html_str = Rrx.nkfex(kdoc.to_html, charset)
File.open("result.htm", "w") {|ff|  ff.write html_str}
tfile.unlink  # テンプレートファイルを削除
puts "'result.htm' を出力しました."
−−−− util03.rb ここまで

    

 数式の記述について説明するのは大変なので省略します。興味があるようでしたら、MathJaxやkramdownの解説を参考にして下さい。

 なお、markdownの原稿の中で、'$$'(半角のドル記号2つ)で数式を囲んでいますが、これは MathJax の記法ではなく、kramdownの math block の記法です。

 html_template() のテンプレートを利用する場合は、MathJaxのルールに即して数式を書き入れる際、\(……\) を用います。ドル記号が使える設定にはなっていません。

 ちょっと ややこしいですが、ご注意ください。

    

△ 目次に戻る


(6) tex_template() によるスタンドアロンの作成

 tex_template() は、LaTeXのスタンドアロンを作成するためのテンプレートを書き出します。テンポラリファイルとして書き出します。

 引数を与えない時は、「\documentclass{jarticle}」がドキュメントクラスになります。

 引数として何か文字列を与えると、それがドキュメントクラスになります。テンプレートの冒頭にそれが置かれます。

 例えば、A4サイズ・12ポイントを明記したいのであれば次のようにします。

  dclass = '\documentclass[a4paper,12pt]{jarticle}'
  tfile = Rrx.tex_template(dclass)

    

 ドキュメントクラスとして jsarticle を指定し、\section を「第1章」とか「第2章」に変換したいのであれば次のようにします。

  tfile = Rrx.tex_template(<<'EOS')
  \documentclass{jsarticle}
  \renewcommand{\presectionname}{第}
  \renewcommand{\postsectionname}{章}
  EOS

    

 以下にLaTeX文書の result.tex を出力するスクリプトを掲げておきます。

 util03.rbを書き換えたものです。Rプログラム部分とmarkdownの原稿部分は同じです。util03.rbと共通するところは省略します。

    

−−−− util03b.rb ここから
#! ruby -Ks
  # templateでstand-aloneのLaTeXを作成  (coding: Windows-31J)
require "rubygems"
require "kramdown"
require "spreadsheet"
require "rrxutil"
        ## Rプログラムの設定
rpro = <<EOS
  [中略]
EOS
        ## Rの実行,LaTeXへの変換
hs = Rrx.rexec(rpro)  # Rの実行
xx = hs["robj1"]["self"]
md_str = <<EOS2
  [中略]
EOS2
        ## kramdownによるLaTeXの生成
tfile = Rrx.tex_template(<<'EOS3')
\documentclass{jsarticle}
\renewcommand{\presectionname}{第}
\renewcommand{\postsectionname}{章}
EOS3
kdoc = Kramdown::Document.new(md_str, :template=>tfile.path)
tex_str = kdoc.to_latex
File.open("result.tex", "w") {|ff|  ff.write tex_str}
tfile.unlink  # テンプレートファイルを削除
puts "'result.tex' を出力しました."
−−−− util03b.rb ここまで

△ 目次に戻る


2. rrx ver 1.03 で追加したメソッドなどについて

 メソッドの仕様については rrxwin02.txt を参照して下さい。

 以下ではweb上のExcelファイルを利用する方法、rooの利用例をサンプルによって示したいと思います。

    

(1) xls2ary()

 当サイトの「単純集計に関する覚え書き/まとめ(関数化)」のところで用いた素材データ data01.csv〜data04.csv を、1つのExcelファイルに取りまとめて、下のurlにアップロードしてあります。

http://cup.sakura.ne.jp/x/sample_data.xls

 sample_data.xls の他に、拡張子が xlsx, ods(OpenOffice), xml(Excel2003xml)のものもあります。いずれも中身は同じです。

 また、Rの関数を収録した tjsf.r を下のurlに置きました。

http://cup.sakura.ne.jp/R/tjsf.r

    

 これらを使って簡単な集計を行い、htmlファイルを書き出すスクリプトを下に掲げます。

 ここでの要点は xls2ary() です。ハードディスクなどにあるローカルなExcelファイルだけでなく、web上にあるものも扱えます。その一例を下に掲げます。

    

−−−− util04.rb ここから
#! ruby -Ks
  # xls2aryでweb上のExcelを扱う  (coding: Windows-31J)
require "rubygems"
require "kramdown"
require "spreadsheet"
require "rrxutil"
        ## Rプログラムの設定
rpro = <<EOS
source("http://cup.sakura.ne.jp/R/tjsf.r", encoding="utf-8")
dtf <- read.csv("@@last@@", header=T, na.strings="")
dtf$性別 <- factor(dtf$性別, levels=c("男", "女"), labels=c("男", "女"))
xx <- sa1(dtf, "性別", "意見")
xx <- lround(xx, 1)
zz <- join.tbl(xx$tbl2, xx$pct1, "%d(%.1f)")
robj(zz)
EOS
        ## Rの実行,htmlへの変換
xl_file = "http://cup.sakura.ne.jp/x/sample_data.xls"
sheets = Rrx.xls2ary(xl_file)  # Excelファイルを読み込んで配列に変換
Rrx.temp_make(sheets[0], ".csv")  # 第1ワークシートをcsvとして出力
hs = Rrx.rexec(rpro)  # Rの実行
zz = hs["robj1"]["self"]
md_str = <<EOS2
# 男女別の「意見」の集計結果\n
 男女別に「意見」(賛成・中立・反対)を集計すると次のとおり。\n
#{Rrx.matrix2table(zz, ["==="], 'border="1"')}
EOS2
        ## kramdownによるhtmlの生成
charset = "euc-jp"  # これから作るhtmlの文字コード
tfile = Rrx.html_template(charset)  # kramdownのテンプレートを生成(tempfile)
kdoc = Kramdown::Document.new(md_str, {:template=>tfile.path})
html_str = Rrx.nkfex(kdoc.to_html, charset)
File.open("result.htm", "w") {|ff|  ff.write html_str}
tfile.unlink  # テンプレートファイルを削除
puts "'result.htm' を出力しました."
−−−− util04.rb ここまで

    

 xls2ary() は、Excelファイルを読み込んで、全ワークシートをrubyの配列に変換するものです。「sheets = Rrx.xls2ary("sample.xls")」とすれば、sample.xlsの全ワークシートが変数sheetsに代入されます。

 サンプルに出てくる sample_data.xls には全部で4つのワークシートが入っていますが、第1ワークシートを参照するなら sheets[0]、第4ワークシートを参照したければ sheets[3] をみます。

 その次にある「Rrx.temp_make(sheets[0], ".csv")」は、第1ワークシートをcsvファイルとして書き出すものです。ファイルは、テンポラリファイルとして出力されます。

 そのテンポラリファイルの名前は、rubyが内的に記憶しています。Rプログラムの中にあった @@last@@ がそのテンポラリファイルの名前に置き換えられます。

    

 「hs = Rrx.rexec(rpro)」は、Rプログラムの実行です。Rプログラムは、文字列 rpro にセットされていますが、それを実行します。

 Rプログラムの出力は hs[:sink] にセットされます。また、Rの実行過程すべてが hs[:log] にセットされます。必要なら参照して下さい。ちなみに、Rプログラム実行中に出された警告メッセージは、hs[:sink] には入りません。hs[:log] の方に記録されます。

    

 Rプログラムの中で、web上にある tjsf.r を読み込んでいますが、職場や学校等proxyが設定された環境だと、うまく読み込めないかもしれません。

 その時は、Rの起動オプションに –internet2 を加えてみて下さい。具体的には rexec() に次のような第3引数を与えます。

  hs = Rrx.rexec(rpro, nil, "--no-save -q --internet2)

 第2引数を nil でなく "log.txt" にすれば、log.txt というファイルにRのログが書き出されます。

    

 util04.rb では *.xls を扱うので、「require "spreadsheet"」としましたが、これを「require "roo"」にすれば、*.xlsx, *.ods, *.xml も扱うことができます。

 もちろん roo で *.xls を扱うこともできますが、その場合、rooは、内部で spreadsheet の機能を呼び出しています。

    

△ 目次に戻る


(2) gss2ary()

 web上にある Google Document Spreadsheet(以下 gss)を扱いたい時は、gss2ary() を用います。rooをrequireしておく必要があります。

 このメソッドの機能は xls2ary() と同じですが、Excelファイルを指定する第1引数のところにgssのkeyを指定します。

 gssはweb上にあり、そのurlは「https://docs.google.com/spreadsheet/ccc?key=xxxx」のようなものになります。このxxxxの部分を第1引数に指定します。

 また、第2引数で Google Drive にアクセスするためのアカウント情報を指定します。

 gssを扱うためには、Google Drive にアクセスするためのアカウントを持っていなければなりません。あなた自身のユーザー名(Googleのemailアドレス)とパスワードが必要になります。

    

 公開されているgssを使わせていただいて、その内容をタブ区切りテキストの形で出力するスクリプトを下に掲げておきます。

 gss2ary() の戻り値は、今回、ハッシュで得るようにしています。こうすると、ワークシート名を鍵にしてその内容を参照することができます。

 ユーザー名とパスワードは、ご自分のものに書き換えて下さい。

    

  −−−−−−−−−−−−
  #! ruby -Ks
    # (coding: Windows-31J)
  require "rubygems"
  require "roo"
  require "rrxutil"
  key = '0AuCUD7G5hGZrdGlBbHBDVElfUXdsbWRkRThVcmdCalE'
  user = 'xxxx@gmail.com'
  password = 'xxxxxxxx'
  opt = {:user=>user, :password=>password}
  sheets = Rrx.gss2ary(key, opt, :hash)
  if sheets
    sheets.each do |sheet_name, ary|
      printf("\f%s\n", sheet_name)
      print Rrx.ary2str(ary, "\t")
      printf("\n")
    end
  end
  −−−−−−−−−−−−

    

△ 目次に戻る


(3) ちょっと実践的なサンプル

 最後に、少しだけ実践的なサンプルを掲げておきます。

 htmlを生成するサンプルですが、kramdownの目次自動生成の機能を利用し、また、Rで作ったグラフをhtmlに組み入れます。

    

 素材データとして、次のサイトに掲載されている sample1.xls を利用させていただきます。

アンケート分析

 これは、ある自動車ディーラーが新車発表会で実施した来場者アンケートの結果です。回答者は 500人。

 新車への期待と反応を調査する目的で行われたアンケートで、回答者の年齢層、運転歴、「何に期待して来場したか」の期待事項、新車への評価といった項目があります。

 年齢層と運転歴は、いくつかのカテゴリーから1つだけを選ぶ方式、

 「外観に期待」などの期待事項は、「はい」か「ノーマーク」のどちらか一方、

 「外観の評価」などの新車への評価は、「満足・まあまあ・あまり良くない・悪い・わからない」の5つから1つを選ぶ方式です。

 Excelの第7ワークシートに500人分の素材データが取りまとめられています。

 今回は、年齢層と期待事項のみ取り上げます。

 ちなみに、上記サイトでは、クロス集計だけでは難しい多様な角度からのデータ分析について KaleiDiagram for Excel というソフトウェアの有効性が紹介されています。直感的でわかり易い分析手法を提供するもののようです。

    

 以下にサンプルスクリプトを掲げます。

 それに関していろいろ解説を記すべきところではありますが、省略します。もしかすると後日、アップロードするかもしれません。

 とりあえずサンプルとして参考にしていただければ幸いです。

    

−−−− util05.rb ここから
#! ruby -Ks
  # create a html document by R and kramdown (coding: Windows-31J)
require "rubygems"
require "roo"
require "kramdown"
require "erb"
require "rrxutil"
        ## Rプログラムの記述
rpro = <<R_PROGRAM
source("http://cup.sakura.ne.jp/R/tjsf.r", encoding="utf-8")
dtf <- read.csv("@@last@@", header=T)
ma_col <- grep("に期待$", colnames(dtf))  # 複数回答の列番号群を取得
dtf <- ma.refactor(dtf, ma_col, c("はい", "ノーマーク"))
ww <- sa1(dtf, "年齢")
png(file="bar.png")
par(family = "Japan1GothicBBB")  # 日本語フォントにゴチックを指定
barplot(ww$tbl1, main="年齢別回答者数", xlab="年齢階層",
    ylab="回答者数", names.arg=names(ww$tbl1))
dev.off()
ss <- join.tbl(ww$tbl2, ww$pct1, "%d(%.1f)")  # 年齢の構成分布
ww <- ma1(dtf, "年齢", ma_col)
tt <- join.tbl(ww$tbl, ww$pct, "%d(%.1f)")  # 期待事項の回答状況
xx <- ww$pct
xx <- xx[,-ncol(xx)]  # 右端の「該当数」を削除
nr <- nrow(xx)  # 最下行の「合計」の行番号
for (j in 1:ncol(xx))  # 特化係数の算出
  for (i in 1:(nr-1)) {
    if (xx[nr,j] == 0)  next
    xx[i,j] <- xx[i,j] / xx[nr,j]
  }
robj(list(回答者分布=ss, 回答状況=tt, 特化係数=round(xx,2)))
R_PROGRAM
        ## Rの実行と結果の受け取り
xl_file = "http://www.timecube.co.jp/Kaleid/aplcn/apl1/sample1.xls"
sheets = Rrx.xls2ary(xl_file)  # Excelファイルを読み込んで配列に変換
Rrx.temp_make(sheets[6], ".csv")  # 第7ワークシートをcsvとして出力
hs = Rrx.rexec(rpro)  # Rの実行
xx = hs["robj1"]
        ## markdown原稿の生成
tblopt = 'border="1"'  # <table>のオプション(枠線の表示)
md_src = <<MARKDOWN
# 新車発表会のアンケート結果について\n
 ○○年××日に行われた新車発表会で、来場者に対して行った
アンケート(回答者500人)の考察結果を記す。\n
- - - - - - - - -\n
# 《目次》
{:#contents}\n
* contents list
{:toc}\n
- - - - - - - - -\n
## 1. 「年齢」と「何に期待して来場したか」との関連\n
### 1-1 回答者の年齢の分布\n
 まず、回答者の年齢の分布をみる。回答者総数は500人。\n
<%= Rrx.array2table(xx["回答者分布"], tblopt) %>
![画像:年齢別回答者数](bar.png)\n
 概観を箇条書きにすると次のとおり。\n
- 20歳未満と60歳以上が両者とも13人(2.6%)と少数。
- 40代が163人と多く、約3分の1を占める。
- 20代・30代・50代は、いずれも2割前後を占める。\n
[△ 目次に戻る](#contents)\n
- - - - - - - - -\n
### 1-2 回答状況\n
 次に、「外観に期待」などの期待事項に「はい」と回答した人の数と
その比率をみると下のとおり。\n
 全体的にみると、「居住性に期待」と「価格に期待」が53%程度を占め、
「外観に期待」(36%)と「乗心地に期待」(41%)に比べて高い。\n
<%= Rrx.matrix2table(xx["回答状況"], tblopt, "===") %>
[△ 目次に戻る](#contents)\n
- - - - - - - - -\n
### 1-3 特化係数\n
 先の表だと、年齢層による特徴を把握しにくいので、「合計」欄の
比率を基準とする特化係数をみてみよう。\n
 なお、「合計」欄の数値は特化係数ではなく、回答比率(%)である。\n
<%= Rrx.matrix2table(xx["特化係数"], tblopt, "===") %>
 特化係数を手がかりにして大雑把に概観すると、次の点を指摘できる。\n
- 全体的に高めの「居住性」と「価格」は、どの年齢層別も比較的高いか平均的。
- 「外観」は、30代と50代が高く、40代が平均的、60歳以上と29歳以下は低い。
- 「乗心地」は、40代と60歳以上が高く、19歳以下と30代が低い。
20代と50代は平均的。\n
 「何に期待して来場したか」について、年齢階層別の特徴を上げたが、
「年齢が高いほど……」といった一定方向の傾向は指摘できない。\n
 ちなみに、各々の期待事項ごとに年齢層とのクロス集計を行い、
\\\\(χ^{2}\\\\)検定にかけた結果、いずれも有意性は認められなかった。\n
[△ 目次に戻る](#contents)\n
- - - - - - - - -\n
## 2. 「運転歴」と「何に期待して来場したか」との関連\n
 [以下、省略]\n
MARKDOWN
        ## markdown→html変換
md_str = ERB.new(md_src).result(binding)
File.open("result.md", "w") {|ff|  ff.write md_str}
enc = "euc-jp"  # これから作るhtmlのencode
tfile = Rrx.html_template(enc, :mathjax)  # テンプレート生成(tempfile)
opt = {:template=>tfile.path, :toc_levels=>[2,3]}
kdoc = Kramdown::Document.new(md_str, opt)
html_str = Rrx.nkfex(kdoc.to_html, enc)
File.open("result.htm", "w") {|ff|  ff.write html_str}
tfile.unlink  # テンプレートファイルを削除
puts "'result.md', 'result.htm', 'bar.png' を出力しました."
−−−− util05.rb ここまで

    

〜 以上 〜

Copyright (C) T. Yoshiizumi, 2013 All rights reserved.


rrxのページへ

kramdownに関する覚え書き 〜 markdown, html, LaTeX の変換処理

トップページへ