The Nameless City

何故か製薬やSAS関連のブログ、の予定。

SASでEXCELを取り込む場合、DDEでファイルを取り込むと、セル内改行文字でぶった切られる件

SAS9.4で確認。


どうにか回避出来ないものかと思って色々考えたんですが、infileステートメントでどうにもtermstrとか指定出来ないですし、別レコード判定がされてしまっているようで。
仕方ないので、改行文字の入っていないセルだけを取り込む形で回避しましたが、どうにも不格好だなあ。


EXCELファイル取り込み、幾つか方法があります。

SAS/ACCESS Interface to PC Files経由
PROC IMPORTでDBMS=EXCELで取り込む方法。SAS/ACCESS Interface to PC Filesのライセンスが必要です。また、SASのbit数とOfficeのbit数が合わない場合には、PC Files Serverを立てる必要があり、かつ、EXCELCSエンジンとか使う必要が出て来ますし、コントロール出来るレベルが変わります。
DDEで取り込む
DDEは古いデータ交換方式で、どちらかというと、動いているアプリケーション間でのデータのやり取りに使われるのですが、廃止されてはいませんが、あんまりセキュアではないです。DDEを使ったExploitはあります。ただ、今でも、Excel文書のリンク機能なんかはDDEで行われたりしているので、完全廃止とかになる可能性は薄いかと思います。


SASのDDE特有かもしれませんが、XWAIT/XSYNCとかをNOにしておかないと、バッチ形式であってもプロセスが停止したりしますね。
このあたりも問題で、Windowsのセッション内でSYNCでない状態で別プロセスでExcelを起動しそこと非同期で実行するのに、不確実なsleep関数を仕込む必要があるとか、ちょっと良くないやり方にはなってます。


Excelのセル内改行の問題は、昔からいろんなアプリで「対応していなかった」のですが、Excelのデータを例えばCSVやTSV(という言い方はあんまり一般的ではないですが、タブ区切りのテキストファイル)に保存して読み込む際でも再現出来ないというオチがあり、ある意味仕方ないのですけど、ですけど。。。。


暇になったらマクロでも作ってみようかと思いますが、多分SAS/ACCESS Interface to PC Filesとかでは回避出来るんじゃないかというのと、そもそもそれはSASで頑張りすぎじゃないか(Excel側でやるのがみんな幸せになれると思います)というので、優先度は低め。

サーバのSAS環境に源ノ角ゴシック Code JPを入れたい。

SASプログラムで、私結構一重引用符使うのですが、
MSゴシックだとこれがカンマと混ざるのが辛い。


源ノ角ゴシックを拡張エディタで使いたいなあと思うのですが、如何せん共有サーバだと厳しいっすなー。
SAS自体に仕込むんじゃなくて、あくまでもエディタ設定に仕込みたいだけなので、悪影響はないと思うんですけどね。
ちょっと話してみたいですが、検証環境がない故に試しにくい見せにくいのが困りものです。

SDTMとかADaM触っててイライラする事

SAS V5 Transport fileの制限ではあるが、

  • 変数名8文字まで

というのが、プログラムにおいて大変質が悪い状況を発生させてる。
変数が認識しづらいし、サジェスト機能を作るにも不便きわまりない。


やっぱまともなプログラマーが設計とかに関係しないとダメですね。

連続性の補正、という言葉について。

直接相談された訳ではないので言ってませんが、メモとして。


この単語が出てきた場合には、
何らかの値が本来は離散値であるにも関わらず、連続値として想定し、連続値用の分布を使って近似する場合で、
ちょっと統計的に有意な差が出ないような側に統計量計算の際、その計算元となる離散値から0.5を減じるという処理を行ってます。
連続性補正 - Wikipedia


メジャーどころではカイ二乗検定イェーツの補正ですね。
この場合には、頻度分布なので離散値なんだけどなー連続値のカイ二乗分布で近似してるよなーという所で、度数の部分で確か0.5減じてたと思います。
位置の検定、順位とか使うやつでも、連続性の補正が発生する事があります。

おまけ

SASでは、NPAR1WAYプロシージャで、PROC NPAR1WAYステートメントでWilcoxonオプションを指定するとWilcoxonスコアというのが計算されますが、単純にVARに指定した順で順位つけてその値を使って計算しています。
「順位」を値としてみなして、それが正規分布だとかt分布だとかに従う事を想定して検定しているだけという、大変簡単な話になってます。
なので、スコアはキレイな数字であり、全体の例数をnとするとn(n+1)/2というのが全スコアの合計になってます。


原義的には正規分布で近似するはずですが、SASではt分布での近似もされる事があります。
この場合、デフォルトではSASは連続性の補正を行っていますが、PROC NPAR1WAYステートメントでCORRECT=NOオプションを指定すると連続性の補正は無しにする事が出来ます。
最近の議論としては連続性の補正ってどうよとかあるかと思いますが、通常は入れとくという話ですね。
ちゃんと指定してくれない依頼者多いと思いますが、最初に「特に指定されていない場合には、SASのデフォルトに従いますよ」的な話つけとくといいかと思います。


なお、このスコアを離散値として正確確率検定を行う事も可能で、EXACTステートメント使う事も出来ます。


Kruskal-Wallis検定は、多群の場合のWilcoxon検定の拡張になります。
正規分布ではなくカイ二乗分布使って検定する訳ですが、
二群の場合には自由度1になるし、Kruskal-Wallis検定の結果とWilcoxon検定の結果(正規分布の方)って一致しますね。

転職しております。

12/1付で某大手電機子会社から、CROの方に転職しました。


リセラーな会社だったので、ライセンスとか使い放題な所があったんですが、次は多分違う。
当面は、SAS Foundation製品触るだけになるだろうなーとは思います。

UTF-8で勘違いしてた事。

wつかないlatin-1領域でも、UTF-8に変換すると非ASCIIの所で2バイトになる。

完全にASCIIなら同じに出来るが、latin-1、wlatin-1なら変換が必要で、

latin-1
最悪二倍
wlatin-1
最悪三倍

だなと。

S-JIS領域での最悪は3倍になる事がある。

半角カナが1バイトから3バイトになるなあ。

US-ASCIIでもlatin-1として変換掛けた方がよい。

何となれば、実際の所、Windowsだったりするとwlatin-1の文字が入力出来てしまう(非ASCII文字を排除しない)。
ブラウザとかでlatin-1指定していてもwlatin-1のイメージで動く。

余談

例えデータセットエンコーディングUTF-8であったとしても、そこに格納されている文字のコードがUTF-8であるという事は全然保証はされてない。
結構どんな言語でもそうで、たまたま上手く変換出来ない文字があったりすると引っかかってくるだけなんだよね。

SASのUTF-8で考える事アレコレ。

簡単ながら。

データセットの内容自体はほぼ対応出来る。

文字の固定長指定を長めにしなければいけないとか色々あるけど、とりあえずは出来る。

問題が残る所がある。

SASのラベルの長さが制限されているが、この為、うっかりすると文字が切れる。日本語で255/3*2=170文字辺り。
ただ、そんなにいるか?というと疑問。「通常は」。

SAS V5 TRANSPORT形式ではヤバい。

SAS V5 TRANSPORT形式(XPORT形式)の場合、古い形式に制限される為、正直困難が有りすぎる。
・文字列長さが200バイトまで
・データセット名が8バイトまで
・変数のラベルが40まで
エンコード情報は持ってくれない
実はこれの拡張のV8形式というのがあるんだが、不思議と流行らない。


何故かというとー、結局文字エンコーディングの情報がないという所があるから。
エンジンもトランスエンコーディングには対応していない。
なお、他の手段ねえかというと、今はXMLエンジン使うという荒業があるが、そんな事するくらいなら案外SASデータセットでいいんじゃないのという話もなきにしもあらず。多分SAS9.3か9.4のシロモノで、あまりテストされてない気もするし、時間かかるよって事だし。

余談

データセットラベルは、元から極力使わない事を推奨しておきます。
プログラムで転がしている最中によく脱落しますし。

トランスエンコーディング、というお話を見て。

namelesscity.hatenadiary.com
SASユーザー総会でも誰ぞの発表ありましたが。

エンコーディング情報がないレガシーデータの地獄。

そんなデータあらへんやろーという人に一つだけ言うと。


SAS V6辺りではエンコーディング情報がデータセットにくっついてませんでしたよね?

XPORT形式の地獄。

なので、SAS V5 TRANSPORT FILEの形式だと、トランスエンコーディングの情報がないんですよねー。
SAS 9とかで見ると、エンコーディングがDefaultとか付いてます。Defaultって何ぞやというと、情報がないので現在のセッションのエンコードを無理矢理当てはめますねというくらいにしか意味はないです。

海外データの実際、あれこれ。

SASの世界の話、ですが。

欧米は大体wlatin-1。

だいたいはそうです。UTF-8であってもおおよそはコード値は同じ。
但し、Windowsでの拡張については問題があり、‡とかは位置が異なったりします。
wlatin-1、正確には、Windows-1252といいます。
Windows-1252 - Wikipedia
古来から使われている標準的な仕様としてのlatin-1ではないです。8x、9x辺りが埋まっているのが特徴。
ISO/IEC 8859-1 - Wikipedia
稀にlatin-9とかもあるらしいですが、SASの世界で多いかは知らないです。扱った事はないです。

日本の場合、SJISEUC-JPが混ざる。

Win系のOSだとSJISなのですが、UNIX系ではEUC-JP。
SJIS、正確には、CP932とか言います。
EUC-JPはそのまんまですね。
ただ、SolarisとかはSJISだった記憶があります。本当のレガシーなデータは、つまり結構日本語環境でも文字コード混ざります。

中国語・韓国語は取り扱ってない。

まず、英語版(wlatin-1)で扱われている事が殆どだと思います。

UTF-8を素で使っているケースは稀。

SAS 9.4くらいでも若干UTF-8の表示には弱い所があるみたい、という憶測があります。
SAS 9.1.3では評価版的な機能でUIが追従してませんでしたし、SAS9.2でもUTF-8モードはデフォルトではなかったと思います。
UTF-8モード、ログウィンドウがなんか表示壊れるんですよね・・・・・・

autodetect&transcodingの方法論

発表へのツッコミみたいになるのちょっとイヤですが。

  • 変換表みたいなのを作成し
  • 変換表に従って実行

みたいな二段階にした方がいいかと思うのと、

  • 文字コード変換のバリデーションも自動化した方がいい

です。


自分が実装したのは、「とりあえず○→UTF8変換、そこからUTF-8→○変換」を、想定しているwlatin-1やsjisの分だけ実行して、「実行が異常終了」「proc compareでの比較確認」という感じでやりました。
autodetectのロジックは作るのが面倒でかつ「フォルダ単位でのエンコーディングは普通同一」というような知見を突っ込んだ方が楽だったので。


なお、個人的には、「そろそろHTAヤバいんじゃないかな」とは思うんですが(そろそろWin10)、他、デフォルトで使えそうなのが結局Excel VBAとかだとちょっと悲しいですよね。
けど、Electronとか面倒くさそうだしなあ・・・・・・あの適当さを代替するものって、ナカナカないですよねえ・・・・・

文字コード変換後の実際の長さの検出

最初に、CVPMULT=3とかにしておいて、後で実際の長さに詰める、という事は全然出来るのですが、SASデータセットの場合、油断するとMEMLABELが削れたりFORMATが削れたりするので注意です。SDTMとかはFORMAT要らんですが。
ただ、変換再度あるので面倒だし、COMPRESSオプション使った方が幸せなんじゃないかと思います。

ラベルの変換、変数名やテーブル名の変換

ラベルの最大長が256バイトの為、SJISでダラダラ付けられたラベルは変換すると切れると思った方がいいです。
まあSDTMの場合には変数名やテーブル名の問題も発生しませんが、これ拡張使ってダブルバイトの変数名とか付けてると、これもまた切れます。

独自に作成したアプリケーションのバリデーションはどうするか。

「逆変換して、元のデータセットと比較して確認した」というやり方をした事があります。ただ、結局の所、そのまま申請データとして用いた訳ではなく、多分プロトコル毎にチェックはされているはずです。
そういう形で逃げられない場合にはどうしましょうねえという所は悩みどころ。

プログラムの文字コード変換の場合は、「大変です」。

Windowsでやろうとすると、APIとか叩くプログラム作ったりするのも出来はするんですが。
ただ、逆変換含む比較が難しいというか、「文字として読み込んで、改行文字は適宜CRLFとLFは同じものとして比較」とかありがちなんですよね。
Git適用とか考えておられるならば、改行文字はLFに統一して下さい、とか言いたいんですが、SASのDMSでは改行コードとか指定して保存出来ないかなーと思ったりもします。

立派な客よりマトモな客求む。

もう、あのシステム保守自体切りたいんだけどマジで。


某製薬会社向けの受託開発やったのおそらく十年は前。
システム綺麗にしましょうとかバージョンアップさせましょうとか延々と伸ばされ提案は却下され、保守費用も月数時間とお客さん環境に接続する為のe-Learningやパスワード変更分くらいしかないし。
まあ、それでも理屈にあった事ならまあ仕方ねえなあとは思ってたけど。


出力帳票の全パターン設計に書け、とか言われて正直モチベーションダダ下がりです。
いや、出力に影響するパラメータ複数をわざわざマトリクス化して、「ほらちゃんとそれぞれのパターン網羅してるでしょ」とか書いてたのに、「設計書にはそもそも全て載せるべき」みたいな事を言ってくるんだからもうどうしようもないね。


はあ、ホント何で客のプロジェクトオーナー余所に行っちゃったんだろう。残された人はつらいわ(システム開発してた前任者の先輩は、もう亡くなってるってのもある)。


ある意味、こういう信頼関係の阻害が、システムを遺産化していくんだろうなあとは思うんだよ。ずーっと面倒見てたらそら幾らなんでも「古いXPマシンが必要」とかにはなってねえしなあ。


ああうんざり。


何だろうねえ、名前が通っている会社ほど非人道的な事するし、正直頑張る気がせん。
東京勤務だったらマジで転職してただろうなあ。まあ、大阪でも転職出来なくはないけど、面白味にはかける。


でもなー、データ利活用とか統計だーとかの人って、大体はろくでもないんだよなー。あったら便利程度の道具にしか思ってない。そもそも日本の情報システム部の評価は低いし、コストとしか思ってないからねえ情報システムを。
とにかく安く安く。


AWSだって、「安く」しか見てないでしょ。
そうじゃねえ、「情報システムにはドンドンカネかけてくもんだ」って意識ない。AWSにレガシー如何に載っけるかとか、如何に古いシステムを延命させるかとか、そんなニーズしか日本にはないから、SIerとかの仕事が全般的に腐っていってるだけなんだ。
あまりにも「そんな腐ったユーザを見捨てなかった」業界も悪いんだけどさ。


そろそろ、情報システム側が、三行半突きつけていいと思うんだよねえ。

縛りプレイでの、Phoenix Framework環境構築。

環境の縛り

  • 認証つきProxyで外部環境に繋がる。
    • ユーザIDには「@」を含む。
  • Windows上。

Phoenix Frameworkのインストールガイド

www.phoenixframework.org

必要なアプリ・モジュール

Elixir

そりゃElixirで動くFrameworkだからなあ。

Hex

Erlangのライブラリ管理ツール。

Phoenix

Phoenix Framework本体。Installの所と違ってここに位置付けたのは、単にツリー構造上の話です。Elixirのパッケージだから。
ただ、このインストールの方法では特にHexを使ってインストールしている訳ではない。

Erlang

そりゃElixirはErlangVMで動くからなあ。

Plug, Cowboy, and Ecto

Phoenix Frameworkが必要とするElixirやErlangのパッケージ。中身は今の段階では分からず。
同じVMだからもあるけど、ElixirからErlangのパッケージなんかは利用しやすいようで。
Phoenix入れたら勝手に入るらしい。

node.js (>= 5.0.0)

Phoenix Frameworkではデフォルトではbrunch.ioとかで画面の静的アセット作るらしい。画面はよう分からんが、他に切り替えるほどのノウハウ持っている訳もないので入れておく。

PostgreSQL

裏にDBもつものらしい。うーん、Webアプリから利用するデータおく為のもの?な位置付けでいいのか?
よく知らん。

インストー

Elixirインストー

公式インストーラーで問題なし。
・・・・・・と言いたいがそのままではmixが上手く動かない。後述。

Erlangインストー

問題なし(Elixirと共に入る)。

node.jsインストー

インストール自体は問題ないが、やっぱLinuxベースアプリという事で、Proxyが上手く通らない。
Proxyの設定が必要。

npm -g config set proxy "http://<proxy username>:<proxy password>@<server>:<port>/"
npm -g config set https-proxy "http://<proxy username>:<proxy password>@<server>:<port>/"
npm -g config set registry "http://registry.npmjs.org/"
npm -g config set strict-ssl=false

ユーザ名やパスワードにURIエンコーディングが必要。
試しにbrunch.ioをインストールして通る事は確かめた。
・・・・・・重い。

PostgreSQLインストー

本体は問題なし。psqlodbc入れるStackBuilderが動作しない。Proxy設定を上のように入れてみても上手くいかないので諦め。
psqlodbcを手動で導入した。
postgresユーザのパスワードが、Phoenix Frameworkではpostgresなので苦労しないように一応そうしておく。
・・・・・・良くないです。

Windows版だと、デフォルトでPostgreSQLのそのDB起動周りもサービスとして登録されます。
デフォルトのポート番号は「5432」。

hex導入のmixコマンド

そのままでは動作しない。Proxy設定する所もない。
・・・・・・環境変数http_proxy、https_proxyを設定すればその設定を読んでくれるというのをソースから推測して入れる。
但し、npmの設定と異なり、URIエンコーディングは不要だった。何か他のエスケープ文字あったりする?
他のアプリの設定と一致しないので、ちょっと考えて、mix.batに以下二行を先頭に追加。

@set http_proxy=http://<proxy username>:<proxy password>@<server>:<port>/
@set https_proxy=http://<proxy username>:<proxy password>@<server>:<port>/

これで、「mix local.hex」は成功する。mixコマンド経由ではとりあえずプロキシ通る。

Phoenix導入

「mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez
です。
上が通れば出来るはず。

skeleton試してみる(mix phoenix.new --no-brunch --no-ecto&mix phoenix.server)

プロジェクトの置き場に行って

mix phoenix.new <project name> --no-brunch --no-ecto

する。
すると、のフォルダが出来て、その下にPhoenixのテンプレートがコピーされる。
「Fetch and install dependencies?」と聞かれてYを選択すると、その後に、mix deps.getが実行されて、依存関係のあるモジュールも落ちてくる。

cd <project name>
mix phoenix.server

で、フォルダ配下のElixirのファイルがコンパイルされて、サーバが動く。

普通にプロジェクト作ってみる(mix phoenix.new)

プロジェクトの置き場に行って

mix phoenix.new <project name> --no-brunch --no-ecto

する。
Phoenixのテンプレートがコピーされるまでは一緒(但しモジュールが増えてる)。
ただ、先の質問でYを答えると、mix deps.getの後に、

npm install && node node_modules/brunch/bin/brunch build

が実施されている。これが遅い。

これで、package.jsonの内容をインストールしているらしい。
んだが、クソ重い。なんだこれ。
まあ、他にCPU使ってるのもあるんだけど・・・・・・

多分、前のDISのは、当面直らないんではと思う。

namelesscity.hatenadiary.com
あれからも、このバグって簡単かねえと思いながら見てたのですが、
そういや、
Oracleの場合二重引用符で列名を指定する事が出来た
なと。
SASは名前リテラル('~'n)というのを持っているので二重引用符と一重引用符の使い分けなしに(この使い分けは、SASはマクロ言語の所で使ってしまっている)なんとかなりますが、SQLとして標準化されていくものとしてこんなの使われる訳ないよねと。


PROC SQLステートメントのオプションに、DQUOTE=オプションがあり、ANSISASどちらかで指定出来るのですが、ANSIで設定すると二重引用符で列名を記載する事が出来ます。SASの場合には、これは文字リテラルであるなと認識されます。
つまり、そういう細かいオプションに判定アルゴリズムが引きずられるので、多分問題になるかと思います。
PROC SQLも古いプログラムですしね。SAS/ACCESS Interfaceあたりにも影響するはずの為、ちょっと簡単ではないと思われます。


なお、FEDSQLというのが出てますが、イマイチ使い勝手は分かっていません。

意外と知られていない、データセットの指定方法。

ネタ用のソース。

手持ちのSASで試して見て下さい。
しかし、SAS On Demandの場合にはこれで動くかはやってないので正確な所は分かりませんが多分出来ないです。SAS University Editionも同様で、SAS Integration Technology上に乗っかってるのでは、XCMDが無効化されているので、データ作成とかCDとかが多分無理。
(XCMD/NOXWAIT/XSYNCが望ましいです)
WORKライブラリの配下であればフォルダもありますが、他、システムオプションが権限コントロールされているので無理かなとも思います。

** 下のテスト用のフォルダは、自分の環境に合わせて適宜変更して下さい ** ;
%let _FLD=C:\Workspace\tmp ;
%let _DR=C: ;
/*
念の為。
Windows環境下では、UNCパスでは最後のCDコマンドが動かないので注意
*/

** テストデータ一次作成 ** ;
libname TEST base "&_FLD." ;


data  TEST.CLASS ;
	set SASHELP.CLASS ;
	attrib MEMO length=$20. ;
	retain MEMO ;
	if _N_ = 1 then MEMO='demo用データ' ;
run ;

** このライブラリ設定がクリアされていない場合には、そのライブラリを使いにいく ** ;
libname TEST clear ;

title '**フルパス指定**' ;
title2 '**こんな指定の仕方で大丈夫か**' ;
footnote '**問題ない**' ;
proc print data="&_FLD.\class.sas7bdat" ;
quit ;

footnote ;


title '**定義情報**' ;
proc contents data="&_FLD.\class.sas7bdat" varnum out=_wk_def;
quit ;

title '**定義情報** ライブラリが自動設定されている...WC<連番>という形で定義される' ;

proc print data=_wk_def ;
quit ;

title '**ライブラリ定義(SAS...以外)...WC<連番>という形で定義される**' ;
proc print data=SASHELP.VLIBNAM ;
	where LIBNAME not like 'SAS%' and LIBNAME not like 'MAP%' and LIBNAME ^= 'WORK' ;
quit ;

** 自動割当されたライブラリを一旦クリアしておく ** ;
%let _w_lib = ;
proc sql noprint ;
	select LIBNAME into : _w_lib from SASHELP.VLIBNAM
	where LIBNAME not like 'SAS%' and LIBNAME not like 'MAP%' and LIBNAME ^= 'WORK' ; 
quit ;

data _null_ ;
	attrib LIB length=$10. ;
	LIB = symget('_w_lib') ;
	if not missing(LIB) then do ;
		call execute(catx(' ','libname', LIB,'clear ;')) ;
	end ;
run ;


**もしかしてこれファイル名変なのにしても大丈夫?** ;
title '**EXTEND指定の場合のSASデータセット名制限の緩和**' ;
option validmemname=extend ;


data "&_FLD.\1_class.sas7bdat" ;
	set "&_FLD.\class.sas7bdat" ;
run ;


title2 '**こんな指定の仕方で大丈夫か**' ;
footnote '**問題ない**' ;
proc print data="&_FLD.\1_class.sas7bdat" ;
quit ;
footnote ;


**名前リテラルを使うパターン** ;
title '**名前リテラル指定**' ;
libname TEST base "&_FLD." ;

title2 '**こんな指定の仕方で大丈夫か**' ;
footnote '**問題ない**' ;
proc print data=TEST.'1_CLASS'n ;
quit ;
footnote ;


**実はこんな酷い事がwww** ;
options xsync ;
x "cd ""&_FLD.""" ;
x "&_DR." ;
/*
念の為。cd /d ...のコマンドはSASは理解しない為、
/d つけると失敗します。
*/
title '**相対パス指定**' ;
title2 '**こんな指定の仕方で大丈夫か**' ;
footnote '**問題ない**' ;
proc print data='1_class.sas7bdat' ;
quit ;

データセットの指定方法の簡単な説明。

普通のやり方。

「<ライブラリ名>.<データセット名>」ですよね。
因みに、ライブラリ名を省略した、「<データセット名>」の場合、WORKライブラリ配下に作成される

のが普通なのですが、実はUSERシステムオプションに従う事になってます。そのデフォルトがWORKです。
ただ、このオプション、キリキリ切り替える人ってそういないと思います。設計時点で仕込めば問題ないんですが。
そういう言語仕様なので、SASのソリューションで自動生成されるプログラムではまずライブラリ名は省略されてないと思います。

パス指定。

引用符で囲む事によって、「パス指定でデータセットとして認識させられる」んです。


これ、面倒臭いだけじゃんとか思われるかとも思いますが、ライブラリ設定をしなくても済むってのが利点で、勝手にBASEエンジンのライブラリが定義されてその下に出来ているように見えます。


ただ、この仕様ちょっと厄介で面白い所もあります。
'c:\workspace\tmp\class'で指定→「c:\workspace\tmp\class.sas7bdat」で作成。
'c:\workspace\tmp\class.dat'で指定→有効ではない拡張子が指定されているとしてエラー。


つまり、パス指定と言えども、実際には「ライブラリの自動登録と、データセット名の推論」で動いているかと思われます。
これ、

data CLASS ;
    set SASHELP.CLASS ;
run ;
data 'CLASS' ;
    set SASHELP.CLASS ;
run ;

どちらでも大抵はclass.sas7bdatファイルが出来るのです。
「ライブラリが省略された場合に補完される」のは通常「WORKライブラリ」なので、そこに出来るのですが、
相対パス指定」の場合には通常SAS起動時に設定されている作業フォルダ(カレントディレクトリ)なので、素のSAS起動直後では「%userprofile%」(C:\Users\)に出来ます。

SASの各種ツールはSAS構文全てに対応している訳ではない、例としてのDISの変な挙動の話。

DISのマッピングで出てる警告について聞かれたのですが。


DISにはDISに食わせる為の書き方というのがあって、例えソースが一種類であっても、「テーブル.列名」という記述をする必要があったんじゃないかと記憶しているのです。
面倒臭いなと思ったら生SASを書いてしまう人なので、実はあんまりDISのTransform(SASの日本語マニュアルで「変換」って書かれますけど、これ用語として良くないですよねー)を使わないのですが、DISのTransformでどこまで警告消せるかっての試してた事がありまして、その経験値になります。
DISのTransformって、結構マニアックな所までGUIで出来てしまうんですが(サブクエリも書けます)、画面のオブジェクトをクリックした中に入れ子を作っていくのは結構問題あるなーと思って、出来るだけJOINでなんとかする書き方を考えたり、色々悩む事はあります。


話戻しまして、SASのエンジンが理解出来る構文が、その実ラッパーであるDISが理解出来るかというとこれが案外理解できず困るという事は多々あります。
また、データの持ち方として、「列とはテーブルを親に保つもの」というオブジェクトが想定されているのもあるでしょう。多分。
余談ながら、式ビルダもホントイケてないから問題なんですよねえ。
Transformも複雑なものだと案外「こういう使い方するもの」ってのは、想定と違ったりするので。
自分でやる際には、殆ど生SASSQL結合使いかですねえ。


うんまあ、SQLでビュー作ったの繋いでいくよりも、生SASでビュー繋いでいく方が正直早い気がするんですよね。


ダラダラと前フリしましたが、以下、まあこういう事があるよという例です。
ちなみに、これが発生するのは、SAS DIS4.901で確認しております。

f:id:houyhnhm:20170516170009p:plain
はい、この原因は、多分文字リテラルと変数名が被っちゃっててなんだろうと思います。
因みに、データは、SASHELP.CLASSからの流用です。
f:id:houyhnhm:20170516170026p:plain
実行すると警告は出ますが、
f:id:houyhnhm:20170516170036p:plain
データについては特に問題はないです。マッピングの紐付けのメタデータがイマイチイケてないだけです。
f:id:houyhnhm:20170516170102p:plain
人力で「テーブル名.」を補完してやります。
f:id:houyhnhm:20170516170116p:plain
補完した文字は消えますが、警告マークが取れます。
f:id:houyhnhm:20170516170131p:plain
実行しても警告は出ないようになりました。


単純にDISのマッピング判定のロジックがイケてないって事だと思いますが。
直らん上に結局仕様(警告マーク無視して)とか言われかねないので、まあ下策ですがこんな形でこのジョブ上のTransformの中身を作ってやる、と。
これ出来ないと、開発系から本番系へのお引っ越しなんかの時に、テーブルの紐付けどうやって確認したらいいんだという話になりかねないので(警告マークが信用出来なくなるから簡単でなくなる)こういう対応もありかなという所です。
所詮はプログラムのエディタだと割り切った方が良いです。


一応似たようなケースでのエラーでProbrem Noteは出ていて、その中では「Warning抑止するオプションを設定」でした。
52167 - A warning occurs on the Mapping tab when you join a table with itself via aliases in SAS® Data Integration Studio
うんまあ酷いな。
今のDISでも出てますが、警告ない状況でセーブして再度開くと警告になるという、大変タチの悪い状況です。ただ、同一テーブルをソースにしてのJOINとかはまずやらんと思いますが。
報告されてるエラーの回避策として、「どちらか一個にTransformかますと大丈夫」だったりします。要は同名テーブルだがエイリアス設定があるみたいなのが上手くいってない所なので、ビューとして別物に仕立てると大丈夫だったり。
同様にして、「変数名を変えておく」のが一番マシな回避策かも知れない。

余談

SASのバージョンによって挙動が変わったりする所があるかと思います。ご注意下さい。
特にこの辺りSASの正式ドキュメントはないので申し訳ないですが表立って回答として出せない為、無責任な状況でご提示しておくものです。
なんとなく察して下さいお願いします。
お引っ越しに関しても大丈夫かどうか確認してませんのでよろしくお願いします。

COMPRESS=オプションの活用。

実は、V6時代から存在するけど、その実あまり使われていないような気がするオプションですが、
パフォーマンス等にメチャクチャ影響するので、適度に使う事を推奨したいオプションです。
個人的にはCOMPRESS=YESってデフォルトでもいいと思うんですけどね。

使い方幾つか。

個々のデータセットに使う方法。

data CLASS(compress=yes) ;
    set SASHELP.CLASS ;
run ;

こんな感じです。この場合には、全く圧縮率は上がりませんが。

ライブラリに定義しておく方法。

libname TEST base "C:\test" compress=yes ;

こちらは、「今後TESTライブラリ配下に作成される際に参照され」、ライブラリ配下のデータセットが圧縮して作られます。
COPYプロシージャなどでコピーする際には原則として適用されないと思った方がいいです(多分オプション駆使したらいいんだろうけど)。

システムに定義しておく方法。

options compress=yes ;

このステートメントが実行された後、「全てのBASEエンジンでのデータセットを作成される際に参照され」、圧縮して作られます。
但し、基本的にはセッション毎に保持されるものと思って下さい。sasv9.cfgなどで設定ファイルに設定した場合には、全てのセッションに反映されます。
SAS実行用のサーバを構成している場合には、Workspaceサーバ等だけに適用する方法、SASApp配下全体に適用する方法などで設定ファイルを弄る事を推奨します。Metadataサーバに適用してしまっても多分意味がない・下手するとパフォーマンスちょっと悪化するので。

圧縮のロジック・影響

個々の変数に対して連長圧縮という事をします。
その為、適用されても必ずサイズが小さくなる訳ではありません。
連長圧縮 - Wikipedia
圧縮効率は悪いですが、極めて単純なロジックの為、CPU負荷はあまりありません。ディスクI/O待ちがかなり多いSASの場合にはかなり有利なロジックではあります。


以下イメージ。
CSVファイル

abcdefghi,,abcdefghi,
,abcdefghi,,

SASデータセットイメージ(定義の部分とかで大きめなヘッダがついてますが、大体イメージです)

abcdefghi,_________,abcdefghi,_________
_________,abcdefghi,_________,_________

SASは、固定長文字列としてデータを保持する為、COMPRESSオプション指定なし、デフォルトのNOである状況では、定義の長さまでデータを半角スペース(0x20)で埋めます。
定義の長さまでデータが埋められてない、欠損値が多い(SASではRDBのNULLのようなものを欠損値と表現します。厳密にはRDBのNULLとは異なり、型としては数値型・文字型両方あります)場合には、この「ただ埋める為だけの半角スペースが多い」ので問題になります。
このせいでCSVのサイズとSASデータセットのサイズも比例しづらいです。

余談

SASの固定長文字列型というのは、これ今後も変わらないと思います。
2000年代でも既に珍品の域だったと思いますが、ただ、どんなプラットフォームでもそこそこ高速に動くのはこの辺りの仕様です。
メモリ消費量が案外小さいのもそうで、ただ、プロセス起動が重い(イチイチフォルダ作って物理実体を作業スペースでも作ってしまう)のも問題ではあるんですが。
プロセス起動のネックになっているWORKライブラリは、MEMLIB等の設定がありますので、高速化考えているならば検討の余地はあります・・・・・・が、結局の所、SSDより大容量なメモリを抱えている訳でもないので・・・・・・パフォーマンスチューニングは厄介ですねえ。
固定長文字列型というのの利点は、ディスクのページサイズと合わせる事によって、変なディスクキャッシュをかまさなくて高速に動く所、ですかね。

余談:SAS EGでのやり方

データインポートのタスクにデータセットオプションを指定する方法はどうも簡単にはなさそうなので、システムオプションを変更するプログラムを作り、上記タスクの前に実行するようにフローを作った後、まとめて実行する方法が良さそうです。
注意として、一度システムオプションで変更するとセッション中はずーっと圧縮かけるように設定されてしまう為、必要があれば解除するようシステムオプションを再度設定しなおすという事も行って下さい。
ただ、一点ツッコミ入れておきますが、データインポートでは、EGからサーバへ平文のCSVが転送されます。その手の変換はサーバ内でDISや生SAS使うのが妥当です。

レガシーシステムの規制当局申請用データ変換の不毛さ。

時代遅れでかつデザインもイケてないフロントを何故ひたすら抱えさせるのか意味不明であるし、
データ移行を楽にする為なのか、内部構造ももう消費期限過ぎているのに無理矢理延命させる意味も分からん。
オマケに、元々の内部構造が、正規化されてないので拡張にイチイチalter tableする必要があるって頭が悪いとしか思えない。


そもそも、データの履歴含めて保持する必要があるシステムのはずが、そこの時点でリファクタリングや作り直しをやれてない時点で、開発当初から失敗するのが目に見えてる。
それに気付かず計画を進めるような人材が大量にいる時点で終わってるのだけど、何故そのグタグタなものをシステムで作り上げようとするのか意味不明である。


お前らいい加減Part11理解しようよ。データのトレーサビリティ要求されんの近年の重めなシステムでは当たり前でしょうが。
チョロチョロっとデータ加工して弄る、みたいな事しても仕方ねえんだよ。
もうお前ら馬鹿なんじゃないかと繰り返し怒鳴りたくなる。


そんなパッケージでもそれなりの売上が出てしまう所が、大手SIerの問題だろうなあ。
文句言わなければそこに寄生して食ってける。


ああ、いい加減綺麗な新規開発したい。現在販売中のパッケージだって、これ、中身は二十年前とか余裕な時代遅れのシステムで、完全に技術的負債になってるのに偉いさんは金の卵のように扱うんだ。
ホントうんざりする。