filename myfile "/var/tmp/total_cases.csv"; options set=SSL_USE_SNI=1; options set=SSL_SNI_HOSTNAME="covid.ourworldindata.org"; proc http url="https://covid.ourworldindata.org/data/ecdc/total_cases.csv" method="GET" out=myfile; run; proc import out=work.total_cases datafile=myfile dbms=csv replace; getnames=yes; datarow=2; guessingrows=200; run;
SASプログラムとログを解析するユーティリティを開発するための備忘録です。This is a memo to develop utility that analyzes the SAS log.
2020年3月30日月曜日
PROC HTTP コロナウィルスのデータ
Webページに掲載されているCSVファイルを読み込むサンプルです。PROC HTTPを使って、コロナウィルスのデータCSVを読み込んでいます。
エラー”SSL Error: Invalid subject name”の対応として、オプションを設定していますが、これはProblem Note 64218に情報があります。
2017年7月5日水曜日
Enterprise Guide 7.13, 実行時のエラーに対するアクション
2016年11月13日日曜日
Enterprise GuideのMap Chartの例
SAS Enterprise Guideでマップチャートを使った例をメモしておきます。資料を探すと海外のネタがいくつか転がっていますが、今回は埼玉県のマップを描きます。さて、ここで迷ったのが日本の地図のデータをどこから取ってくるかです。東京都のデータなら、NLSのライブラリMAPSの下にあります。東京以外のデータも描きたいということで、別なところから地図のデータを探して取ってきます。地図データの検索キーワードは"地図 シェープファイル”で手繰ります。以下、マップを描く手順です。
データの役割を下の図のように設定します。ID変数役割で間違った変数を指定すると、思わぬ方向に線が引かれることがあります。そのときには、ID変数を疑ってください。
変数RANDOMを集計するので、「グラフに使用する統計量」に合計を指定します。それと凡例の箇所もチェックしてください。
- 全国市区町村界データをesriジャパンから取ってくる
- PROC MAPIMPORTでシェイプを読み込んでデータセットにする
- データセットから埼玉県だけを抽出
- エリア毎の濃淡をつけるために乱数で変数を作る
- マップチャートで描く
出力はこんなイメージです。
最初にesriジャパンのWebサイトを検索して、全国市区町村界データをダウンロードします。ダウンロードしたら、ZIPファイルを展開してc:\tempの下に置きます。
次にコードタスクで、ダウンロードしたシェイプのデータを読み取ります。埼玉県だけの情報に絞って、乱数で適当な変数を作ります。この変数はマップチャートのタスクで集計します。
データセット選択して、タスク>グラフ>マップチャートを選択します。2D塗り分け地図を選びます。因みに、シェープデータだけで「空白の地図を作成」することができます。シェープデータの中味を確認するときに使ってください。
データの役割を下の図のように設定します。ID変数役割で間違った変数を指定すると、思わぬ方向に線が引かれることがあります。そのときには、ID変数を疑ってください。
変数RANDOMを集計するので、「グラフに使用する統計量」に合計を指定します。それと凡例の箇所もチェックしてください。
プロセスフローは以下のようになるはずです。
シェイプファイルですが、様々なフォーマットで色んなところから提供されています。メッシュ上に区切った形状のものや、海岸線、避難地域など国交省のネタがあることを知りました。シェイプファイルについて、私が参照したリンクはコチラです。
2016年9月26日月曜日
EG7.1 で credentials.xml の位置が変わってます。
EGで credentials.xml を使う人向けの情報です。
バッチ実行で、credentials.xml を使うネタは、以下のNote:に記述があります。
が、7.1の情報が書かれていません。
Usage Note 30917: Scheduling projects in SAS® Enterprise Guide®
EG7.1のパスは変更されています。
%APPDATA%\SAS\SharedSettings\7.1\credentials.xml で作成してください。
あと、server nameの値はプロファイルの名前でした。これ一時間ほど悩みました。
2016年8月7日日曜日
ローカルのサーバで、RPMのスコアリングを行う方法
デスクトップ版のEnterprise MinerとEnterprise GuideのRPMの組合せですが、スコアリングは、Metadata Serverに接続しないとできない仕様になっています。わざわざ筆を持ち換えて、Enterprise Minerに移るのは面倒です。
そんなときは、コードタスクでスコアのデータセット名を書き換えればスコアリングできます。RPMの「前回実行したコード」を表示してコードタスクにコピーして、SCORE=とSCOREOUT=の部分を書き換えます。
そんなときは、コードタスクでスコアのデータセット名を書き換えればスコアリングできます。RPMの「前回実行したコード」を表示してコードタスクにコピーして、SCORE=とSCOREOUT=の部分を書き換えます。
%EM_RPM(
FLOW=INTERMEDIATE,
PROJPATH=%NRBQUOTE(C:\Temp\RPM),
PROJNAME=%NRBQUOTE(RPM),
TASKID=efb7cb31-d183-4282-81d6-d938435074fd,
DATA=&em_traindata,
VARIABLEDELTA=&em_vardelta,
TARGETLEVEL=,
DECDATA=&em_decdata,
PRIOR=NONE,
DECISION=INVERSE,
EVENT=%NRBQUOTE()
,
SCORE=WORK.TEST,
SCOREOUT=WORK.SCORED_TEST
);
2016年4月8日金曜日
Enterprise Guide, UACダイアログが出る現象
2016年3月22日火曜日
RPM - Rapid Predictive Modeler
10年ぶりのEnterprise Miner
久しぶりにEnterprise Minerを使ったら、RPMなる便利な機能が付いてました。10年以上前にSAS Enterprise Minerのトレーニングを受けたものの、仕事ではSPSS Modeler(Clementine)ばかりを使っていました。しばらく会えなかった友人(又は恋人)に再開したような気持ちです。RPMとは何か?
Enterprise Guideのデータに対して目的変数、説明変数を設定し、予測モデルを作ってくれる機能です。データ加工はEGの上で行って、EMのプロジェクトはRPMで作ることができます。モデル作成の機能が割り切りよく、基本、中間、詳細の3段階というのが良いです。できたモデルをEGから参照して、スコアリングできます。細かい調整をしたい人は、EMからプロジェクトを開いて修正します。モデル作成で詳細を指定すると、回帰、決定木と複数のモデルを作成して比較してくれます。とはいえ、実際に使うモデルの手法は、業務や分析者で決まってしまうとは思いますが。
Rev up your RPMs; A Modeling Sampler動画
RPMがどんなものかは、下の動画を見れば、一目瞭然かと思います。Part 1
Part 2
Part 3
2015年12月28日月曜日
EGPからログを抽出するVBScript
EGPからログを抽出するスクリプトを作りました。EGPをZIPのファイルにコピーして、そのなかからresult.logのファイルを特定し、1つのファイルに出力しています。この方法は、公式ではなくNon Supportです。EGPのファイルが壊れたときに救済手段として、どこかに紹介されていました。
DebugFlag = Trueだと、メッセージのダイアログを表示します。あと、ログファイルの並び順は意識していません。
DebugFlag = Trueだと、メッセージのダイアログを表示します。あと、ログファイルの並び順は意識していません。
'---
' プログラム: EGPのファイルからSASログを抽出します。
' 説明: EGPの拡張子をZIPに変更して、ZIPのフォルダからresult.logのファイルを抽出
' 作成者: mining
'
' 引数1: EGPのファイルパス
' 引数2: ログファイルのパス
' 実行例: cscript foo.vbs C:\temp\foo.egp C:\temp\foo.log
'
'---
Option Explicit
On Error Resume Next
'---
' 定数
'---
Const FOF_SILENT = &H4 ' 進捗ダイアログを表示しない
Const FOF_NOCONFIRMATION = &H10 ' 上書き確認ダイアログを表示しない
Const ForWriting = 2 ' テキストファイルのオープン
Const ForReading = 1 ' テキストファイルのオープン
Const TristateUseDefault = -2 ' Opens the file using the system default.
Const TristateTrue = -1 ' Opens the file as Unicode.
Const TristateFalse = 0 ' Opens the file as ASCII.
Const DebugFlag = True
'---
' 変数
'---
Dim objShell
Dim objFso
Dim objTs
Dim sZipFile
Dim sTempFolder
Dim sEgpFilePath
Dim sLogFilePath
Dim ErrCount
Dim WarCount
Dim sMsg
'---
' オブジェクト生成します。
'---
Set objShell = CreateObject("Shell.Application")
Set objFso = CreateObject("Scripting.FileSystemObject")
'---
' 引数をチェックします。
'--
If WScript.Arguments.Count <> 2 Then
Call MsgBox("引数1にEGP、引数2にログファイルを指定してください。", vbOKOnly + vbExclamation, WScript.ScriptName)
WScript.Quit(1)
End If
sEgpFilePath = WScript.Arguments.Item(0)
sLogFilePath = WScript.Arguments.Item(1)
If objFso.FileExists(sEgpFilePath) = False Then
Call MsgBox("引数1で指定したファイルが存在しません。", vbOKOnly + vbExclamation, WScript.ScriptName)
WScript.Quit(1)
End If
'---
' デバッグ用のメッセージ出力
'---
Sub DebugMsg(msg)
If DebugFlag = True Then
Call MsgBox(msg, vbOKOnly + vbInformation, WScript.ScriptName)
End If
End Sub
'---
' ZIPファイルを指定したフォルダに解凍
'---
Sub Unzip(objShell, sFile, sFolder)
Dim objFilesInZip
Dim objFolder
Set objFilesInZip = objShell.Namespace(sFile).Items
If Err.Number <> 0 Then
Exit Sub
End If
Set objFolder = objShell.Namespace(sFolder)
If Err.Number <> 0 Then
Exit Sub
End If
If (Not objFolder Is Nothing) Then
objFolder.CopyHere objFilesInZip, FOF_NOCONFIRMATION + FOF_SILENT
Else
Err.Raise 432 ' オートメーションの操作中にファイル名またはクラス名を見つけられませんでした。
End If
Set objFilesInZip = Nothing
Set objFolder = Nothing
End Sub
'---
' フォルダを作成
'---
Sub CreateUnzipFolder(objFso, sFolder)
objFso.CreateFolder sFolder
End Sub
'---
' フォルダを削除
'---
Sub DeleteUnzipFolder(objFso, sFolder)
If objFso.FolderExists(sFolder) = True Then
objFso.DeleteFolder sFolder, True
End If
End Sub
'---
' テンポラリのフォルダのパスを作成
'---
Function CreateFolderPath(objFso, sFolder)
Const TemporaryFolder = 2
Dim objTempFolder
Set objTempFolder = objFso.GetSpecialFolder(TemporaryFolder)
CreateFolderPath = objFso.BuildPath(objTempFolder.Path, sFolder)
Set objTempFolder = Nothing
End Function
'---
' サブフォルダからresult.logを探して、objTsに出力
'---
Sub SearchLog(objFso, objTs, tmpFolderItems)
Const FileName = "result.log"
Dim objFolderItemsB
Dim objItem
Dim Stream
For Each objItem in tmpFolderItems
' 取り出した物がファイルかフォルダかを判定
If objItem.IsFolder Then
' フォルダであれば、再帰呼び出しでフォルダ階層を手繰ります。
Set objFolderItemsB = objItem.GetFolder
Call SearchLog(objFso, objTs, objFolderItemsB.Items())
ElseIf objItem.Name = FileName Then
' ファイル名が一致したら、テキストを読み取りobjTSに出力します。
Set Stream = CreateObject("ADODB.Stream")
Stream.Charset = "UTF-8"
Stream.Type = 2
Stream.Open
Stream.LoadFromFile(objItem.Path)
objTs.Write(Stream.ReadText)
Stream.Close
Set Stream = Nothing
End If
Next
Set objItem = Nothing
Set objFolderItemsB = Nothing
End Sub
'---
' ログファイルからERROR, WARNINGの件数をカウント
'---
Sub CountLog(objFso, sLogFile, byRef ErrCount, byRef WarCount)
Const KeyError = "e ERROR"
Const KeyWarning = "w WARNING"
Dim objTs
Dim sBuf
On Error Goto 0
ErrCount = 0
WarCount = 0
Set objTs = objFso.OpenTextFile(sLogFile, ForReading, False, TristateTrue)
If Err.Number <> 0 Then
Exit Sub
End If
Do Until objTs.AtEndOfLine = True
sBuf = objTs.ReadLine
If Left(sBuf, Len(KeyError)) = KeyError Then
ErrCount = ErrCount + 1
ElseIf Left(sBuf, Len(KeyWarning)) = KeyWarning Then
WarCount = WarCount + 1
End If
Loop
objTs.Close
If Err.Number <> 0 Then
Exit Sub
End If
Set objTs = Nothing
End Sub
'---
' エラーチェック
'---
Function CheckError(fnName)
Checkerror = False
Dim strmsg
Dim errNum
If Err.Number <> 0 Then
strmsg = "Error #" & Hex(Err.Number) & vbCrLf & "In Function " & fnName & vbCrLf & Err.Description
Call MsgBox(strmsg, vbOkOnly + vbCritical, WScript.ScriptName)
Checkerror = True
End If
End Function
'---
' ログファイルを開きます。
'---
Set objTs = objFso.CreateTextFile(sLogFilePath, True, True)
If CheckError("objFso.CreateTextFile") Then
WScript.Quit(1)
End If
'---
' EGPの拡張子をZIPに変更してコピーします。
'---
sZipFile = CreateFolderPath(objFso, objFso.GetTempName & ".zip")
Call DebugMsg("EGPの拡張子をZIPに変えてコピー:" & sZipFile)
objFso.CopyFile sEgpFilePath, sZipFile
If CheckError("objFso.CopyFile") Then
WScript.Quit(1)
End If
'---
' 解凍先のテンポラリのフォルダを作成します。
'---
sTempFolder = CreateFolderPath(objFso, objFso.GetTempName)
Call DebugMsg("テンポラリのフォルダを作成:" & sTempFolder)
Call CreateUnzipFolder(objFso, sTempFolder)
If CheckError("CreateUnzipFolder") Then
WScript.Quit(1)
End If
'---
' ZIPファイルを解凍します。
'---
Call DebugMsg("ZIPファイルを解凍:" & sZipFile)
Call Unzip(objShell, sZipFile, sTempFolder)
If CheckError("Unzip") Then
WScript.Quit(1)
End If
'---
' テンポラリフォルダからログファイル探してobjTSに出力します。
'---
Call DebugMsg("テンポラリのフォルダからログを収集:" & sTempFolder)
Call SearchLog(objFso, objTs, (objShell.NameSpace(sTempFolder)).Items)
If CheckError("SearchLog") Then
WScript.Quit(1)
End If
'---
' ログファイルを閉じます。
'---
objTs.Close
If CheckError("objTs.Close") Then
WScript.Quit(1)
End If
'---
' テンポラリのフォルダを削除します。
'---
Call DebugMsg("テンポラリのフォルダを削除:" & sTempFolder)
Call DeleteUnzipFolder(objFso, sTempFolder)
If CheckError("DeleteUnzipFolder") Then
WScript.Quit(1)
End If
'---
' ZIPファイルを削除します。
'---
Call DebugMsg("ZIPファイルを削除:" & sZipFile)
objFso.DeleteFile sZipFile
If CheckError("objFso.DeleteFile") Then
WScript.Quit(1)
End If
'---
' Error, Warningの件数を数えます。
'---
Call CountLog(objFso, sLogFilePath, ErrCount, WarCount)
If CheckError("objFso.DeleteFile") Then
WScript.Quit(1)
End If
Call DebugMsg("ERROR件数:" & CStr(ErrCount) & " WARNING件数:" & CStr(WarCount))
'---
' オブジェクトを破棄します。
'---
Set objTs = Nothing
Set objFso = Nothing
Set objShell = Nothing
'---
' 終了
'---
WScript.Quit(0)
2015年12月26日土曜日
EGPからログを取り出す方法
SAS Enterprise Guide Projectファイルからログを取り出す方法を調べました。調べてみるといくつか技術的な課題あり、てこずったのでここに記しておきます。EGのバージョンは7.1です。さて、その方法ですが、4種類みつけました。
OLE AutomationからVBSやPowerShellでログを取り出す
この方法は、スケジューリングで出力されるVBSのファイルを開いて、手を加えればできます。しかしながら、クエリ、コードタスク以外のログが取れませんでした。ProjectItemsの中をループで探りましたがランクや転置などデータ加工のタスク、グラフ作成のタスクが捕捉できませんでした。何故かは分かっていませんが、そういう実装なのだと割り切って考えています。
EGのツール、オプションでカスタムコードを書いてログの出力先を変える
proc printtoでログの出力先を変えます。この方法が使えるかと思いきや、クライアント/サーバ構成だとログがサーバ上に出力されて、クライアントPCから参照するためにもう一工夫必要になりあます。サーバ側でログの加工をするのであれば、問題ありません。カスタムのコードを設定する箇所が複数ありますが、使い分けは調べてください。
EGPの拡張子をZIPに変えて、フォルダの中からログを取り出す
元ネタはココの記事です。試してみると、サブフォルダのなかにresult.logがありますので、これをピックアップすればログを抽出できます。サブフォルダの中を見ると、削除されたと思しきタスクの殻フォルダがいくつかあります。ゴミがあるやも知れないので、この方法を使うときには検証をしてください。Non Supportです。
Tools、Options、Application Loggingでログを出力する
元ネタはココです。カスタムコードでproc printtoと似ていますが、サーバが出力するコード以外のログが含まれます。
EGPからログを取り出すときの検討項目を挙げます。
参考まで
- OLE AutomationでVBScriptやPowerShellから取り出す
- EGのツール、オプションでカスタムコードを書いてログの出力先を変える
- EGPの拡張子をZIPに変えて、フォルダの中からログを取り出す
- EGのツール、オプション、Application Loggingでログを出力する
OLE AutomationからVBSやPowerShellでログを取り出す
この方法は、スケジューリングで出力されるVBSのファイルを開いて、手を加えればできます。しかしながら、クエリ、コードタスク以外のログが取れませんでした。ProjectItemsの中をループで探りましたがランクや転置などデータ加工のタスク、グラフ作成のタスクが捕捉できませんでした。何故かは分かっていませんが、そういう実装なのだと割り切って考えています。
EGのツール、オプションでカスタムコードを書いてログの出力先を変える
proc printtoでログの出力先を変えます。この方法が使えるかと思いきや、クライアント/サーバ構成だとログがサーバ上に出力されて、クライアントPCから参照するためにもう一工夫必要になりあます。サーバ側でログの加工をするのであれば、問題ありません。カスタムのコードを設定する箇所が複数ありますが、使い分けは調べてください。
EGPの拡張子をZIPに変えて、フォルダの中からログを取り出す
元ネタはココの記事です。試してみると、サブフォルダのなかにresult.logがありますので、これをピックアップすればログを抽出できます。サブフォルダの中を見ると、削除されたと思しきタスクの殻フォルダがいくつかあります。ゴミがあるやも知れないので、この方法を使うときには検証をしてください。Non Supportです。
Tools、Options、Application Loggingでログを出力する
元ネタはココです。カスタムコードでproc printtoと似ていますが、サーバが出力するコード以外のログが含まれます。
EGPからログを取り出すときの検討項目を挙げます。
- プロジェクトファイル名を取得するか否か
- ログは時系列で取り出す必要があるか
- SASログ以外のログが含まれても良いか
- ログの出力先はローカルのPC、又はサーバ上?
- 抽出するファイルは1本にまとめるか、複数バラバラで良いか?
参考まで
2014年4月22日火曜日
Enterprise Guide 6.1 とVBAの組み合わせでエラー
2012年6月11日月曜日
EGPの中を検索するツール
How to search your SAS Enterprise Guide project files
世の中、考えることは同じなのです。
しかし、インターフェイスの作りが違って面白い。
SRXの公開版を作らねば...
2011年4月12日火曜日
2011年2月16日水曜日
SAS Enterprise Guide 4.3 の便利な新機能, インデント
SASから送られてくるレターの中で、EG4.3の新機能の記事がありました。その中でも評価したいのが、コードを整形、インデントしてくれる機能です。これ、作りたいなと思っていたので、嬉しいような、先を越されて悔しいような気持ちです。マクロの部分がどのようになるのか評価したいです。
SAS Programmer's Paradise: New Goodies in SAS® Enterprise Guide 4.3
他にも、コーディング途中で入力の候補を出してくれる機能があります。ポイント&クリックが売りなのに、こういう部分を強化してくるということは、ハードコードする人のニーズがあるのでしょう。
SAS Programmer's Paradise: New Goodies in SAS® Enterprise Guide 4.3
他にも、コーディング途中で入力の候補を出してくれる機能があります。ポイント&クリックが売りなのに、こういう部分を強化してくるということは、ハードコードする人のニーズがあるのでしょう。
登録:
投稿
(
Atom
)









