mirror of
https://github.com/yabwon/SAS_PACKAGES.git
synced 2026-01-07 15:10:04 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ff8fd506c | ||
|
|
7be17a3a57 | ||
|
|
e2e54b8025 | ||
|
|
cdf07fc232 | ||
|
|
bcbd078b7d | ||
|
|
c12260fdcd | ||
|
|
b45b79fd3c | ||
|
|
2ce8a83499 | ||
|
|
59cda13330 |
15
README.md
15
README.md
@@ -21,7 +21,7 @@ Short description of the SAS Packages Framework macros can be found [here](https
|
|||||||
- [SAS Global Forum 2020 V.E.](https://www.youtube.com/watch?v=qCkb-bx0Dv8&t=0s "SGF2020") (April 2020)
|
- [SAS Global Forum 2020 V.E.](https://www.youtube.com/watch?v=qCkb-bx0Dv8&t=0s "SGF2020") (April 2020)
|
||||||
- [Sasensei International Dojo](https://www.youtube.com/watch?v=BFhdUBQgjYQ&t=0s "SID no. 1") (April 2020)
|
- [Sasensei International Dojo](https://www.youtube.com/watch?v=BFhdUBQgjYQ&t=0s "SID no. 1") (April 2020)
|
||||||
- [SAS dla Administratorów i Praktyków 2020](https://www.youtube.com/watch?v=mXuep2k48Z8&feature=youtu.be&t=0s "SASAiP2020") (October 2020, in Polish)
|
- [SAS dla Administratorów i Praktyków 2020](https://www.youtube.com/watch?v=mXuep2k48Z8&feature=youtu.be&t=0s "SASAiP2020") (October 2020, in Polish)
|
||||||
- [Boston Area SAS Users Group webinar](https://us02web.zoom.us/rec/share/p6ZpCsvc5YZDQGpLOOLOB4zyNGA4vjfjJcNhwaGQ7jKKR00Z_bmeCcBkcwkut6Pr.Q6UoueYAOcv6dPQf "BASUG") (November 2020)
|
- [Boston Area SAS Users Group webinar](https://www.basug.org/videos?wix-vod-video-id=78067e61413d43d3a6951974b3bc3014&wix-vod-comp-id=comp-klv807gt "BASUG") (November 2020)
|
||||||
- [SAS Global Forum 2021 V.E.](https://www.youtube.com/watch?v=hqexaQtGw88 "SGF2021") (May 20th, 2021)
|
- [SAS Global Forum 2021 V.E.](https://www.youtube.com/watch?v=hqexaQtGw88 "SGF2021") (May 20th, 2021)
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ SHA256 digest for macroArray: 849629D3AF3FE3AB45D86990E303F1D5E4D5F9F31C8ED6864C
|
|||||||
[Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/macroarray.md "Documentation for macroArray")
|
[Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/macroarray.md "Documentation for macroArray")
|
||||||
|
|
||||||
|
|
||||||
- **BasePlus**\[0.991\] adds a bunch of functionalities I am missing in BASE SAS, such as:
|
- **BasePlus**\[0.993\] adds a bunch of functionalities I am missing in BASE SAS, such as:
|
||||||
```sas
|
```sas
|
||||||
call arrMissToRight(myArray);
|
call arrMissToRight(myArray);
|
||||||
call arrFillMiss(17, myArray);
|
call arrFillMiss(17, myArray);
|
||||||
@@ -158,10 +158,19 @@ format x bool.;
|
|||||||
|
|
||||||
%put %getVars(sashelp.class, pattern = ght$, sep = +, varRange = _numeric_);
|
%put %getVars(sashelp.class, pattern = ght$, sep = +, varRange = _numeric_);
|
||||||
```
|
```
|
||||||
SHA256 digest for BasePlus: A321A4BC54D444B82575EC5D443553A096557AD69DC171D578A330277E67637A
|
SHA256 digest for BasePlus: 5EAEF846754F19759C0492308478417C9667C9651F1EF14F70E4FF8AB4C857F6
|
||||||
|
|
||||||
[Documentation for BasePlus](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md "Documentation for BasePlus")
|
[Documentation for BasePlus](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md "Documentation for BasePlus")
|
||||||
|
|
||||||
|
- **GSM** (Generate Secure Macros)\[0.14\], package allows
|
||||||
|
to create secured macros stored in SAS Proc FCMP functions.
|
||||||
|
The dataset with functions can be shared between different operating systems
|
||||||
|
and allows to generate macros on site without showing their code.
|
||||||
|
|
||||||
|
SHA256 digest for GSM: 93D88D4465B68984E938212241DE55C7B12EBC20601538553AC9E1AC0628C006
|
||||||
|
|
||||||
|
[Documentation for GSM](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/gsm.md "Documentation for GSM")
|
||||||
|
|
||||||
- **dynMacroArray**\[0.2\], set of macros (wrappers for a hash table) emulating dynamic array in the data step (macro predecessor of DFA)
|
- **dynMacroArray**\[0.2\], set of macros (wrappers for a hash table) emulating dynamic array in the data step (macro predecessor of DFA)
|
||||||
|
|
||||||
SHA256 digest for dynMacroArray: 67956116578E71327748B7EB3DAFF9D872DBC6F6EDD0DC11B7CF2A54FDA71785
|
SHA256 digest for dynMacroArray: 67956116578E71327748B7EB3DAFF9D872DBC6F6EDD0DC11B7CF2A54FDA71785
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ SHA256 digest for macroArray: 849629D3AF3FE3AB45D86990E303F1D5E4D5F9F31C8ED6864C
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
- **BasePlus**\[0.991\] adds a bunch of functionalities I am missing in BASE SAS, such as:
|
- **BasePlus**\[0.993\] adds a bunch of functionalities I am missing in BASE SAS, such as:
|
||||||
```sas
|
```sas
|
||||||
call arrMissToRight(myArray);
|
call arrMissToRight(myArray);
|
||||||
call arrFillMiss(17, myArray);
|
call arrFillMiss(17, myArray);
|
||||||
@@ -104,12 +104,23 @@ format x bool.;
|
|||||||
|
|
||||||
%put %getVars(sashelp.class, pattern = ght$, sep = +, varRange = _numeric_);
|
%put %getVars(sashelp.class, pattern = ght$, sep = +, varRange = _numeric_);
|
||||||
```
|
```
|
||||||
SHA256 digest for BasePlus: A321A4BC54D444B82575EC5D443553A096557AD69DC171D578A330277E67637A
|
SHA256 digest for BasePlus: 5EAEF846754F19759C0492308478417C9667C9651F1EF14F70E4FF8AB4C857F6
|
||||||
|
|
||||||
[Documentation for BasePlus](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md "Documentation for BasePlus")
|
[Documentation for BasePlus](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md "Documentation for BasePlus")
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
- **GSM** (Generate Secure Macros)\[0.14\], package allows
|
||||||
|
to create secured macros stored in SAS Proc FCMP functions.
|
||||||
|
The dataset with functions can be shared between different operating systems
|
||||||
|
and allows to generate macros on site without showing their code.
|
||||||
|
|
||||||
|
SHA256 digest for GSM: 93D88D4465B68984E938212241DE55C7B12EBC20601538553AC9E1AC0628C006
|
||||||
|
|
||||||
|
[Documentation for GSM](https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/gsm.md "Documentation for GSM")
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
- **dynMacroArray**\[0.2\], set of macros (wrappers for a hash table) emulating dynamic array in the data step (macro predecessor of DFA)
|
- **dynMacroArray**\[0.2\], set of macros (wrappers for a hash table) emulating dynamic array in the data step (macro predecessor of DFA)
|
||||||
|
|
||||||
SHA256 digest for dynMacroArray: 67956116578E71327748B7EB3DAFF9D872DBC6F6EDD0DC11B7CF2A54FDA71785
|
SHA256 digest for dynMacroArray: 67956116578E71327748B7EB3DAFF9D872DBC6F6EDD0DC11B7CF2A54FDA71785
|
||||||
|
|||||||
@@ -1,3 +1,24 @@
|
|||||||
|
/* 20211001 */
|
||||||
|
BasePlus: 5EAEF846754F19759C0492308478417C9667C9651F1EF14F70E4FF8AB4C857F6
|
||||||
|
|
||||||
|
/* 20210908 */
|
||||||
|
GSM: 93D88D4465B68984E938212241DE55C7B12EBC20601538553AC9E1AC0628C006
|
||||||
|
|
||||||
|
/* 20210818 */
|
||||||
|
BasePlus: C9D26CAC2504634EF25F02B5BD04596B2F873E3C25E8CEDDD7F496A78B184E9F
|
||||||
|
|
||||||
|
/* 20210726 */
|
||||||
|
GSM: 2FC239B5A2216D073826125999BFD64FBA32BFEA3EE6EA2B22EC64E8C1B04144
|
||||||
|
|
||||||
|
/* 20210722 */
|
||||||
|
GSM: 311BCF510B7B189AE9A75C56C4D2F99F844114CC5AD32329FAD690BA1F10422A
|
||||||
|
|
||||||
|
/* 20210719 */
|
||||||
|
GSM: 4322D79C382B9D58EF5E51AFD0856331F8B38B1B35AC21295DADFC43F81B2AF8
|
||||||
|
|
||||||
|
/* 20210716 */
|
||||||
|
GSM: 7134C8672023972BA0D5D5CE1E611F0DBB5F60ADAE847BC59C94FF7E2BEC0278
|
||||||
|
|
||||||
/* 20210528 */
|
/* 20210528 */
|
||||||
BasePlus: A321A4BC54D444B82575EC5D443553A096557AD69DC171D578A330277E67637A
|
BasePlus: A321A4BC54D444B82575EC5D443553A096557AD69DC171D578A330277E67637A
|
||||||
DFA: 22AB51B85E3344B8C0FB7AF164247881B656F5CBA88BBA974AD8BC41ED79327F
|
DFA: 22AB51B85E3344B8C0FB7AF164247881B656F5CBA88BBA974AD8BC41ED79327F
|
||||||
|
|||||||
@@ -41,12 +41,15 @@
|
|||||||
* [`semicolonN()` function](#semicolonn-function)
|
* [`semicolonN()` function](#semicolonn-function)
|
||||||
* [`%zipEvalf()` macro](#zipevalf-macro)
|
* [`%zipEvalf()` macro](#zipevalf-macro)
|
||||||
* [`%QzipEvalf()` macro](#qzipevalf-macro)
|
* [`%QzipEvalf()` macro](#qzipevalf-macro)
|
||||||
|
* [`%functionExists()` macro](#functionexists-macro)
|
||||||
|
* [`%RainCloudPlot()` macro](#raincloudplot-macro)
|
||||||
|
|
||||||
|
|
||||||
* [License](#license)
|
* [License](#license)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# The BasePlus package [ver. 0.991] <a name="baseplus-package"></a> ###############################################
|
# The BasePlus package [ver. 0.993] <a name="baseplus-package"></a> ###############################################
|
||||||
|
|
||||||
The **BasePlus** package implements useful
|
The **BasePlus** package implements useful
|
||||||
functions and functionalities I miss in the BASE SAS.
|
functions and functionalities I miss in the BASE SAS.
|
||||||
@@ -61,7 +64,8 @@ Kudos to all who inspired me to generate this package:
|
|||||||
*Mark Keintz*,
|
*Mark Keintz*,
|
||||||
*Paul Dorfman*,
|
*Paul Dorfman*,
|
||||||
*Richard DeVenezia*,
|
*Richard DeVenezia*,
|
||||||
*Christian Graffeuille*.
|
*Christian Graffeuille*,
|
||||||
|
*Allan Bowe*.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -176,55 +180,66 @@ Kudos to all who inspired me to generate this package:
|
|||||||
%put &=x;
|
%put &=x;
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**Example 9**: Simple Rain Cloud plot.
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%rainCloudPlot(sashelp.cars,DriveTrain,Invoice)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Package contains:
|
Package contains:
|
||||||
1. macro deduplistc
|
1. macro deduplistc
|
||||||
2. macro deduplistp
|
2. macro deduplistp
|
||||||
3. macro deduplists
|
3. macro deduplists
|
||||||
4. macro deduplistx
|
4. macro deduplistx
|
||||||
5. macro getvars
|
5. macro functionexists
|
||||||
6. macro qdeduplistx
|
6. macro getvars
|
||||||
7. macro qgetvars
|
7. macro qdeduplistx
|
||||||
8. macro qzipevalf
|
8. macro qgetvars
|
||||||
9. macro symdelglobal
|
9. macro qzipevalf
|
||||||
10. macro zipevalf
|
10. macro raincloudplot
|
||||||
11. format bool
|
11. macro symdelglobal
|
||||||
12. format boolz
|
12. macro zipevalf
|
||||||
13. format ceil
|
13. format bool
|
||||||
14. format floor
|
14. format boolz
|
||||||
15. format int
|
15. format ceil
|
||||||
16. functions arrfill
|
16. format floor
|
||||||
17. functions arrfillc
|
17. format int
|
||||||
18. functions arrmissfill
|
18. functions arrfill
|
||||||
19. functions arrmissfillc
|
19. functions arrfillc
|
||||||
20. functions arrmisstoleft
|
20. functions arrmissfill
|
||||||
21. functions arrmisstoleftc
|
21. functions arrmissfillc
|
||||||
22. functions arrmisstoright
|
22. functions arrmisstoleft
|
||||||
23. functions arrmisstorightc
|
23. functions arrmisstoleftc
|
||||||
24. functions bracketsc
|
24. functions arrmisstoright
|
||||||
25. functions bracketsn
|
25. functions arrmisstorightc
|
||||||
26. functions catxfc
|
26. functions bracketsc
|
||||||
27. functions catxfi
|
27. functions bracketsn
|
||||||
28. functions catxfj
|
28. functions catxfc
|
||||||
29. functions catxfn
|
29. functions catxfi
|
||||||
30. functions deldataset
|
30. functions catxfj
|
||||||
31. functions semicolonc
|
31. functions catxfn
|
||||||
32. functions semicolonn
|
32. functions deldataset
|
||||||
33. format brackets
|
33. functions semicolonc
|
||||||
34. format semicolon
|
34. functions semicolonn
|
||||||
35. proto qsortincbyprocproto
|
35. format brackets
|
||||||
36. functions frommissingtonumberbs
|
36. format semicolon
|
||||||
37. functions fromnumbertomissing
|
37. proto qsortincbyprocproto
|
||||||
38. functions quicksort4notmiss
|
38. functions frommissingtonumberbs
|
||||||
39. functions quicksorthash
|
39. functions fromnumbertomissing
|
||||||
40. functions quicksorthashsddv
|
40. functions quicksort4notmiss
|
||||||
41. functions quicksortlight
|
41. functions quicksorthash
|
||||||
|
42. functions quicksorthashsddv
|
||||||
|
43. functions quicksortlight
|
||||||
|
|
||||||
*SAS package generated by generatePackage, version 20210109*
|
|
||||||
|
*SAS package generated by generatePackage, version 20210528*
|
||||||
|
|
||||||
The SHA256 hash digest for package BasePlus:
|
The SHA256 hash digest for package BasePlus:
|
||||||
`A321A4BC54D444B82575EC5D443553A096557AD69DC171D578A330277E67637A`
|
`5EAEF846754F19759C0492308478417C9667C9651F1EF14F70E4FF8AB4C857F6`
|
||||||
|
|
||||||
---
|
---
|
||||||
# Content description ############################################################################################
|
# Content description ############################################################################################
|
||||||
@@ -2929,8 +2944,292 @@ run;
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## >>> `%functionExists()` macro: <<< <a name="functionexists-macro"></a> #######################
|
||||||
|
|
||||||
|
The functionExists() macro function tests
|
||||||
|
if given funcion exists in the SAS session.
|
||||||
|
The `sashelp.vfunc` view is used.
|
||||||
|
|
||||||
|
See examples below for the details.
|
||||||
|
|
||||||
|
The `%functionExists()` macro executes like a pure macro code.
|
||||||
|
|
||||||
|
The function is a result of cooperation with [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
|
||||||
|
|
||||||
|
### SYNTAX: ###################################################################
|
||||||
|
|
||||||
|
The basic syntax is the following, the `<...>` means optional parameters:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%functionExists(
|
||||||
|
funName
|
||||||
|
)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**Arguments description**:
|
||||||
|
|
||||||
|
1. `funName` - *Required*, the name of the function
|
||||||
|
existence of which you are testing.
|
||||||
|
|
||||||
|
### EXAMPLES AND USECASES: ####################################################
|
||||||
|
|
||||||
|
**EXAMPLE 1.** Test if function exists:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%put %functionExists(HASHING);
|
||||||
|
|
||||||
|
%put %functionExists(COSsinLOG);
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## >>> `%RainCloudPlot()` macro: <<< <a name="raincloudplot-macro"></a> #######################
|
||||||
|
|
||||||
|
The RainCloudPlot() macro allow to plot Rain Cloud plots, i.e. pots of
|
||||||
|
kernel density estimates, jitter data values, and box-and-whiskers plot.
|
||||||
|
|
||||||
|
See examples below for the details.
|
||||||
|
|
||||||
|
### SYNTAX: ###################################################################
|
||||||
|
|
||||||
|
The basic syntax is the following, the `<...>` means optional parameters:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%RainCloudPlot(
|
||||||
|
DS
|
||||||
|
,gr
|
||||||
|
,vars
|
||||||
|
|
||||||
|
<,WidthPX=>
|
||||||
|
<,HeightPX=>
|
||||||
|
<,boxPlot=>
|
||||||
|
<,roundFactor=>
|
||||||
|
<,rainDropSize=>
|
||||||
|
<,boxPlotSymbolSize=>
|
||||||
|
<,colorsList=>
|
||||||
|
<,monochrome=>
|
||||||
|
<,antialiasMax=>
|
||||||
|
<,title=>
|
||||||
|
<,footnote=>
|
||||||
|
<,catLabels=>
|
||||||
|
<,xLabels=>
|
||||||
|
<,catLabelPos=>
|
||||||
|
<,xLabelPos=>
|
||||||
|
<,formated=>
|
||||||
|
<,y2axis=>
|
||||||
|
<,y2axisLevels=>
|
||||||
|
|
||||||
|
<,VSCALE=>
|
||||||
|
<,KERNEL_K=>
|
||||||
|
<,KERNEL_C=>
|
||||||
|
|
||||||
|
<,cleanTempData=>
|
||||||
|
)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**Arguments description**:
|
||||||
|
|
||||||
|
1. `DS` - *Required*, name of the dataset from
|
||||||
|
which variables are to be taken.
|
||||||
|
|
||||||
|
2. `gr` - *Required*, name of the grouping variable.
|
||||||
|
When more than one variable is specified
|
||||||
|
separate plots are rendered.
|
||||||
|
Can be numeric or character.
|
||||||
|
|
||||||
|
3. `vars` - *Required*, name of the aggregated numeric variable.
|
||||||
|
When more than one variable is specified
|
||||||
|
separate plots are rendered.
|
||||||
|
|
||||||
|
***Plot related options***:
|
||||||
|
|
||||||
|
* `WidthPX` - *Optional*, default value `1200`.
|
||||||
|
Total width of the plot in pixels.
|
||||||
|
|
||||||
|
* `HeightPX` - *Optional*, default value `220`.
|
||||||
|
Partial height of the plot in pixels.
|
||||||
|
Total height is calculated as `#GROUPS x HeightPX`.
|
||||||
|
|
||||||
|
* `boxPlot` - *Optional*, default value `1`.
|
||||||
|
Indicates if the Box Plot should be added.
|
||||||
|
|
||||||
|
* `roundFactor` - *Optional*, default value `0.000001`.
|
||||||
|
Rounding level when calculating maximum value
|
||||||
|
of the cloud chart. Should be adjusted to data
|
||||||
|
granularity level, e.g. for data with value
|
||||||
|
around `1e-8` should be decreased.
|
||||||
|
|
||||||
|
* `rainDropSiz` - *Optional*, default value `5px`.
|
||||||
|
Size of data points in the "rain" plot.
|
||||||
|
|
||||||
|
* `boxPlotSymbolSize` - *Optional*, default value `8px`.
|
||||||
|
Size of symbols on the box plot.
|
||||||
|
|
||||||
|
* `colorsList` - *Optional*, default value is empty.
|
||||||
|
List of colours for plotting.
|
||||||
|
Empty indicates that the default list will be used.
|
||||||
|
|
||||||
|
* `monochrome` - *Optional*, default value `0`.
|
||||||
|
Indicates if the default list of colours should be gray-scale.
|
||||||
|
|
||||||
|
* `antialiasMax` - *Optional*, default value is empty.
|
||||||
|
Sets a value to the ODS graphics `ANTIALIASMAX` option.
|
||||||
|
When empty the value is calculated from data.
|
||||||
|
|
||||||
|
* `title` - *Optional*, default value - see notes below.
|
||||||
|
Provides a list of titles printed on the plot.
|
||||||
|
For details see notes below.
|
||||||
|
|
||||||
|
* `footnote` - *Optional*, default value - see notes below.
|
||||||
|
Provides a list of titles printed on the plot.
|
||||||
|
For details see notes below.
|
||||||
|
|
||||||
|
* `catLabels` - *Optional*, default value is empty.
|
||||||
|
List of values for group axix labels (vertical).
|
||||||
|
When empty a grouping variable name is used.
|
||||||
|
For details see notes below.
|
||||||
|
|
||||||
|
* `xLabels` - *Optional*, default value is empty.
|
||||||
|
List of values for data variable axix labels (horizontal).
|
||||||
|
When empty a data variable name is used.
|
||||||
|
For details see notes below.
|
||||||
|
|
||||||
|
* `catLabelPos` - *Optional*, default value `DATACENTER`.
|
||||||
|
Indicates position of the label on group axix (vertical).
|
||||||
|
Allowed values are `BOTTOM`, `CENTER`, `DATACENTER`, and `TOP`.
|
||||||
|
|
||||||
|
* `xLabelPos` - *Optional*, default value `DATACENTER`.
|
||||||
|
Indicates position of the label on data axix (horizontal).
|
||||||
|
Allowed values are `LEFT`, `CENTER`, `DATACENTER`, and `RIGHT`.
|
||||||
|
|
||||||
|
* `formated` - *Optional*, default value `0`.
|
||||||
|
Indicates if values of the grouping variable should be formated.
|
||||||
|
|
||||||
|
* `y2axis` - *Optional*, default value `1`.
|
||||||
|
Indicates if the righ vertical axix should be displayed.
|
||||||
|
|
||||||
|
* `y2axisLevels` - *Optional*, default value `4`.
|
||||||
|
Indicates if the number of expected levels of values printed
|
||||||
|
on the right vertical axix.
|
||||||
|
|
||||||
|
***Stat related options***:
|
||||||
|
|
||||||
|
* `VSCALE` - *Optional*, default value `Proportion`.
|
||||||
|
Specifies the scale of the vertical axis.
|
||||||
|
Allowed values are `PROPORTION`, `PERCENT`, and `COUNT`.
|
||||||
|
`PROPORTION` scales the data in units of proportion of observations per data unit.
|
||||||
|
`PERCENT` scales the data in units of percent of observations per data unit.
|
||||||
|
`COUNT` scales the data in units of the number of observations per data unit.
|
||||||
|
|
||||||
|
* `KERNEL_K` - *Optional*, default value `NORMAL`.
|
||||||
|
Specifies type of kernel function to compute kernel density estimates.
|
||||||
|
Allowed values are `NORMAL`, `QUADRATIC`, and `TRIANGULAR`.
|
||||||
|
|
||||||
|
|
||||||
|
* `KERNEL_C` - *Optional*, default value `1`.
|
||||||
|
Specifies standardized bandwidth parameter *C* to compute kernel density estimates.
|
||||||
|
Allowed values are between `0` and `1`,
|
||||||
|
|
||||||
|
***Other options***:
|
||||||
|
|
||||||
|
* `cleanTempData` - *Optional*, default value `1`.
|
||||||
|
Indicates if temporary data sets should be deleted.
|
||||||
|
|
||||||
|
**NOTES:**
|
||||||
|
|
||||||
|
* Default value of the `title` option is:
|
||||||
|
`%nrstr(title1 JUSTIFY=C "Rain Cloud plot for &list_g. by " %unquote(&xLabel.);)`
|
||||||
|
Use the `%str()` or `%nrstr()` macro-function to handle special characters.
|
||||||
|
The `%unquote()` is used when resolving the parameter.
|
||||||
|
|
||||||
|
* Default value of the `footnote` option is:
|
||||||
|
`%nrstr(footnote1 JUSTIFY=L COLOR=lightGray HEIGHT=1 "by RainCloudPlot macro from the BasePlus package";)`
|
||||||
|
Use the `%str()` or `%nrstr()` macro-function to handle special characters.
|
||||||
|
The `%unquote()` is used when resolving the parameter.
|
||||||
|
|
||||||
|
* The `catLabels` and `xLabels` should be quoted comma separated lists enclosed with brackets,
|
||||||
|
e.g. `catLabels=("Continent of Origin", "Car Type")`, see Example below.
|
||||||
|
|
||||||
|
* Kernel density estimates and basic statistics are calculated with `PROC UNIVARIATE`.
|
||||||
|
|
||||||
|
* Plot is generated by `PROC SGPLOT` with `BAND`, `SCATTE`, and `POLYGON` plots.
|
||||||
|
|
||||||
|
* After execution the ODS graphics dimension parameters are set to `800px` by `600px`.
|
||||||
|
|
||||||
|
* SAS notes (`NOTE:`) are disabled for the execution time.
|
||||||
|
|
||||||
|
* List of predefined colours is:
|
||||||
|
`BlueViolet`, `RoyalBlue`, `OliveDrab`, `Gold`, `HotPink`, `Crimson`,
|
||||||
|
`MediumPurple`, `CornflowerBlue`, `YellowGreen`, `Goldenrod`, `Orchid`, `IndianRed`.
|
||||||
|
|
||||||
|
* The box-plot has the following interpretation:
|
||||||
|
- left vertical bar indicates the minimum,
|
||||||
|
- left whisker line starts at `max(Q1 - 1.5IQR, minimum)` and ends at lower quartile (Q1),
|
||||||
|
- diamond indicates mean,
|
||||||
|
- vertical bar inside of the box indicates median.
|
||||||
|
- right whisker line starts at upper quartile (Q3) and ends at `min(Q3 + 1.5IQR, maximum)`,
|
||||||
|
- right vertical bar indicates the maximum.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### EXAMPLES AND USECASES: ####################################################
|
||||||
|
|
||||||
|
**EXAMPLE 1.** Simple Rain Cloud Plot for a `have` dataset:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
|
||||||
|
data have;
|
||||||
|
g = "Aaa";
|
||||||
|
do _N_ = 1 to 50;
|
||||||
|
x = rannor(42);
|
||||||
|
output;
|
||||||
|
end;
|
||||||
|
|
||||||
|
g = "Bb";
|
||||||
|
do _N_ = 1 to 120;
|
||||||
|
select (mod(_N_,9));
|
||||||
|
when(1,2,3,4,5) x = 0.5*rannor(42)+1;
|
||||||
|
when(6,7,8) x = 0.5*rannor(42)+3;
|
||||||
|
otherwise x = 0.5*rannor(42)+5;
|
||||||
|
end;
|
||||||
|
output;
|
||||||
|
end;
|
||||||
|
|
||||||
|
g = "C";
|
||||||
|
do _N_ = 1 to 60;
|
||||||
|
x = 3*rannor(42)+7;
|
||||||
|
output;
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%RainCloudPlot(have, g, x)
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The output:
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**EXAMPLE 2.** Rain Cloud plot for `sashelp.cars` dataset
|
||||||
|
with groups by Origin or Type
|
||||||
|
for Invoice variables:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
|
||||||
|
%RainCloudPlot(
|
||||||
|
sashelp.cars(where=(Type ne "Hybrid"))
|
||||||
|
, Origin Type
|
||||||
|
, Invoice
|
||||||
|
, HeightPX=300
|
||||||
|
, y2axisLevels=3
|
||||||
|
, catLabels=("Continent of Origin", "Car Type")
|
||||||
|
, xLabels="Invoice, [$]"
|
||||||
|
)
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The output:
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## License ####################################################################
|
## License ####################################################################
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
BIN
packages/baseplus_RainCloudPlot_Ex0_9.png
Normal file
BIN
packages/baseplus_RainCloudPlot_Ex0_9.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
packages/baseplus_RainCloudPlot_Ex1.png
Normal file
BIN
packages/baseplus_RainCloudPlot_Ex1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
packages/baseplus_RainCloudPlot_Ex2a.png
Normal file
BIN
packages/baseplus_RainCloudPlot_Ex2a.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
BIN
packages/baseplus_RainCloudPlot_Ex2b.png
Normal file
BIN
packages/baseplus_RainCloudPlot_Ex2b.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
266
packages/gsm.md
Normal file
266
packages/gsm.md
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
- [The GSM package](#gsm-package)
|
||||||
|
- [Content description](#content-description)
|
||||||
|
* [`%GSM()` macro](#gsm-macro)
|
||||||
|
* [`%GSMpck_makeFCMPcode()` macro](#gsmpck-makefcmpcode-macro)
|
||||||
|
|
||||||
|
* [License](#license)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
# The GSM package [ver. 0.14] <a name="gsm-package"></a> ###############################################
|
||||||
|
|
||||||
|
The **GSM** (a.k.a. *Generate Secure Macros*) package allows
|
||||||
|
to create secured macros stored in SAS Proc FCMP functions.
|
||||||
|
The dataset with functions can be shared and allows to generate
|
||||||
|
macros without showing their code.
|
||||||
|
|
||||||
|
The GSM package is basically an automated version of the following:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
proc fcmp outlib = work.gsm.secure ENCRYPT;
|
||||||
|
function generateMacro() $;
|
||||||
|
rc = RESOLVE('
|
||||||
|
%macro secretMacro(x) / SECURE;
|
||||||
|
data test;
|
||||||
|
a = "&x.";
|
||||||
|
run;
|
||||||
|
%mend;
|
||||||
|
');
|
||||||
|
return (rc);
|
||||||
|
endsub;
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* share work.gsm dataset */
|
||||||
|
options cmplib = work.gsm;
|
||||||
|
data _null_;
|
||||||
|
rc = generateMacro();
|
||||||
|
put rc=;
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* enjoy */
|
||||||
|
%secretMacro(42)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
See examples for more details.
|
||||||
|
|
||||||
|
|
||||||
|
*How to use it:*
|
||||||
|
- Copy all files with your secured macros code into a directory.
|
||||||
|
Best approach is to have one file for one macro.
|
||||||
|
- Copy a path to the directory.
|
||||||
|
- Run the following code:
|
||||||
|
```
|
||||||
|
%GSM(<the path to directory>, cmplib=<name of the dataset>)
|
||||||
|
```
|
||||||
|
- Share generated `ZIP` file (unzip and run the code).
|
||||||
|
|
||||||
|
*Limitations:*
|
||||||
|
Single macro file cannot be longer than 32760 bytes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Package contains:
|
||||||
|
1. macro gsm
|
||||||
|
2. macro gsmpck_makefcmpcode
|
||||||
|
|
||||||
|
Required SAS Components:
|
||||||
|
`Base SAS Software`
|
||||||
|
|
||||||
|
* SAS package generated by generatePackage, version 20210528 *
|
||||||
|
|
||||||
|
The SHA256 hash digest for package BasePlus:
|
||||||
|
`93D88D4465B68984E938212241DE55C7B12EBC20601538553AC9E1AC0628C006`
|
||||||
|
|
||||||
|
|
||||||
|
## >>> `%GSM()` macro: <<< <a name="gsm-macro"></a> #######################
|
||||||
|
|
||||||
|
The `%GSM()` macro is the main macro of
|
||||||
|
the **GSM** (a.k.a. *Generate Secure Macros*) package.
|
||||||
|
|
||||||
|
It converts a list of macros provided by the user into
|
||||||
|
a data set of the Proc FCMP functions. The macros are stored
|
||||||
|
in functions are encrypted which allow to share them without
|
||||||
|
showing their code. *Important* thing is that macros provided
|
||||||
|
by the user *has* to be "secure", i.e. the `secure` option has to
|
||||||
|
be added to the macro definition. See the example:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%macro secretMacro(x) / SECURE; /* <- the secure option */
|
||||||
|
<... some code ...>
|
||||||
|
%mend secretMacro;
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
|
As a result a zip file, containing dataset with functions and
|
||||||
|
code to be executed on site, is generated.
|
||||||
|
|
||||||
|
Since encrypted code is stored in a SAS dataset it has
|
||||||
|
no limitation in sharing between operating systems (like catalogs have).
|
||||||
|
|
||||||
|
*Limitation:* Due to the `Resolve()` function limitations
|
||||||
|
a single macro file cannot be longer than 32760 bytes.
|
||||||
|
|
||||||
|
*Notes:*
|
||||||
|
- All macros have to have the `secure` option added, i.e. `%macro aMacroname(...) / SECURE ;`.
|
||||||
|
- During the execution a test macro, named `%GSMpck_dummyMacroForTests()`, is generated.
|
||||||
|
- The `%GSM()` macro calls the `%GSMpck_makeFCMPcode(...)` macro internally.
|
||||||
|
|
||||||
|
### SYNTAX: ###################################################################
|
||||||
|
|
||||||
|
The basic syntax is the following, the `<...>` means optional parameters:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%GSM(
|
||||||
|
path
|
||||||
|
<,trim=0>
|
||||||
|
<,cmplib=work.generateMacros>
|
||||||
|
<,source2=>
|
||||||
|
<,outpath=>
|
||||||
|
<,encodingRestricted=>
|
||||||
|
)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**Arguments description**:
|
||||||
|
|
||||||
|
1. `path` - *Required*, indicates a directory which contains files with macros.
|
||||||
|
Only files with `sas` extension are used.
|
||||||
|
|
||||||
|
* `trim=` - *Optional*, the default value is `0`.
|
||||||
|
If set to `1` then lines of macro code are trimmed.
|
||||||
|
If set to `2` then lines of macro code are stripped.
|
||||||
|
|
||||||
|
* `cmplib=` - *Optional*, the default value is `work.generateMacros`.
|
||||||
|
Names the dataset which will contain generated functions.
|
||||||
|
|
||||||
|
* `source2=` - *Optional*, the default value is null.
|
||||||
|
Indicate if `%includ`-ed files are printed out.
|
||||||
|
Any value other than null enables printing.
|
||||||
|
|
||||||
|
* `outpath=` - *Optional*, the default value is set the same as the `path`.
|
||||||
|
Points a directory in which a result (a zip file) is generated.
|
||||||
|
|
||||||
|
* `encodingRestricted=` - *Optional*, the default value is `0`.
|
||||||
|
If set to 1 then if User session encoding is different from
|
||||||
|
encoding of the session which generates the dataset then
|
||||||
|
the generateMacros() function will not execute macro code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Example: ###################################################################
|
||||||
|
|
||||||
|
Example 1. Prepare 2 files: `f1.sas` and `f2.sas` and use the `%GSM()` macro.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%let path = %sysfunc(pathname(work))/path2files;
|
||||||
|
|
||||||
|
%put &=path.;
|
||||||
|
options dlcreatedir;
|
||||||
|
libname path "&path.";
|
||||||
|
filename path "&path.";
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file path(f1.sas);
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
cards4;
|
||||||
|
%macro abc(x) / SECURE;
|
||||||
|
data test;
|
||||||
|
do i = 1 to &x.;
|
||||||
|
put i=;
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
%mend;
|
||||||
|
;;;;
|
||||||
|
run;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file path(f2.sas);
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
cards4;
|
||||||
|
%macro xyz(x) / SECURE;
|
||||||
|
%do i = 1 to &x.;
|
||||||
|
%put &i=;
|
||||||
|
%end;
|
||||||
|
%mend;
|
||||||
|
;;;;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%GSM(&path., cmplib=work.myMacros)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
|
## >>> `%GSMpck_makeFCMPcode()` macro: <<< <a name="gsmpck-makefcmpcode-macro"></a> #######################
|
||||||
|
|
||||||
|
The `%GSMpck_makeFCMPcode()` macro is an internal macro of
|
||||||
|
the **GSM** (a.k.a. *Generate Secure Macros*) package.
|
||||||
|
|
||||||
|
It executes a process of converting
|
||||||
|
a macro provided by the user into
|
||||||
|
a Proc FCMP function.
|
||||||
|
|
||||||
|
Since encrypted code is stored in a SAS dataset it has
|
||||||
|
no limitation in sharing between operating systems (like catalogs have).
|
||||||
|
|
||||||
|
*Limitation:* Single macro file cannot be longer than 32760 bytes.
|
||||||
|
|
||||||
|
### SYNTAX: ###################################################################
|
||||||
|
|
||||||
|
The basic syntax is the following, the `<...>` means optional parameters:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%GSMpck_makeFCMPcode(
|
||||||
|
path
|
||||||
|
,number
|
||||||
|
<,trim=0>
|
||||||
|
<,outlib=work.generateMacros.secure>
|
||||||
|
<,source2=>
|
||||||
|
<,fileNameCode=FNC>
|
||||||
|
)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**Arguments description**:
|
||||||
|
|
||||||
|
1. `path` - *Required*, indicates a directory which contains files with macros.
|
||||||
|
Only files with `sas` extension are used.
|
||||||
|
|
||||||
|
2. `number` - *Required*, a sequential number.
|
||||||
|
|
||||||
|
* `trim=` - *Optional*, the default value is `0`.
|
||||||
|
If set to `1` then lines of macro code are trimmed.
|
||||||
|
If set to `2` then lines of macro code are stripped.
|
||||||
|
|
||||||
|
* `cmplib=` - *Optional*, the default value is `work.generateMacros`.
|
||||||
|
Names the dataset which will contain generated functions.
|
||||||
|
|
||||||
|
* `source2=` - *Optional*, the default value is null.
|
||||||
|
Indicate if `%includ`-ed files are printed out.
|
||||||
|
Any value other than null enables printing.
|
||||||
|
|
||||||
|
* `fileNameCode=` - *Optional*, the default value is `FNC`.
|
||||||
|
Internal fileref.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## License ####################################################################
|
||||||
|
|
||||||
|
Copyright (c) Bartosz Jablonski, since 2021
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
---
|
||||||
BIN
packages/gsm.zip
Normal file
BIN
packages/gsm.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user