Mukku John Blog

取り組んでいること を つらつら と

Execute RモジュールでPlotしたグラフをPDFファイルで出力する

Microsoft AzureのMachine Learningで、Rプログラムでグラフを作成し、
作成したグラフをPDFファイルとして取得してみます。
azure.microsoft.com

ゴール

イカサマサイコロを2個振って、出た目の合計ヒストグラム
PDFファイルでダウンロードできるようにします。
mukkujohn.hatenablog.com

流れ

  1. Rスクリプトを利用してヒストグラムを作成し、PDFファイルとして出力する
  2. Base64エンコードした文字列を持つファイルをAzure Blob Storageに保存
  3. ファイル内のBase64文字列から、バイト配列を取得し返す

Azure Machine Learning

Azure Machine Learningで使用するModuleは2つです。

  1. Execute R Script Module
  2. Export Data Module

f:id:MukkuJohn:20160707195538p:plain

Execute R Script Module

Execute R Script ModuleのPropertiesはこうなっています。
f:id:MukkuJohn:20160707200213p:plain
このR Script PropertyにRスクリプトを記述します。

library(ggplot2)
roll <- function() {
  die <- 1:6
  dice <- sample(die, 2, replace = 2,
                 prob = c(1 / 8, 1 / 8, 1 / 8, 1 / 8, 1 / 8, 3 / 8))
  sum(dice)
}

pdf()
rolls <- replicate(10000, roll())
qplot(rolls, binwidth = 1)
dev.off()

library(caTools)
b64ePDF <- function(filename) {
                maxFileSizeInBytes <- 5 * 1024 * 1024 # 5 MB
                return(base64encode(readBin(filename, "raw", n = maxFileSizeInBytes)))
}

d2 <- data.frame(pdf = b64ePDF("Rplots.pdf"))
maml.mapOutputPort("d2");
イカサマサイコロを2個振って、出た目を合計する

過去記事で作成した、roll関数をそのまま利用します。

roll <- function() {
  die <- 1:6
  dice <- sample(die, 2, replace = 2,
                 prob = c(1 / 8, 1 / 8, 1 / 8, 1 / 8, 1 / 8, 3 / 8))
  sum(dice)
}
ヒストグラムをPDFファイルとして出力

pdf関数で始まり、dev.offで閉じます。

pdf()
rolls <- replicate(10000, roll())
qplot(rolls, binwidth = 1)
dev.off()

PDFファイルをBase64エンコードして出力

ここは、このページのWrite a Graphics File部分をそのまま頂きます。
Execute R Script

library(caTools)
b64ePDF <- function(filename) {
                maxFileSizeInBytes <- 5 * 1024 * 1024 # 5 MB
                return(base64encode(readBin(filename, "raw", n = maxFileSizeInBytes)))
}

d2 <- data.frame(pdf = b64ePDF("Rplots.pdf"))
maml.mapOutputPort("d2");

Export Data Module

Export Data ModuleのPropertiesです。
f:id:MukkuJohn:20160707210559p:plain

RUN

ここまで設定できたら、RUNして確認してみます。
f:id:MukkuJohn:20160707210910p:plain

緑色のチェックが付いたので、Blob Storage側を確認します。
f:id:MukkuJohn:20160707210934p:plain
Export Data ModuleのPropertyで指定したファイルができています。

ファイルの取得、デコード、ダウンロード

C# Webアプリケーション MVCで作成します。
f:id:MukkuJohn:20160707212245p:plain

Azure Blob StorageをC#コードが操作するためには、このサイトを参考に進めていきます。
azure.microsoft.com
サイト内にも記載されていますが、
2つのパッケージが必要なため、GUIを使うか、パッケージマネージャコンソールからインストールします
www.nuget.org
www.nuget.org

(GUIから行いました。)
f:id:MukkuJohn:20160707211922p:plain

Controllerの作成

PDFファイルを出力するControllerを作成します。
RPlotControllerとしました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using Microsoft.Azure; 
using Microsoft.WindowsAzure.Storage; 
using Microsoft.WindowsAzure.Storage.Blob; 

namespace WebApplication1.Controllers
{
    public class RPlotController : Controller
    {
        // GET: RPlot
        public ActionResult Index()
        {
            var pdfData = GetPlotPDFData();
            if(pdfData == null)

            {
                return View();
            }

            return File(pdfData, "application/pdf", "RollPlot.pdf");
        }

        private byte[] GetPlotPDFData()
        {
            // ストレージアカウントオブジェクトを作る
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));

            // ストレージアカウントのBlobにアクセスするクライアントを作る
            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

            // コンテナを指すオブジェクトを作る
            CloudBlobContainer container = blobClient.GetContainerReference("test");

            // コンテナ内のオブジェクトを順番に参照していく
            foreach (IListBlobItem item in container.ListBlobs(null, false))
            {
                // ブロックブロブなら
                if (item.GetType() == typeof(CloudBlockBlob))
                {
                    // オブジェクトを捕まえて
                    CloudBlockBlob blob = (CloudBlockBlob)item;

                    // Machine Learningで出力したファイル名なら
                    if(blob.Name.Equals("Rplots.csv"))
                    {
                        // blobの内容を文字列として取得して、Base64エンコード文字列としてバイト配列に変換
                        return Convert.FromBase64String(blob.DownloadText());
                    }

                }
            }

            return null;
        }
    }
}

Viewの作成

こんな感じです。

@{
    ViewBag.Title = "Top Page";
}

<h1>Top Page</h1>
<p>@Html.ActionLink("ダウンロード","Index","RPlot")</p>

(RPlotContollerのIndexViewは適当に作成しておいてください。)

実行

アプリケーションを実行してみます。
f:id:MukkuJohn:20160707214415p:plain

ダウンロードリンクをクリックすると、ファイルがダウンロードされています。
f:id:MukkuJohn:20160707214513p:plain

ファイルの確認

ダウンロードフォルダを確認してファイルを開いてみます。
f:id:MukkuJohn:20160707214708p:plain
ちゃんと開けて、意図したグラフが配置されています。

まとめ

めんどくさい手順を踏みましたが、この手順を踏めば
ggplotを利用したグラフをAzure Machine Learningで作成して、
PDFファイルとして配信や、ダウンロードさせる事ができそうです。

入力データや保存先など、Web Server Parameterなりにする必要がありますが、、、


Machine Learningのモジュールをクリックして
visualizeして確認できるグラフが出力できたらなぁ。。。