Scripting Guide JMP 12 SAS Institute
User Manual: Pdf
Open the PDF directly: View PDF .
Page Count: 692
Download | |
Open PDF In Browser | View PDF |
Version 12 Scripting Guide “The real voyage of discovery consists not in seeking new landscapes, but in having new eyes.” Marcel Proust JMP, A Business Unit of SAS SAS Campus Drive Cary, NC 27513 The correct bibliographic citation for this manual is as follows: SAS Institute Inc. 2015. JMP® 12 Scripting Guide. Cary, NC: SAS Institute Inc. JMP® 12 Scripting Guide Copyright © 2015, SAS Institute Inc., Cary, NC, USA ISBN 978‐1‐62959‐482‐8 (Hardcopy) ISBN 978‐1‐62959‐484‐2 (EPUB) ISBN 978‐1‐62959‐485‐9 (MOBI) ISBN 978‐1‐62959‐483‐5 (PDF) All rights reserved. Produced in the United States of America. For a hard-copy book: No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopying, or otherwise, without the prior written permission of the publisher, SAS Institute Inc. For a web download or e-book: Your use of this publication shall be governed by the terms established by the vendor at the time you acquire this publication. The scanning, uploading, and distribution of this book via the Internet or any other means without the permission of the publisher is illegal and punishable by law. Please purchase only authorized electronic editions and do not participate in or encourage electronic piracy of copyrighted materials. Your support of others’ rights is appreciated. U.S. Government License Rights; Restricted Rights: The Software and its documentation is commercial computer software developed at private expense and is provided with RESTRICTED RIGHTS to the United States Government. Use, duplication or disclosure of the Software by the United States Government is subject to the license terms of this Agreement pursuant to, as applicable, FAR 12.212, DFAR 227.7202‐1(a), DFAR 227.7202‐3(a) and DFAR 227.7202‐4 and, to the extent required under U.S. federal law, the minimum restricted rights as set out in FAR 52.227‐19 (DEC 2007). If FAR 52.227‐19 is applicable, this provision serves as notice under clause (c) thereof and no other notice is required to be affixed to the Software or documentation. The Government’s rights in Software and documentation shall be only those set forth in this Agreement. SAS Institute Inc., SAS Campus Drive, Cary, North Carolina 27513‐2414. March 2015 SAS® and all other SAS Institute Inc. product or service names are registered trademarks or trademarks of SAS Institute Inc. in the USA and other countries. ® indicates USA registration. Other brand and product names are trademarks of their respective companies. Technology License Notices • Scintilla ‐ Copyright © 1998‐2014 by Neil Hodgson. All Rights Reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. • Telerik RadControls: Copyright © 2002‐2012, Telerik. Usage of the included Telerik RadControls outside of JMP is not permitted. • ZLIB Compression Library ‐ Copyright © 1995‐2005, Jean‐Loup Gailly and Mark Adler. • Made with Natural Earth. Free vector and raster map data @ naturalearthdata.com. • Packages ‐ Copyright © 2009‐2010, Stéphane Sudre (s.sudre.free.fr). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. • iODBC software ‐ Copyright © 1995‐2006, OpenLink Software Inc and Ke Jin (www.iodbc.org). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: ‒ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. ‒ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ‒ Neither the name of OpenLink Software Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. • bzip2, the associated library “libbzip2”, and all documentation, are Copyright © 1996‐2010, Julian R Seward. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. • R software is Copyright © 1999‐2012, R Foundation for Statistical Computing. • MATLAB software is Copyright © 1984‐2012, The MathWorks, Inc. Protected by U.S. and international patents. See www.mathworks.com/patents. MATLAB and Simulink are registered trademarks of The MathWorks, Inc. See www.mathworks.com/ trademarks for a list of additional trademarks. Other product or brand names may be trademarks or registered trademarks of their respective holders. • libopc is Copyright © 2011, Florian Reuter. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: ‒ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. ‒ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and / or other materials provided with the distribution. ‒ Neither the name of Florian Reuter nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. • libxml2 ‐ Except where otherwise noted in the source code (e.g. the files hash.c, list.c and the trio files, which are covered by a similar licence but with different Copyright notices) all the files are: Copyright © 1998 ‐ 2003 Daniel Veillard. All Rights Reserved. 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 DANIEL VEILLARD 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. Except as contained in this notice, the name of Daniel Veillard shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from him. Get the Most from JMP® Whether you are a first‐time or a long‐time user, there is always something to learn about JMP. Visit JMP.com to find the following: • live and recorded webcasts about how to get started with JMP • video demos and webcasts of new features and advanced techniques • details on registering for JMP training • schedules for seminars being held in your area • success stories showing how others use JMP • a blog with tips, tricks, and stories from JMP staff • a forum to discuss JMP with other users http://www.jmp.com/getstarted/ Contents Scripting Guide 1 Learn about JMP Documentation and Additional Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Formatting Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 JMP Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 JMP Documentation Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 JMP Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Additional Resources for Learning JMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Tutorials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Sample Data Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Learn about Statistical and JSL Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Learn JMP Tips and Tricks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Tooltips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 JMP User Community . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 JMPer Cable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 JMP Books by Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 The JMP Starter Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 2 Introduction Welcome to the JMP Scripting Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 What JSL Can Do for You . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Help with Learning JSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 The Scripting Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 The Scripting Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Let JMP Teach You JSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Basic JSL Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 10 3 Scripting Guide Getting Started Let JMP Write Your Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Capturing a Script for an Analysis Report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Capturing a Script for a Data Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Capturing a Script to Import a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Gluing Scripts Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4 Scripting Tools Using the Script Editor, Log Window, Debugger and Profiler . . . . . . . . . . . . . . . . . . . . . . . 53 Using the Script Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Run a Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Stop a Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Edit a Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Color Coding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Auto Complete Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Tooltips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Split a Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Match Parentheses, Brackets, and Braces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Select a Rectangular Block of Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Select Fragmented Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Drag and Drop Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Find and Replace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Automatic Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Add Code Folding Markers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Advanced Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Set Preferences for the Script Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Working with the Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Show the Log in the Script Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Save the Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Debug or Profile Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Debugger and Profiler Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Work with Breakpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 View Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Work with Watches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Modify Preferences in Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Scripting Guide 11 Persistent Debugger Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Examples of Debugging and Profiling Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 5 JSL Building Blocks Learning the Basics of JSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 JSL Syntax Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Value Separators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Global and Local Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Local Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Named Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Show Symbols, Clear Symbols, and Delete Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Lock and Unlock Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Rules for Name Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Resolving Unscoped Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Troubleshooting Variables and Column Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Troubleshooting Variables and Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Alternatives for Gluing Expressions Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Iterate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Summation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Product . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Break and Continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Conditional Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 If . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Match . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Choose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Interpolate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Step . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Compare Incomplete or Mismatched Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 12 Scripting Guide Inquiry Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 6 Types of Data Working with Numbers, Strings, Dates, Currency, and More . . . . . . . . . . . . . . . . . . . . . . 123 Numbers and Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Unicode Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Path Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 Create and Customize Path Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Relative Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 File Path Separators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Date‐Time Functions and Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 Date‐Time Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 Program with Date‐Time Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Date‐Time Values in Data Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Currency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Hexadecimal and BLOB Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 Work with Character Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Concat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Munger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Repeat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Pattern Matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 7 Data Structures Working with Collections of Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Evaluate Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Assignments with Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Perform Operations in Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Find the Number of Items in a List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Subscripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Locate Items in a List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 List Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Iterate through a List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Concatenate Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Scripting Guide 13 Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Construct Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Subscripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Inquiry Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Comparisons, Range Checks, and Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Numeric Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 Concatenation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 Transpose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 Matrices and Data Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 Matrices and Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Loc Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Ranking and Sorting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Special Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Inverse Matrices and Linear Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 Decompositions and Normalizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 Build Your Own Matrix Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Statistical Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Associative Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 8 Programming Methods Complex Scripting Techniques and Additional Functions . . . . . . . . . . . . . . . . . . . . . . . . . 219 Lists and Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Stored expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231 Manipulating lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231 Manipulating expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Advanced Scoping and Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Names Default To Here . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 Scoped Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 Referencing Namespaces and Scopes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Resolving Named Variable References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Best Practices for Advanced Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 Advanced Programming Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Throwing and Catching Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 14 Scripting Guide Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Includes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Loading and Saving Text Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 Scripting BY Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 Organize Files into Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 Encrypt and Decrypt Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 Additional Numeric Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Derivatives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Algebraic Manipulations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 Maximize and Minimize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 Scheduling Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 Functions that Communicate with Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 Writing to the Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 Send information to the User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 9 Data Tables Working with Data Table Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 Get Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Basic Data Table Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Open a Data Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Create a New Data Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 Import Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 Set the Current Data Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 Name a Data Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 Save a Data Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 Hide a Data Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 Advanced Data Table Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 Columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 Rows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 Accessing Data Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 Add Metadata to a Data Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 Calculations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366 Scripting Guide 15 10 Scripting Platforms Create, Repeat, and Modify Analyses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 Scripting Analysis Platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 Launching Platforms Interactively and Obtaining the Equivalent Script . . . . . . . . . . . . . . . . 373 Launch a Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373 Save Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373 Make Some Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 Syntax for Platform Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 BY Group Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 Saving BY Group Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 Sending Script Commands to a Live Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 Conventions for Commands and Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 Sending Several Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 Learning the Messages an Object Responds to . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 How to Interpret the Listing from Show Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 Launching Platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382 Specifying Columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382 Platform Action Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384 Invisible Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384 Report Titles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 General Messages for Platform Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 Additional Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 Supercategories in Categorical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 Spline Fits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390 Fit Model Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390 Fit Model Send Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 DOE Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 Scatterplot Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 Process Capability Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 Control Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 11 Display Trees Create and Use Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 Manipulating Displays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 16 Scripting Guide Introduction to Display Boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 Display Box Object References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408 Sending Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411 How to Access Built‐in Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Using the Pick Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 Files in Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 Constructing Display Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 Updating an Existing Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425 Interactive Display Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428 Modal and Non‐Modal Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433 Send Messages to Constructed Displays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451 Build Your Own Displays from Scratch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452 Construct Display Boxes Containing Platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452 Construct a Custom Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455 Sheets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458 Journals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460 Picture Display Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461 Modal Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461 Constructing Modal Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462 General‐Purpose Modal Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462 Convert Deprecated Dialog to New Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463 Comparison of Dialog and New Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468 Constructing Dialogs and Column Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474 Scripting the Script Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477 Syntax Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478 12 Scripting Graphs Create and Edit 2-Dimensional Plots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487 Adding Scripts to Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489 Ordering Graphics Elements Using JSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490 Adding a Legend to a Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495 Creating New Graphs From Scratch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495 Making Changes to Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496 Scripting Guide 17 Graphing Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498 Plotting Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498 Getting the Properties of a Graphics Frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503 Adding a Legend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503 Drawing Lines, Arrows, Points, and Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 Arrows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506 Markers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507 Pies and Arcs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509 Regular Shapes: Circles, Rectangles, and Ovals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510 Irregular Shapes: Polygons and Contours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513 Adding text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515 Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516 Transparency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518 Fill patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519 Line types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519 Drawing With Pixels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520 Interactive graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521 Handle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521 MouseTrap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524 Drag Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525 Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527 Creating Background Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527 13 Three-Dimensional Scenes Scripting in Three Dimensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531 About JSL 3‐D Scenes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533 JSL 3‐D Scene Boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533 Setting the Viewing Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536 Setting Up a Perspective Scene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 Setting up an Orthographic Scene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538 Changing the View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 The Translate Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 The Rotate Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 The Look At Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541 18 Scripting Guide The ArcBall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542 Graphics Primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543 Primitives Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546 Controlling the Appearance of Primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547 Other uses of Begin and End . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553 Drawing Spheres, Cylinders, and Disks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553 Drawing Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555 Using the Matrix Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556 Lighting and Normals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559 Creating Light Sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559 Lighting Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561 Normal Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562 Shading Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562 Material Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563 Alpha Blending . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564 Fog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564 Bézier Curves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566 Using the Mouse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569 Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571 14 Extending JMP External Data Sources, Analytical Tools, and Automation . . . . . . . . . . . . . . . . . . . . . . . . . 573 Real‐Time Data Capture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575 Create a Datafeed Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575 Read in Real‐Time Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576 Manage a Datafeed with Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577 Dynamic Link Libraries (DLLs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581 Using Sockets in JSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584 Database Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587 Working with SAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590 Make a SAS DATA Step . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590 Create SAS DATA Step Code for Formula Columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590 SAS Variable Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 591 Scripting Guide 19 Get the Values of SAS Macro Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 591 Connect to a SAS Metadata Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592 Preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595 Sample Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595 Working with MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596 Installing MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597 Working with R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598 Installing R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598 JMP to R Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600 R JSL Scriptable Object Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600 Conversion Between JMP Data Types and R Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . 600 Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604 Working with Excel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605 Parsing XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606 OLE Automation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608 Automating JMP through Visual Basic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608 Automating JMP through Visual C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 616 15 Creating and Sharing Applications Application Builder and Add-In Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621 Application Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623 Application Builder Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625 Design an Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627 Application Builder Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627 Red Triangle Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629 Create an Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630 Edit or Run an Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642 Options for Saving Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642 JMP Add‐Ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646 Create an Add‐In Using Add‐In Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646 Edit an Add‐In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 650 Remove an Add‐In from the Add‐Ins Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 650 Uninstall an Add‐In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 650 20 Scripting Guide Share an Add‐In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651 Register an Add‐In Using JSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 652 Create an Add‐In Manually . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 652 16 Common Tasks Getting Started with Sample Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655 Run a Script at Start Up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 657 Convert Character Dates to Numeric Dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 657 Format Date/Time Values and Subset Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 659 Create a Formula Column . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 660 Extract Values from an Analysis into a Report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661 Create an Interactive Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 664 A Compatibility Notes Changes in Scripting from JMP 11 to JMP 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669 Compatibility Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669 Deprecated JSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671 B Glossary Terms, Concepts, and Placeholders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673 Index Scripting Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677 Chapter 1 Learn about JMP Documentation and Additional Resources This chapter includes the following information: • book conventions • JMP documentation • JMP Help • additional resources, such as the following: ‒ other JMP documentation ‒ tutorials ‒ indexes ‒ Web resources Figure 1.1 The JMP Help Home Window on Windows Contents Formatting Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 JMP Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 JMP Documentation Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 JMP Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Additional Resources for Learning JMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Tutorials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Sample Data Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Learn about Statistical and JSL Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Learn JMP Tips and Tricks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Tooltips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 JMP User Community . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 JMPer Cable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 JMP Books by Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 The JMP Starter Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Chapter 1 Scripting Guide Learn about JMP Formatting Conventions 23 Formatting Conventions The following conventions help you relate written material to information that you see on your screen. • Sample data table names, column names, pathnames, filenames, file extensions, and folders appear in Helvetica font. • Code appears in Lucida Sans Typewriter font. • Code output appears in Lucida Sans Typewriter italic font and is indented farther than the preceding code. • Helvetica bold formatting indicates items that you select to complete a task: ‒ buttons ‒ check boxes ‒ commands ‒ list names that are selectable ‒ menus ‒ options ‒ tab names ‒ text boxes • The following items appear in italics: ‒ words or phrases that are important or have definitions specific to JMP ‒ book titles ‒ variables ‒ script output • Features that are for JMP Pro only are noted with the JMP Pro icon of JMP Pro features, visit http://www.jmp.com/software/pro/. . For an overview Note: Special information and limitations appear within a Note. Tip: Helpful information appears within a Tip. JMP Documentation JMP offers documentation in various formats, from print books and Portable Document Format (PDF) to electronic books (e‐books). 24 Learn about JMP JMP Documentation Chapter 1 Scripting Guide • Open the PDF versions from the Help > Books menu or from the JMP online Help footers. • All books are also combined into one PDF file, called JMP Documentation Library, for convenient searching. Open the JMP Documentation Library PDF file from the Help > Books menu. • e‐books are available at online retailers. Visit http://www.jmp.com/support/downloads/ documentation.shtml for details. • You can also purchase printed documentation on the SAS website: http://support.sas.com/documentation/onlinedoc/jmp/index.html JMP Documentation Library The following table describes the purpose and content of each book in the JMP library. Document Title Document Purpose Document Content Discovering JMP If you are not familiar with JMP, start here. Introduces you to JMP and gets you started creating and analyzing data. Using JMP Learn about JMP data tables and how to perform basic operations. Covers general JMP concepts and features that span across all of JMP, including importing data, modifying columns properties, sorting data, and connecting to SAS. Basic Analysis Perform basic analysis using this document. Describes these Analyze menu platforms: • Distribution • Fit Y by X • Matched Pairs • Tabulate How to approximate sampling distributions using bootstrapping and modeling utilities are also included. Chapter 1 Scripting Guide Learn about JMP JMP Documentation Document Title Document Purpose Document Content Essential Graphing Find the ideal graph for your data. Describes these Graph menu platforms: • Graph Builder • Overlay Plot • Scatterplot 3D • Contour Plot • Bubble Plot • Parallel Plot • Cell Plot • Treemap • Scatterplot Matrix • Ternary Plot • Chart The book also covers how to create background and custom maps. Profilers Learn how to use interactive profiling tools, which enable you to view cross‐sections of any response surface. Covers all profilers listed in the Graph menu. Analyzing noise factors is included along with running simulations using random inputs. Design of Experiments Guide Learn how to design experiments and determine appropriate sample sizes. Covers all topics in the DOE menu and the Screening menu item in the Analyze > Modeling menu. 25 26 Learn about JMP JMP Documentation Chapter 1 Scripting Guide Document Title Document Purpose Document Content Fitting Linear Models Learn about Fit Model platform and many of its personalities. Describes these personalities, all available within the Analyze menu Fit Model platform: Specialized Models Learn about additional modeling techniques. • Standard Least Squares • Stepwise • Generalized Regression • Mixed Model • MANOVA • Loglinear Variance • Nominal Logistic • Ordinal Logistic • Generalized Linear Model Describes these Analyze > Modeling menu platforms: • Partition • Neural • Model Comparison • Nonlinear • Gaussian Process • Time Series • Response Screening The Screening platform in the Analyze > Modeling menu is described in Design of Experiments Guide. Multivariate Methods Read about techniques for analyzing several variables simultaneously. Describes these Analyze > Multivariate Methods menu platforms: • Multivariate • Cluster • Principal Components • Discriminant • Partial Least Squares Chapter 1 Scripting Guide Learn about JMP JMP Documentation Document Title Document Purpose Document Content Quality and Process Methods Read about tools for evaluating and improving processes. Describes these Analyze > Quality and Process menu platforms: Reliability and Survival Methods Consumer Research Learn to evaluate and improve reliability in a product or system and analyze survival data for people and products. Learn about methods for studying consumer preferences and using that insight to create better products and services. • Control Chart Builder and individual control charts • Measurement Systems Analysis • Variability / Attribute Gauge Charts • Process Capability • Pareto Plot • Diagram Describes these Analyze > Reliability and Survival menu platforms: • Life Distribution • Fit Life by X • Recurrence Analysis • Degradation and Destructive Degradation • Reliability Forecast • Reliability Growth • Reliability Block Diagram • Survival • Fit Parametric Survival • Fit Proportional Hazards Describes these Analyze > Consumer Research menu platforms: • Categorical • Multiple Correspondence Analysis • Factor Analysis • Choice • Uplift • Item Analysis 27 28 Learn about JMP Additional Resources for Learning JMP Chapter 1 Scripting Guide Document Title Document Purpose Document Content Scripting Guide Learn about taking advantage of the powerful JMP Scripting Language (JSL). Covers a variety of topics, such as writing and debugging scripts, manipulating data tables, constructing display boxes, and creating JMP applications. JSL Syntax Reference Read about many JSL functions on functions and their arguments, and messages that you send to objects and display boxes. Includes syntax, examples, and notes for JSL commands. Note: The Books menu also contains two reference cards that can be printed: The Menu Card describes JMP menus, and the Quick Reference describes JMP keyboard shortcuts. JMP Help JMP Help is an abbreviated version of the documentation library that provides targeted information. You can open JMP Help in several ways: • On Windows, press the F1 key to open the Help system window. • Get help on a specific part of a data table or report window. Select the Help tool from the Tools menu and then click anywhere in a data table or report window to see the Help for that area. • Within a JMP window, click the Help button. • Search and view JMP Help on Windows using the Help > Help Contents, Search Help, and Help Index options. On Mac, select Help > JMP Help. • Search the Help at http://jmp.com/support/help/ (English only). Additional Resources for Learning JMP In addition to JMP documentation and JMP Help, you can also learn about JMP using the following resources: • Tutorials (see “Tutorials” on page 29) • Sample data (see “Sample Data Tables” on page 29) • Indexes (see “Learn about Statistical and JSL Terms” on page 29) Chapter 1 Scripting Guide Learn about JMP Additional Resources for Learning JMP • Tip of the Day (see “Learn JMP Tips and Tricks” on page 30) • Web resources (see “JMP User Community” on page 30) • JMPer Cable technical publication (see “JMPer Cable” on page 30) • Books about JMP (see “JMP Books by Users” on page 31) • JMP Starter (see “The JMP Starter Window” on page 31) 29 Tutorials You can access JMP tutorials by selecting Help > Tutorials. The first item on the Tutorials menu is Tutorials Directory. This opens a new window with all the tutorials grouped by category. If you are not familiar with JMP, then start with the Beginners Tutorial. It steps you through the JMP interface and explains the basics of using JMP. The rest of the tutorials help you with specific aspects of JMP, such as creating a pie chart, using Graph Builder, and so on. Sample Data Tables All of the examples in the JMP documentation suite use sample data. Select Help > Sample Data Library to do the following actions to open the sample data directory. To view an alphabetized list of sample data tables or view sample data within categories, select Help > Sample Data. Sample data tables are installed in the following directory: On Windows: C:\Program Files\SAS\JMP\ \Samples\Data On Macintosh: \Library\Application Support\JMP\ \Samples\Data In JMP Pro, sample data is installed in the JMPPRO (rather than JMP) directory. In JMP Shrinkwrap, sample data is installed in the JMPSW directory. Learn about Statistical and JSL Terms The Help menu contains the following indexes: Statistics Index Provides definitions of statistical terms. Lets you search for information about JSL functions, objects, and display boxes. You can also edit and run sample scripts from the Scripting Index. Scripting Index 30 Learn about JMP Additional Resources for Learning JMP Chapter 1 Scripting Guide Learn JMP Tips and Tricks When you first start JMP, you see the Tip of the Day window. This window provides tips for using JMP. To turn off the Tip of the Day, clear the Show tips at startup check box. To view it again, select Help > Tip of the Day. Or, you can turn it off using the Preferences window. See the Using JMP book for details. Tooltips JMP provides descriptive tooltips when you place your cursor over items, such as the following: • Menu or toolbar options • Labels in graphs • Text results in the report window (move your cursor in a circle to reveal) • Files or windows in the Home Window • Code in the Script Editor Tip: You can hide tooltips in the JMP Preferences. Select File > Preferences > General (or JMP > Preferences > General on Macintosh) and then deselect Show menu tips. JMP User Community The JMP User Community provides a range of options to help you learn more about JMP and connect with other JMP users. The learning library of one‐page guides, tutorials, and demos is a good place to start. And you can continue your education by registering for a variety of JMP training courses. Other resources include a discussion forum, sample data and script file exchange, webcasts, and social networking groups. To access JMP resources on the website, select Help > JMP User Community. JMPer Cable The JMPer Cable is a yearly technical publication targeted to users of JMP. The JMPer Cable is available on the JMP website: http://www.jmp.com/about/newsletters/jmpercable/ Chapter 1 Scripting Guide Learn about JMP Additional Resources for Learning JMP 31 JMP Books by Users Additional books about using JMP that are written by JMP users are available on the JMP website: http://www.jmp.com/support/books.shtml The JMP Starter Window The JMP Starter window is a good place to begin if you are not familiar with JMP or data analysis. Options are categorized and described, and you launch them by clicking a button. The JMP Starter window covers many of the options found in the Analyze, Graph, Tables, and File menus. • To open the JMP Starter window, select View (Window on the Macintosh) > JMP Starter. • To display the JMP Starter automatically when you open JMP on Windows, select File > Preferences > General, and then select JMP Starter from the Initial JMP Window list. On Macintosh, select JMP > Preferences > Initial JMP Starter Window. 32 Learn about JMP Additional Resources for Learning JMP Chapter 1 Scripting Guide Chapter 2 Introduction Welcome to the JMP Scripting Language The JMP Scripting Language, or JSL, lets you write scripts to recreate results in JMP. Power users often develop scripts to extend JMP’s functionality and automate a regularly scheduled analysis in production settings. If you do not want to learn JSL, JMP can write the scripts for you. JSL is used to perform many actions: • implements column formulas • launches platforms • interactively modifies platforms • creates graphics Contents What JSL Can Do for You. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Help with Learning JSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 The Scripting Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 The Scripting Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Let JMP Teach You JSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Basic JSL Syntax. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Chapter 2 Scripting Guide Introduction What JSL Can Do for You 35 What JSL Can Do for You JMP can automatically save scripts to reproduce any data table or analysis in its current state. You can pause any time in your analysis to save a script to a script window (or script editor), in a data table, or in an analysis report. You can then modify the script as needed for future projects. When you are finished with your work, you can then save a script to reproduce your final results. Here are some examples where JSL scripts can be helpful: • Suppose you need to describe an analysis process in detail, from beginning to end. An example is to create an audit trail for a governing agency, or for peers reviewing your journal article. • Suppose you have a set of analysis steps that should be followed routinely by your lab technicians. • Suppose you fit the same model to new data every day, and the steps are always the same. You can use JMP interactively as usual, save scripts to reproduce your work, and in the future run those scripts to reproduce your results. There are a few things that JSL is not designed to do: • JMP cannot record scripts while you are working. Though script‐recording is a useful feature in some other scripting languages, it is less important for software like JMP, where the results are what matter. You cannot use script‐recording to observe how a sequence of interactive steps is performed. • JSL is not an alternative command‐line interface for using the program. Help with Learning JSL There are several places within JMP to get help with writing or understanding a JSL script. The Scripting Guide The Scripting Guide book begins with basic information (such as terminology and syntax) for JMP users who are not familiar with the scripting language. The book progresses to more advanced information. Chapters 2 through 4 Includes information about learning JSL, producing basic scripts, and introduces you to the JSL scripting environment. 36 Introduction Help with Learning JSL Chapter 2 Scripting Guide Chapters 5 through 8 Introduces the building blocks of the language; working with basic data types, such as numbers and strings; writings lists, matrices, and associate arrays; namespaces; and the fundamentals of programming in JSL. Chapters 9 through 13 Covers using JSL with objects in JMP, such as data tables, platforms, windows, and graphics. Chapter 14 Describes how to write scripts that work with external programs, such as SAS, R, and Excel. Chapter 15 Introduces creating JMP applications in Application Builder, a drag‐and‐drop environment for visually designing windows with buttons, lists, graphs, and other objects. The chapter also describes how to use Add‐In Builder to compile scripts into one easily shared file. Chapter 16 Contains a collection of recipes, or script examples, that you can copy and modify for your own use. Appendices A and B Provides information about compatibility issues with the previous version of JMP and defines JSL concepts and terminology. The Scripting Index The Scripting Index on the Help menu provides a brief description and the syntax for JSL functions, objects, and display boxes. Each entry includes an example that you can run and modify to test your own code. And an embedded log window lets you see messages as examples are run. The Scripting Index window includes the following buttons: Click the Search button to begin the search. Click the Clear button to clear the search text box to begin a new search. Click the Settings button to set search types and parameters. Several types of searches are available from the Settings button: Partial Match returns all entries that contain at least a part of the “string” for example, a search for “leas” will return messages such as “Release Zoom” and “Partial Least Squares”. This option is the default search type. Chapter 2 Scripting Guide Introduction Help with Learning JSL 37 Exact Phrase returns entries that contain the exact string, for example, a search for “text” will return all elements that contain the “text” string. returns entries that contain either or both strings, for example, a search for “t test” will return all elements that contain either or both of the search strings, “Pat Test”, “Shortest Edit Script” and “Paired t test”. All Terms Any Term returns entries that contain either of the search strings, for example, a search for “text string” returns “Context Box”, “Drag Text”, and “Is String”. allows you to use the wildcard (*) and period (.) in the search box, for example, searching for “get *name” returns messages such as “Get Name Info” and “Get Namespace”. Searching for “get.*name” returns items such as “Get Color Theme Names”, “Get Name Info”, and “Get Effect Names”. Regular Expression Several search parameters are also available from the Settings button: All Fields specifies that JMP search all fields in the index for the search string. Titles Only specifies that JMP search only index titles for the search string. Examples Only specifies that JMP search only index examples for the search string. Without Examples specifies that JMP exclude examples from the search. Click an item’s Topic Help button to read more about the item in JMP’s online Help system. Let JMP Teach You JSL The best JSL writer is JMP. You can work in JMP interactively and then save the results as a script to reuse later. With simple modifications, your script can serve as a template for speeding up routine tasks. Because JSL is a very flexible language, you can reach your goals in many different ways. Here is an example. Typically, the script that JMP saves for you specifies every detail of your analysis, even if most of the details happen automatically by default. Does that mean that the scripts that you write have to be just as complete and detailed? Not at all. You usually need to specify only those details that you would select in the graphical user interface (GUI). For example, if you open Big Class.jmp from the sample data folder and want to launch Distribution for height, weight, and sex, the following script is all that is necessary: Distribution( Y( :height, :weight, :sex ) ); Suppose you run the Distribution platform in the GUI and then select Script > Save Script to Script Window from the red triangle menu for the report. The following script appears: Distribution( Nominal Distribution( Column( :sex ) ), Continuous Distribution( Column( :height ) ), Continuous Distribution( Column( :weight ) ) 38 Introduction Terminology Chapter 2 Scripting Guide ); Both scripts give the same result. Feel free to experiment with JSL. If you think something ought to be possible, it probably is. Give it a try, and see what happens. Terminology Before you begin creating scripts, you should become familiar with basic JSL terms used throughout this book. Operators and Functions An operator is one‐ or two‐character symbol (such as + or =) for common arithmetic actions. A function is a command that might contain additional information for the function to use. Certain JSL functions work the same as operators but provide access to more complex actions. For example, the following two lines are equivalent: 2 + 3; Add( 2, 3 ); The first line uses the + operator. The second line uses the Add() function equivalent. Although all JSL operators have function equivalents, not all functions have operator equivalents. For example, Sqrt(a) can be represented only by the Sqrt() function. Note: In previous versions of JMP and its documentation, the terms operators and functions were used interchangeably. Now each term has a specific meaning. Objects and Messages An object is a dynamic entity in JMP, such as a data table, a data column, a platform results window, a graph, and so on. Most objects can receive messages that instruct the object to perform some action on itself. A message is a JSL expression that is directed to an object. That object knows how to evaluate the message. In the following example, dt is the data table object. << indicates that a message follows. In the following example, the message tells JMP to create a summary table with the specified variables. dt << Summary( Group( :age ), Mean( :height ) ) In this expression, dt is the name of a variable that contains a reference to a data table. You could use any name for this variable. This book commonly uses dt to represent data table Chapter 2 Scripting Guide Introduction Terminology 39 references. Here are some of the more common names used in this book to represent references to certain objects: Abbreviation Object dt data table col column in a data table colname the name of a column in a data table obj an object db display box These variables are not pre‐assigned references. Each one must be assigned prior to its use. In the following example, the global variable named A is assigned the value “Hello, World”. When the Show( A ) command is processed, the result is the value of A. A = "Hello, World"; Show( A ); A = "Hello, World"; Arguments and Parameters An argument is additional information that you can provide to a function or message. For example, in Root(25), 25 is an argument to the Root() function. Root() acts on the argument that you provide and returns the result: 5. Programming and scripting books commonly talk about parameters as well. A parameter is a description of the argument that a function accepts. For example, the general specification for Root() might be Root( number ), where number is the parameter. Parameter and argument express two perspectives of the same concept: information that a function needs. For simplicity in this book, we use the word argument in both cases. A named argument is an optional argument that you select from a predetermined set and explicitly define. For example, title("My Line Graph") in the Graph Box() function is a named argument because the title is explicitly defined as such. Graph Box( title("My Line Graph"), Frame Size( 300, 500 ), Marker( Marker State( 3 ), [11 44 77], [75 25 50] ); Pen Color( "Blue" ); Line( [10 30 70], [88 22 44] )); 40 Introduction Terminology Chapter 2 Scripting Guide Note that the Frame Size() arguments 300 and 500 are not named. The position of these arguments implies meaning; the first argument is always the width, the second argument is always the height. Optional Arguments Functions and messages require certain arguments, and other arguments are optional. You can include them, but you do not have to. In specifications, optional arguments are enclosed in angle brackets. For example: Root( x, ) The x argument is required. The n argument is optional. Optional arguments often have a default value. For example, for Root(), the default value of n is 2: Code Output Explanation Root( 25 ) 5 Returns the square root of 25. Root( 25, 2 ) 5 Returns the square root of 25. Root( 25, 3 ) 2.92401773821287 Returns the cube root of 25. Expressions An expression is a section of JSL code that accomplishes a task. JSL expressions hold data, manipulate data, and send commands to objects. For example, the following expression opens the Big Class.jmp sample data table and creates a Bivariate graph: Open( "$SAMPLE_DATA/Big Class.JMP" ); Bivariate( Y( :weight ), X( :height ) ); Or and the Vertical Bar Symbol A single vertical bar (|) represents a logical OR. For brevity, | represents the word or when referring to alternative values. For example, a pathname can be either absolute or relative. When you see an argument such as absolute|relative, this means that you enter either one of the following two options: • absolute indicates an absolute pathname. • relative indicates a relative pathname. More than two options can also be strung together with a vertical bar in this way. Chapter 2 Scripting Guide Introduction Basic JSL Syntax 41 Script Formatting Whitespace characters (such as spaces, tabs, and newlines) and capitalization are ignored in JSL. This means that the following two expressions are equivalent: // Expression 1 sum=0; for(i=1,i<=10,i++,sum+=i;show(i,sum)) // Expression 2 Sum = 0; For( i = 1, i <= 10, i++, Sum += i; Show( i, Sum ); ); You can format your script in any way that you like. However, the script editor can also format your script for you. This book uses the script editor’s default formatting for capitalization, spaces, returns, tabs, and so on. See “Using the Script Editor” on page 55 in the “Scripting Tools” chapter for details about using the script editor. Note: The only white space exception is two‐character operators (such as <= or ++). The operators cannot be separated by a space. Basic JSL Syntax A JSL script is a series of expressions. Each expression is a section of JSL code that accomplishes a task. JSL expressions hold data, manipulate data, and send commands to objects. Many expressions are nested message names, with message contents enclosed in parentheses: Message Name ( argument 1, argument 2, ... ) The meaning of JSL names depends on the context. The same name might mean one thing in a data table context and something entirely different in a function context. See “Rules for Name Resolution” on page 97 in the “JSL Building Blocks” chapter for more information. Almost anything that follows certain punctuation rules, such as matching parentheses, is a valid JSL expression. For example: New Window( "A Window", << modal, Text box( "Hello, World" ), Text Box( "-----" ), ButtonBox( "OK" ) ); 42 Introduction Basic JSL Syntax Chapter 2 Scripting Guide Notice the following: • Names can have embedded spaces. See “Names” on page 88 in the “JSL Building Blocks” chapter for more information. • Message contents are enclosed in parentheses, which must be balanced. See “Parentheses” on page 85 in the “JSL Building Blocks” chapter. • Items are separated by commas. See “Commas” on page 85 in the “JSL Building Blocks” chapter. • JSL is not case sensitive; you can type “text box();” or “Text Box()”. • Messages are commonly nested inside other messages. Chapter 3 Getting Started Let JMP Write Your Scripts You often have to produce the same reports for the same data on a regular basis. This chapter shows you how to let JMP write scripts for common tasks like importing text data, opening Excel files, and producing reports. A final tutorial shows you how to put it all together into a single script to open an Excel file and produce three reports automatically. This book is written for users who are familiar with JMP but might not be familiar with JSL. For information about performing common tasks, refer to the Using JMP book. The Discovering JMP book is also a good resource for learning basic concepts and understanding the JMP workflow. Contents Capturing a Script for an Analysis Report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Capturing a Script for a Data Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Capturing a Script to Import a File. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Gluing Scripts Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Chapter 3 Scripting Guide Getting Started Capturing a Script for an Analysis Report 45 Capturing a Script for an Analysis Report The basic steps for capturing a script to reproduce an analysis are as follows: 1. Launch a platform, such as Distribution. 2. Make any changes or additions that you need. For example, add tests and other graphs. 3. Capture the script to recreate your results. You can save the script in the data table, so that if you send the data table to others, they can run your script and duplicate your reports. Example Follow these steps to produce a distribution report, capture the script to reproduce it, and save it to the data table. Note: The data tables that you use in examples are located in JMP’s Samples/Data folder. 1. Select Help > Sample Data Library and open the Companies.jmp. 2. Select Analyze > Distribution to open the Distribution launch window. 3. Select Profits ($M) in the Select Columns box and click the Y, Columns button. 4. Click OK. The Distribution report window appears. 5. From the red triangle menu next to Distributions, select Stack to make your report horizontal. 6. From the red triangle menu next to Profits ($M), deselect Outlier Box Plot to turn the option off. 7. From the red triangle menu next to Profits ($M), select Test Mean. The Test Mean window appears. 8. Type 500 in the Specify Hypothesized Mean box. 9. Click OK. The test for the mean is added to the report window. Now you have your customized report. 46 Getting Started Capturing a Script for a Data Table Chapter 3 Scripting Guide Figure 3.1 Customized Distribution Report 10. From the red triangle menu next to Distributions, select Script > Save Script to Data Table. Your data table now has a script named Distribution saved to it. From the red triangle menu for the script, select Edit to see the script. Figure 3.2 Distribution Script Saved to the Data Table 11. To run the script and reproduce your final report exactly, select Run Script from the red triangle menu for the script. Capturing a Script for a Data Table The basic steps for capturing a script to reproduce a data table are as follows: 1. Open the data table. 2. Make any changes that you need. For example, add a script, correct values, add new columns. Chapter 3 Scripting Guide Getting Started Capturing a Script to Import a File 47 3. Capture the script to recreate your data table. Example Use the data table from the previous example, where you saved a script to it. 1. In the data table, select the red triangle next to the data table’s name. 2. Select Copy Table Script. Figure 3.3 Copy the Table Script 3. Open a script window by selecting File > New > Script. 4. Select Edit > Paste. You now have a script that duplicates your data table. You can save this script and run it at any time to recreate your data table, with all its scripts attached. Capturing a Script to Import a File To capture a script that imports a file, you open the file in JMP. JMP automatically records the steps that occurred when you opened the file. Import a Text File 1. Select File > Open. The Open Data File window appears. 2. Select Text Files from the list next to File name. 3. In the Open as section, select Data, using best guess. JMP formats the data based on tabs, commas, white space, and other characters in the text file. 48 Getting Started Gluing Scripts Together Chapter 3 Scripting Guide 4. Browse to select the file, and then select Open. The file is opened as a data table. The data table includes a script named Source. This JSL script imports your text file with the text import rules that you used. 5. From the red triangle menu for Source, select Edit. You can copy this script, paste it into a new script window, and save it. Then you can run this script later to reimport the text file. Tip: The import script is an Open() expression that specifies the text file and the import options to correctly import the file into JMP. The first part of this expression is the pathname to the specific file that you imported. If you save this script and want to run it a different place, you might need to edit the pathname so that it points to the text file. Pathnames are discussed in greater detail in “Path Variables” on page 126 in the “Types of Data” chapter. Gluing Scripts Together Suppose new data is saved out to an Excel file once a week, and you need to produce the same reports every week. You could open the file and perform the same steps every week. However, creating a script that imports the new Excel file into JMP and runs all analyses automatically is more efficient. The following example shows you how to set up your script and run it each week. Import the Microsoft Excel File 1. Open a new script window (File > New > Script). 2. In your script window, enter the Open() expression to open the Solubil.xls sample import data file. The file is located in JMP’s Samples/Import Data folder. Open( "$SAMPLE_IMPORT_DATA/Solubil.xls" ); Be sure to put the semicolon at the end of this expression, because you will add more expressions. The semicolon glues expressions together. 3. Run your script to import the Excel file by selecting Edit > Run Script. The Excel file opens as a data table. Note: You can specify an absolute or relative path to the file rather than using a path variable. For relative links, the script and file being opened must be in the same relative location each time you run the script. With absolute links, make sure that other users running the script have access to the file’s location. See “Path Variables” on page 126 in the “Types of Data” chapter for more information about using pathnames. Chapter 3 Scripting Guide Getting Started Gluing Scripts Together 49 Run Your Reports and Capture Their Scripts You have three reports to produce: a distribution report, a 3D scatterplot, and a multivariate report. Perform each one using the GUI, and add its script to the script window. 1. With your new data table open, select Analyze > Distribution. 2. Select all the columns except Labels and click Y, Columns. 3. Click OK. 4. Hold down CTRL and select Histogram Options > Show Counts from the red triangle menu for eth. Bar counts are added to all six histograms. 5. In the Distribution window, select Script > Copy Script from the red triangle menu next to Distributions. 6. Place your cursor in the script window a line or two after your Open() expression and select Edit > Paste. 7. Type a semicolon after the last close parenthesis. 8. Select Graph > Scatterplot 3D. 9. Select all the columns except Labels and click Y, Columns. 10. Click OK. 11. Copy and paste the script for Scatterplot 3D into the script window just like you did for your Distribution report. Be sure to add the semicolon at the end. 12. Select Analyze > Multivariate Methods > Multivariate. 13. Select all the columns except Labels and click Y, Columns. 14. Click OK. 15. Copy and paste the script for Multivariate into the script window just like you did for Distributions and Scatterplot 3D. 50 Getting Started Gluing Scripts Together Chapter 3 Scripting Guide Figure 3.4 The Completed Script Save the Script You now have a script that reproduces all of the steps that you performed manually. Save the script, and close your data table and all its report windows. 1. In the script window that contains your script, select File > Save or File > Save As. 2. Specify a filename (for example, Weekly Report). 3. Click Save. Run the Script As long as your weekly updated Excel file is saved in the same place and contains the same columns, you can run your script and automatically produce all your reports. 1. Open the script that you saved. 2. Select Edit > Run Script. Your Excel file is opened in JMP, and all three of your reports appear. You can send this script to others. As long as they have access to the same Excel file in the same location, they can also run the script in JMP and see your reports. Advanced Note: Auto‐Submit If you want a particular script to always be executed instead of opened into the script window, put the following command on the first line of the script: //! If this is not the very first line, with nothing else on the same line, this command does nothing. Chapter 3 Scripting Guide Getting Started Gluing Scripts Together You can override this command when opening the file. 1. Select File > Open. 2. Hold the CTRL key while you select the JSL file and click Open. The script opens into a script window instead of being executed. The command is also ignored when you right‐click the file in the Home Window and select Edit Script. 51 52 Getting Started Gluing Scripts Together Chapter 3 Scripting Guide Chapter 4 Scripting Tools Using the Script Editor, Log Window, Debugger and Profiler JMP provides several programming tools for script writers. The script editor supports syntax coloring, autocompletes functions as you type, highlights matching braces, allows for code folding, and has additional features to help you develop scripts more quickly. Error messages and output are shown in the log window, which can be displayed inside the script editor. The JMP Scripting Language (JSL) Debugger and Profiler can help you troubleshoot your scripts. Figure 4.1 Script Editor with Embedded Log and the Debugger Contents Using the Script Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Run a Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Stop a Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Edit a Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Color Coding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Auto Complete Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Tooltips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Split a Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Match Parentheses, Brackets, and Braces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Select a Rectangular Block of Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Select Fragmented Text. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Drag and Drop Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Find and Replace. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Automatic Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Add Code Folding Markers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Advanced Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Set Preferences for the Script Editor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Working with the Log. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Show the Log in the Script Window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Save the Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Debug or Profile Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Debugger and Profiler Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Work with Breakpoints. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 View Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Work with Watches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Modify Preferences in Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Persistent Debugger Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Examples of Debugging and Profiling Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Chapter 4 Scripting Guide Scripting Tools Using the Script Editor 55 Using the Script Editor The script editor provides a friendly environment for writing and reading JSL scripts. Figure 4.2 shows basic features such as syntax coloring, inline commenting, and automatic formatting. Other common programming options are described later in this section. Script editor features are also available in the log window and anywhere else that you can edit or write a script (for example, in the Scripting Index or Application Builder). Figure 4.2 The Script Editor Run a Script To run an entire script, select Edit > Run Script. To run specific lines in a script, select those lines and then select Edit > Run Script. To run specific lines that are not adjacent, hold down the Control key, select the lines, and then select Edit > Run Script. On Windows, you can also click in a line or select several lines and press ENTER on your numeric keypad. Run the script automatically when you open it by using one of the following methods: • Type //! on the first line. • Include Run JSL(1) in the Open() statement: 56 Scripting Tools Using the Script Editor Chapter 4 Scripting Guide Open( "$SAMPLE_SCRIPTS/scoping.jsl", Run JSL( 1 ) ); Stop a Script To stop the script, press ESC on Windows (or COMMAND‐PERIOD on Macintosh). You can also select Edit > Stop Script. On Macintosh, Edit > Stop Script is available only when the script is running. Edit a Script To edit a script on Windows, press the Insert key. You can then type directly over (overwrite) any existing JSL code. Note that this feature is not available on Macintosh. Color Coding JMP applies the following colors in the script window: • black for text, identifiers (JSL functions), braces, and user macros • white for the script editor background • gray for the Debugger background, disabled background, and guides • green for comments • purple for strings • teal blue for numbers • dark blue for operator symbols, the first keyword, and JSL objects • medium blue for operator names, second and third keywords, and macros • red for unknown objects Customize colors in the preferences. See “Set Preferences for the Script Editor” on page 63. Auto Complete Functions If you do not remember the exact name of a function, use auto completion to see a list of functions that match what you have typed so far. Type part of the name, and then press CTRL‐SPACE on Windows (OPTION‐ESC on Macintosh). Suppose that you want to clear your JSL variables, but do not remember the command. You can type clear and then press CTRL‐SPACE, to see a list of possible clear commands. Select the command that you want to insert. Chapter 4 Scripting Guide Scripting Tools Using the Script Editor 57 Figure 4.3 Autocomplete Example Tooltips If you are using a function and do not remember the syntax or need more information about it, place the cursor over it to see a brief explanation. This works only with JSL function names, not platform commands, messages, or user‐created functions. JSL function names are colored blue in the script editor. The tooltip shows the syntax, arguments, and a brief explanation of the function (Figure 4.4). The tip also appears in the script editor window status bar. Figure 4.4 Tooltip for a JSL Function After running a script, you can also place the cursor over variable names to see their current value. To turn off variable tooltips, deselect Preferences > Script Editor > Show Variable Value Tips. To turn off function tooltips, deselect Preferences > Script Editor > Show Operator Tips. Example of a Tooltip for a JSL Variable 1. Enter and run the following line in a script window: my_variable = 8; 2. Hover over the variable name after you run the line. A tooltip shows the name of the variable and its value: 8. 3. Enter and run the following line: my_variable = "eight"; 4. Hover over the variable name after you run the line. A tooltip shows the name of the variable and its value: “eight”. 58 Scripting Tools Using the Script Editor Chapter 4 Scripting Guide Split a Window You can split the Script Editor window into two vertical or horizontal windows. This feature allows you to independently scroll through your code in two different places and edit the contents in both. When you make a change in one window, the change is immediately reflected in the other window. • To split an open Script Editor window, right‐click in the window and select Split > Horizontal or Vertical. • To revert back to a single window, right‐click and select Remove Split. Figure 4.5 Example of Splitting a Window Horizontally Chapter 4 Scripting Guide Scripting Tools Using the Script Editor 59 Match Parentheses, Brackets, and Braces The script editor helps you match fences (or parentheses, square brackets, and curly braces) in the following ways: • The matching closing fence is added when you type an opening fence. • When you place your cursor next to either an opening or closing fence, the fence and its match are highlighted in blue. If the fence does not have a match, it is highlighted in red. • If you double‐click a fence, everything between the matching fence is selected (including the fences). • If you put your cursor within an expression and press CTRL‐] on Windows (COMMAND‐B on Macintosh), the entire expression is selected. Fences that enclose the expression are included. Repeat this process to highlight the next‐higher expression. Figure 4.6 shows an example. Figure 4.6 Each Step in Matching Fences When you type an opening brace, JMP adds the closing brace. Enter code between the braces, type the closing brace, and then your cursor automatically moves after the closing brace that JMP added. This prevents you from accidentally adding an unnecessary closing brace. You can turn on and off the auto completion of braces in the JMP preferences. See “Set Preferences for the Script Editor” on page 63 for details. Select a Rectangular Block of Text To select a rectangular block of text, hold down the ALT key and drag your cursor from the starting point to the end of the block. You can either copy or cut the text enclosed in the block. Suppose that you want to the select all of the following code except for the comment marks. 60 Scripting Tools Using the Script Editor Chapter 4 Scripting Guide // Y( :Y ), // X( :X ), Select a rectangular portion beginning with Y. When you paste, you get the following code: Y( :Y ), X( :X ), The rectangular selection inserts returns where needed to maintain the structure of the text. Select Get Menu Item State on both lines in the following example. bb << Get Menu Item State(1), bb << Get Menu Item State(2), When you paste, a return is inserted at the end of each line. Get Menu Item State Get Menu Item State Select Fragmented Text To select text that is not contiguous, hold down the Ctrl key on Windows or Command key on Mac and drag your cursor over the text. Continue this action for any other text that you want to select. You can then copy and paste your selection into a new script or you can run the selected text. Text will be pasted or run in the order it was selected. Drag and Drop Text You can drag and drop text within a script editor window or between windows or from a data table into a script editor window. On Windows, pressing CTRL before dragging and dropping copies the text. On Macintosh, the text is copied by default. Drag and drop text as follows: • Select a row or column, pause, and then drop it into the script editor window. • Double‐click text in a text field and then drop it into the script editor window. Examples are text in a data table cell and any other selectable text. On Windows, you can also drag and drop text into a minimized window. 1. Drag the text over the Home Window button in the lower right corner of the window. The Home Window appears. 2. In the Home Window list, drag the text over the destination window. That window appears. 3. Drop the text where you want it. Chapter 4 Scripting Guide Scripting Tools Using the Script Editor 61 Find and Replace Many find and replace options are available in the script editor, including the support of regular expressions. For example, searching with the following regular expression: get.*name returns messages such as “Get Button Name”, and “GetFontName”. Basic regular expressions such as ^ and $ (which match the start of line and end of line) and \n (which matches a carriage return) are also supported. See the Using JMP book for details about the Search options. Automatic Formatting The script editor can format a script for easier reading. Any generated script (for example, by saving a platform script) is automatically formatted with tabs and returns in appropriate places. You can also reformat individual scripts that are difficult to read (for example, scripts in which all commands are strung together with no whitespace characters). From the Edit menu, select Reformat Script. Tip: This command alerts you if your script is badly formed (for example, if your parentheses are not matched). Add Code Folding Markers You can add code folding markers that show the beginning and the end of the code block, allowing you to collapse and expand code inside stand‐alone functions. To turn on this feature, select JSL code folding in the Script Editor preferences. Then you can expand and collapse blocks of code by right‐clicking on a script and selecting Advanced > Expand All or Collapse All. After you select this preference, Function and Expr expressions are foldable. See “Add More Folding Keywords” on page 62 for details about adding folding markers to other expressions. 62 Scripting Tools Using the Script Editor Chapter 4 Scripting Guide Figure 4.7 Code Folding Markers Shown in a Script By default, code does not remain collapsed after you save the script and restart JMP. To save the state of the folded code, select Save and restore document state information in the Script Editor preferences. Add More Folding Keywords Custom code folding is supported for other stand‐alone functions as shown in the following example: {"If", "For", "For Each Row", "While", "Try", "New Window", "V List Box", "H List Box"} JMP supports multiple keyword lists. A system administrator can define a set of keywords in jmpKeywords.jsl and save the script in C:\ProgramData\SAS\JMP\ or designated directory listed below. You save your version of jmpKeywords.jsl in your C:\Users\ \Documents\ folder. JMP merges all keyword lists from the designated directories. Note: Path names in this section refer to the JMP folder. In JMP Pro, the folder is named “JMPPro”. In JMP Shrinkwrap, the folder is named “JMPSW”. On Windows, the following directories are examined in the order listed: • C:\ProgramData\SAS\JMP\ \ • C:\ProgramData\SAS\JMP\ • C:\Users\ \AppData\Roaming\SAS\JMP\ \ • C:\Users\ \AppData\Roaming\SAS\JMP\ • C:\Users\ \Documents\ On Macintosh, the following directories are examined in the order listed: • /Library/Application Support/JMP/ / • /Library/Application Support/JMP/ • ~/Library/Application Support/JMP/ / • ~/Library/Application Support/JMP/ • ~/Documents/ Chapter 4 Scripting Guide Scripting Tools Using the Script Editor 63 Note that jmpKeywords.jsl is stored in the designated JMP directory, even if you are using JMP Pro. Notes: • The list in jmpKeywords.jsl is case insensitive. • Code folding is not supported for messages, platforms, user‐defined functions, and comments. • After you edit and save the list in jmpKeywords.jsl, turn the Allow additional code folding keywords preference off and then back on for the changes to take effect. Messages in the log indicate that the keywords were loaded. Advanced Options Right‐clicking on selected text in the Script Editor provides the following Advanced options: Option Description Expand All (Appears only if JSL code folding is on) Expands all blocks of code. Collapse All (Appears only if JSL code folding is on) Collapses all blocks of code. Comment Block Makes the selected text comments. Uncomment Block Uncomments the selected comments. Make Uppercase Changes all selected text to uppercase. Make Lowercase Changes all selected text to lowercase. Set Preferences for the Script Editor In the JMP preferences, customize the script editor settings such as the font, colors, and spacing options. Setting the Fonts 1. Select File > Preferences. 2. Select the Fonts group. 3. Click Mono to set the font for the script editor. For more details about font preferences, see the Using JMP book. 64 Scripting Tools Using the Script Editor Chapter 4 Scripting Guide Figure 4.8 Changing the Font Properties for Script Windows Set Script Editor Preferences Select File > Preferences > Script Editor to further customize the editor. Preference Description Use tabs Select this option to enable tabs in your scripts. This option is selected by default. Clear this option to replace any tab that you type with spaces. Tab width Enter how many spaces a tab should indent. If you have disabled tabs, any tab you type is replaced with the number of spaces specified. The default value is 4. Extra space at bottom of document Select this option to enable scrolling up from the last blank lines of a script. This option is selected by default on Windows and deselected on Macintosh. Chapter 4 Scripting Guide Scripting Tools Using the Script Editor 65 Preference Description Auto-complete parentheses and braces Select this option to enable the script editor to automatically add closing parentheses, square brackets, and curly braces when you type an opening one. This option is selected by default. Show line numbers Select this option to show the line numbers on the left side of the script editor. This option is cleared by default. Show indentation guides Select this option to see faint vertical lines that mark indention. This option is selected by default. Show operator tips Select this option to see tooltips for JSL operators. This option is selected by default. Show variable value tips Select this option to see tooltips for variable values. This option is selected by default. Wrap Text Select this option to always wrap text in the script editor. This option is off by default. Show embedded log on script window open Select this option to have an embedded log window appear in the scripting window when editing or running scripts. This option is deselected by default. Color unknown object messages Select this option to cause the script editor to color object messages that are not defined for the target object. Unknown object messages will appear in the color specified by Message unknown color. Note: This option can affect the performance of the JSL editor due to the amount of effort to look up message names in context. Save and restore document state information Saves the state of collapsed and expanded code, and restores that state when the script is reopened. Spaces inside parentheses Select this option to cause the script editor to add spaces between parentheses, brackets, and braces and their contents for automatically formatted scripts. This is on by default. Spaces in operator names Select this option to cause the script editor to add spaces between words within operator names. For example, turning on this option results in New Window instead of NewWindow. This option is selected by default. 66 Scripting Tools Working with the Log Chapter 4 Scripting Guide Preference Description JSL code folding Select this option to use code folding markers in the script editor, which mark the opening and closing of Function() and Expr() expressions. You can expand and collapse these marked blocks of code. This option is off by default. You can also choose the appearance of the marker using the JSL code folding marker menu. Select Allow additional code folding keywords to enable using additional keywords for folding markers in the script editor. See “Add More Folding Keywords” on page 62 for details. Color selection To set your own color for any of the listed types, click the color box and select your color. See “Color Coding” on page 56 for details on default settings. For more details about script editor preferences, see the Using JMP book. Working with the Log As you run a script, the output appears in the log window. The actual script is shaded in the log, and the output appears beneath it (Figure 4.9). Figure 4.9 The Script Window (left) and the Log Window (right) Syntax and compatibility errors are reported in the log, including the line number and code that JMP could not process (Figure 4.10). Chapter 4 Scripting Guide Scripting Tools Working with the Log 67 Figure 4.10 Syntax Error Message Open the log by selecting View > Log (Window > Log on Macintosh). Tips: • On Windows, you can control when the log opens: when JMP starts, when text is written to the log, or only when you open it. Select File > Preferences > Windows Specific to change the Open the JMP Log window setting. • To omit compatibility warnings from the log, deselect Show log warnings for JSL compatibility changes in 12 in the JMP General preferences. Show the Log in the Script Window You can view the log inside the script window by right‐clicking and selecting Show Embedded Log. This option makes it easy to edit and run a script, quickly see the results of your changes, and then continue to develop the script. The embedded log always appears in the Scripting Index script window but is not available in Application Builder and the Debugger. Save the Log You can also save logs as text files, which can be viewed with any text editor. Double‐clicking a log text file opens it in your default text editor, not in JMP. 1. Make the log window active (click the Log window to make it the front‐most window). 2. From the File menu, select Save or Save As. 3. Specify a filename, including the extension .txt on Windows. On Macintosh you cannot save a log as a .txt file. .jsl is appended to the file name. 4. Click Save. 68 Scripting Tools Debug or Profile Scripts Chapter 4 Scripting Guide Debug or Profile Scripts In an open script, click the Debug Script button (or select Edit > Debug Script) to show the script in the JSL Debugger window. You can also use a keyboard shortcut: • Press CTRL + SHIFT + R (Windows). • Press SHIFT + COMMAND + R (Macintosh). The JSL Debugger helps identify the point at which a script causes an error or fails. Rather than commenting out portions of the script or adding Print() expressions, you can use the Debugger to find the problem. Once the JSL Debugger appears, you can continue in this mode, or you can click the Profile JSL Script button to move into the JSL Profiler mode. The JSL Profiler helps with optimization. You can profile your scripts during execution to see how much time is spent executing particular lines or how many times a particular line is executed. Tip: To debug a script automatically when you open it, include Run JSL(1) in the Open() statement: Open( "$SAMPLE_SCRIPTS/scoping.jsl", Run JSL( 1 ) ); Debugger and Profiler Window The Debugger opens in a new instance of JMP (Figure 4.11). The original instance is inoperable until the script produces something that requires interaction. At that point, the Debugger window becomes inoperable until you perform whatever action is required. Then control is returned to the Debugger. Close the Debugger to work again in the original instance of JMP. Chapter 4 Scripting Guide Scripting Tools Debug or Profile Scripts 69 Figure 4.11 The Debugger Window Use the buttons at the top to control the Debugger or the JSL Profiler. One or more scripts that you are debugging or profiling are shown in tabs. If your script includes other scripts, each one opens in a new tab. Tabs in the bottom portion of the Debugger provide options to view variables, namespaces, the log, and the current execution point; work with breakpoints; and set options. Using the Execution Buttons Use the buttons at the top to control execution of the script within the Debugger or JSL Profiler. Table 4.1 Description of the Debugger Buttons Button Button Name Action Run Runs the script in the Debugger until it reaches either a breakpoint or the end of the script. Run without breakpoints Runs the script through the end without stopping. Run profiler 70 Scripting Tools Debug or Profile Scripts Chapter 4 Scripting Guide Table 4.1 Description of the Debugger Buttons (Continued) Button Button Name Action Break All If the script is busy, click Break All to stop all action in the script and return to the Debugger or JSL Profiler, for example, if you are in a very long loop. The Debugger or JSL Profiler may not be able to break execution if the executing script is waiting on some interactive user action, such as completing a dialog or interacting with an opened window. Stop Stops debugging the script and exits the Debugger or the JSL Profiler. Restart Closes the current Debugger session and opens a new session. Step Into Lets you step into a function or an included file. Otherwise, it behaves the same as Step Over. Step Over Runs all expressions on a single line, or a complex expression that spans multiple lines, without stepping into a called expression, function, or Include() file. Step Out Runs the current script or function to a breakpoint or the end and returns to the calling point. If you are in the main script and the Debugger reaches the end, a message appears: Program execution terminated. The Debugger remains open in order for you to inspect the final program conditions. Profile JSL Script Opens the JSL Profiler. (Press the Run profiler button to start the JSL Profiler.) Use the JSL Profiler to see how much time is spent executing particular lines or how many times a particular line is executed. Note the following: Show Profile by Line Count • You can switch back and forth between the Debugger and JSL Profiler modes only prior to the start of the program. • Some of the debugger buttons are disabled when profiling. • All breakpoints are disabled when running in the JSL Profiler mode. Shows the number of times each line is executed. Chapter 4 Scripting Guide Scripting Tools Debug or Profile Scripts 71 Table 4.1 Description of the Debugger Buttons (Continued) Button Button Name Action Show Profile by Time Shows how much time is spent executing a line. Show Profile by Count For line counts, shows the number of times the line is executed. For time, shows the number of microseconds (or milliseconds or seconds) the line takes to complete. Show Profile by Percent For line counts, shows the individual line count divided by the total line count. For time, shows the percentage of time spent on an individual line (line time/total time*100). Time Units Sets the time unit to microseconds, milliseconds, or seconds. Available in the JSL Profiler after you click the Run profiler button . Color Theme Sets the color of the shading for the JSL Profiler. Available in the JSL Profiler after you click the Run profiler button . Variable Lists The tabs on the bottom left of the Debugger let you examine global variables, local variables, watch variables, and variables within namespaces. Globals The Globals tab lists all global variables and updates their values as you step through the script. Each variable is added as it is initialized. If there are already global variables defined from running earlier scripts, they will be listed with their current values when you start the Debugger. See “View Variables” on page 75. Locals The Locals tab lists all variables by scope and updates their values as you step through the script. Select a scope in the menu. See “View Variables” on page 75. If there is a particular variable or value of an expression whose values you want to watch as you step through the code, you can add them here. This is particularly useful if your script uses many variables that might be hard to watch in the Globals or Locals lists. See “Work with Watches” on page 75. Watch As namespaces are defined, they are added to the menu. Select a namespace to view any variables and their values used within the namespace. See “View Variables” on page 75. Namespaces Debugger Options The tabs on the bottom right of the Debugger let you view the call stack, work with breakpoints, set options, and view the log. 72 Scripting Tools Debug or Profile Scripts Chapter 4 Scripting Guide Call Stack The call stack lists the current execution point in scripts and functions. The main script is always the first script listed. If you call a function, the function is added on top of the calling script. Likewise, any included files are added to the top of the list as you step through them. When you exit any function or script, it is removed from the list and you return to the next one in the list. The current line numbers are updated as you step through. Double‐click a row in the call stack to move the cursor to the specified line. Breakpoints Add, edit, delete, and disable or enable breakpoints. See “Work with Breakpoints” on page 72. You can also double‐click a row on the Breakpoints tab to move the cursor to the specified line. Options Set the Debugger preferences interactively on this tab. See “Modify Preferences in Debugger” on page 76. Log The log from the script that you are debugging is shown on this tab. Work with Breakpoints A breakpoint interrupts the execution of a script. Although you can step through a script line by line, this can be tedious and lengthy for a long or complex script. You can set breakpoints at places of interest and simply run the script in the Debugger. The script is run normally until a breakpoint is reached. At the breakpoint, the Debugger stops executing the script so you can look at the values of variables or start stepping line by line. JMP preserves breakpoints across sessions. So when you close and reopen JMP, the breakpoints still appear. Tip: Turn on line numbers by right‐clicking in the script and selecting Show Line Numbers. You can also show line numbers by default in all scripts by modifying the Script Editor preferences. Create a Breakpoint When creating a breakpoint, you can specify settings such as conditions and break behavior. To do so, click on the Breakpoints tab, and then enter the breakpoint information. Otherwise, create a quick breakpoint by doing one of the following: • In the Debugger margin, click on the appropriate line (to the right of the line number if displayed). • In the Debugger margin, right‐click in the margin where you want the breakpoint and select Set Breakpoint. The red breakpoint icon appears where you inserted the breakpoint and on the Breakpoints tab. Chapter 4 Scripting Guide Scripting Tools Debug or Profile Scripts 73 Delete Breakpoints Do one of the following: • In the Debugger margin, click the breakpoint icon. • In the Debugger margin, right‐click the breakpoint icon and select Clear Breakpoint. • On the Breakpoints tab, select the breakpoint and then click • On the Breakpoints tab, click breakpoints). . to delete all breakpoints (not just the selected The red breakpoint icon is removed, and the breakpoint no longer appears on the Breakpoints tab. Disable and Enable Breakpoints Disabling a breakpoint is helpful when you potentially fix a problem and then want to see whether the script will run correctly past that breakpoint. You can then enable the breakpoint when necessary rather than recreating it. Do one of the following: • In the Debugger margin, right‐click the breakpoint icon and select Enable Breakpoint or Disable Breakpoint. • On the Breakpoints tab, select or deselect the breakpoint’s check box. • On the Breakpoints tab, click to disable or enable all breakpoints. A disabled breakpoint turns white; enabled breakpoints are shaded red. Specify and Clear Conditional Expressions on Breakpoints Setting a condition on a breakpoint is an alternative to single‐stepping through code. Rather than single‐step and view the variables for each expression, you specify that the script break only when a condition is met. Then you can step through the code and figure out where the problem arises. Suppose that a calculation in your script is incorrect, and you suspect the problem occurs when i==19. Set a conditional breakpoint for i==18. The Debugger will run until that condition is met, then you can step through the code to identify the problem. Specify a Breakpoint Condition 1. Right‐click the breakpoint icon and select Edit Breakpoint. 2. On the Condition tab, select Condition and enter the conditional expression. 3. Specify whether to break when the expression Is true or Has Changed. 4. Click OK. 74 Scripting Tools Debug or Profile Scripts Chapter 4 Scripting Guide Disable or Enable a Condition 1. Right‐click the breakpoint icon and select Edit Breakpoint. 2. On the Condition tab, deselect or select Condition. Delete a Condition On the Breakpoints tab, click in the breakpoint’s Condition field and press DELETE. Specify Break Options Right‐clicking the breakpoint and selecting Edit Breakpoint provides a quick way to manage breakpoint behavior. Alternatively, select the breakpoint on the Breakpoints tab and click . Both methods display the Breakpoint Information window, where you customize settings on the Hit Count and Action tabs. Change the Hit Count You can control the number of times a breakpoint must be hit and when the break occurs. For example, to break when the condition is met twice, select break when the hit count is equal to and type 2 on the Hit Count tab. Define an Action You also have the option of defining a JSL expression or script that the Debugger executes when a breakpoint is hit and execution has stopped. This script is called an action. On the Action tab, enter the JSL expression to be executed. Run the Script to the Cursor When you right‐click and select Run To Cursor, all expressions before the location of the cursor are executed. Select this option when you only want to see values up to the current line. To see values when each expression is executed, use the stepping options. Tips for Setting Breakpoints • If you do not want to watch for errors in a specific loop, set a breakpoint after the loop ends. The Debugger will hit the next breakpoint rather than stepping through each line of the loop. • Avoid inserting a breakpoint in lines that do not trigger an action (such as comments, blank lines, and end parentheses). Debugger will not break on these lines. • When you insert breakpoints, close Debugger, and edit the script, the breakpoints remain on the original line numbers. You might need to delete and then reinsert the breakpoints. Chapter 4 Scripting Guide Scripting Tools Debug or Profile Scripts 75 • Breakpoints are remembered across Debugger sessions. This means that your breakpoints list includes breakpoints that have been set in all scripts, not just the script that you are currently debugging. • Breakpoints are remembered by the Debugger session, not by each script. This means that breakpoints are listed even for scripts that have been moved or deleted. • On the Breakpoints tab, click to remove all breakpoints in scripts whether they are currently open or not, or for scripts that no longer exist. View Variables The variables lists are populated as they appear in the script. Their values are updated every time the script changes them. If you are uncertain why a variable has a particular value when you run your script, you can watch its value at every step to see what happens. You can also assign the variables whatever value you want. For example, if you are stepping through a For() loop but are interested only in what happens starting with a particular iteration, you can assign your iterating variable that value. Step through the first part of the loop that initializes the iteration variable and then assign it the value that you want in the variable list at the bottom. Then when you step through, the loop begins executing at that point. Tips for Managing Variables • If you have run several scripts using the global scope, you might want to clear or delete global variables. This makes the list of variables in the Debugger shorter and relevant. Use the Delete Symbols() function to do so. You can also close JMP and restart to clear the space. • If your script uses so many variables that they are difficult to find and watch in the variable lists, add watches for the specific variables in which you are interested. Work with Watches JMP preserves the Watch variables across sessions. So when you close and reopen JMP, the Watch variables are still listed on the Watch tab. Create a Watch • On the Watch tab, click and enter the value in the window. • In the Debugger, right‐click the line that you want to watch, select Add Watch, and then enter the variable name in the window. • In the Debugger, place the cursor in or next to a variable name (or select the variable name), right‐click, and select Add Watch. 76 Scripting Tools Debug or Profile Scripts • Chapter 4 Scripting Guide On the Watch tab, enter the variable in an empty Variable field. Modify a Watch Do one of the following on the Watch tab to enter a new value: • Select the watch and click . • Click in the Variable field and enter a new value. Delete Watches Do one of the following on the Watch tab to delete watches: • Select the watch and then click • Click . to remove all watches. Modify Preferences in Debugger The Debugger lets you change preferences as you work in the Debugger. Select the Options tab to find the following settings: Show Line Numbers Shows or hides the line numbers for the script in the Debugger. Break on Multiple Statements Per Line Stops executing the script between each expression in a single line. Breaks when the script executes the Throw() function. For example, Throw() might be enclosed in a Try() expression. The Debugger breaks on Throw() instead of continuing through the rest of the expression. This lets you identify where the problem occurred in the script and then return to debugging. Break On Throw Break On Execution Error Stops executing the script when the error occurs rather than closing the Debugger. Warn On Assignment In Condition Shows a warning when you enter a breakpoint condition that contains the assignment. For example, if you have a breakpoint on x = 1 and add the condition x = 1 to the breakpoint, you are prompted to verify the assignment of x. Enter Debugger Upon Termination Keeps the Debugger open after a JSL program terminates execution. On by default, this option lets you examine attributes of the executed program. Persistent Debugger Sessions JMP saves all breakpoints and watches until you delete them. Other user‐specific settings, such as column widths on the tabs and the Debugger window size, persist between sessions of JMP. Chapter 4 Scripting Guide Scripting Tools Debug or Profile Scripts 77 These settings are stored in a file named JMP.jdeb, the location of which is defined in the USER_APPDATA variable: • Windows 7: "/C:/Users/ /AppData/Roaming/SAS/JMP/ /" • Macintosh: "/Users/ /Library/Application Support/JMP/ /" As usual, the values of local variables, global variables, and namespaces clear when you close and reopen JMP. Note: On Windows, the paths differ based on the JMP edition. In JMP Pro, the path refers to “JMPPro”. In JMP Shrinkwrap, the path refers to “JMPSW”. Examples of Debugging and Profiling Scripts This section includes examples of setting breakpoints to watch variables; stepping into, over, and out of expressions; watching variables in different scopes and namespaces; debugging interactive scripts; and profiling scripts with the JSL Profiler. Example scripts are located in the Samples/Scripts folder. Tip: Make sure that Show Line Numbers is selected on the Debugger Options tab before proceeding. Using Breakpoints and Watching Global Variables The following example shows how to set a breakpoint in a loop and watch variables change through each iteration of the loop. 1. Open the string.jsl sample script and click the Debug Script button. 2. Click in the margin for line 12 to add a breakpoint (Figure 4.12). You should have a breakpoint for the following expression inside the For() loop: stringFunction(i); 78 Scripting Tools Debug or Profile Scripts Chapter 4 Scripting Guide Figure 4.12 Set the Breakpoint 3. Click Run. The first two expressions are evaluated: ‒ stringFunction is defined as a function. ‒ str is defined as an empty string. Both variables and their types and values have been added to the Globals list. In addition, the For() loop has been evaluated up to the line with the breakpoint, shown in Figure 4.12. ‒ i has been assigned to 0. ‒ i and its value and type have been added to the Globals list. ‒ i has been determined to be less than or equal to 9. ‒ stringFunction() has not yet been called. Figure 4.13 View the Initial Global Variables 4. Click Run again. The script runs until it hits the breakpoint. The results are shown in Figure 4.14. ‒ stringFunction() is called, evaluated, and returns to the loop. ‒ i is incremented and determined to be less than or equal to 9. ‒ In the Globals list, i is now 1 and str is now “0”. Chapter 4 Scripting Guide Scripting Tools Debug or Profile Scripts 79 Figure 4.14 Global Variables at First Breakpoint 5. Click Run again. The script runs until it hits a breakpoint. The results are shown in Figure 4.15. ‒ stringFunction() is called, evaluated, and returns to the loop. ‒ i is incremented and determined to be less than or equal to 9. In the Globals list, i is now 2, and str is now “01”. Figure 4.15 Global Variables at Second Breakpoint You can continue to click Run and watch i and str change with each iteration of the loop. Or, click Run without breakpoints to complete running the script and exit the Debugger. Stepping Into, Over, and Out Step Into, Step Over, and Step Out offer flexibility when your script contains expressions, functions, or includes other JSL files. 1. Open the scriptDriver.jsl sample script and click the Debug Script button. 2. This script writes information to the log, so select the Log tab at the bottom of the Debugger to view the messages. 3. Click Step Over. The first line in the script is evaluated. 4. Click Step Over again. The current expression is evaluated, and the Debugger moves to the following line. In this case, the expression is a few lines long, and it assigns an expression to a variable. 5. Click Step Over again. This expression is several lines long, and assigns a function to a variable. Line 30 calls the expression that was created earlier. 6. Click Step Over. 80 Scripting Tools Debug or Profile Scripts Chapter 4 Scripting Guide The Debugger steps into the expression, running it line by line. 7. Continue clicking Step Over until the expression ends. The Debugger returns to the line following the expression call. Line 31 calls the function defined earlier. 8. Click Step Over to run the function without stepping into it. The Debugger runs the entire function, and returns to the line following the function call. Line 33 includes another script. 9. Click Step Into. The Debugger opens the script in another tab and waits. 10. Click Step Over. The next line in the included script is run. 11. Click Step Out. The Debugger runs the rest of the included script and returns to the line following the Include() function. Watching Variables in Different Scopes and Namespaces Tabs at the bottom of the Debugger window let you watch variables as they are created and changed. This example shows variables in several scopes and a namespace. 1. Open the scoping.jsl sample script and click the Debug Script button. 2. Click Step Over. The fourth line turns off Names Default To Here. If you run this script again in the same JMP session, this line resets the scoping so that the first variable that is created is in the global scope. 3. Click Step Over. A global variable named x is created. On the Globals tab, x has been added to the list, showing its value as 5 and its type as number. 4. Select the Locals tab, and then select Global from the list of scopes. The global variable x is also shown here. 5. Click Step Over twice. Names Default To Here is turned on, which places the rest of the script into a Here scope. Then a new variable x is created in that scope. Notice that the value of the global variable x has not changed. 6. Select Here from the list on the Locals tab. The local x is listed under Here, with its value and type. Chapter 4 Scripting Guide Scripting Tools Debug or Profile Scripts 81 7. Click Step Over. A Local Here scope is created. A second Here scope is shown in the Locals list. 8. Click Step Over. A new x variable is created in this Here scope. On the Locals tab, select each of the three scopes from the list (Here, Here, and Global) to see three different x variables. 9. Click Step Over. Look in the Debugger’s log to see the output. Notice that here:x scopes to the local here, not the script window’s here. 10. Click Step Over. After writing an empty line to the log, the script exits the Local Here scope. The second Here, along with its’ x variable, has disappeared from the Locals list. 11. Click Step Over. A namespace called “test” is created, with another variable named x. Select the Namespaces tab to see it. 12. Click Step Over and look at the log. 13. Click Step Over to exit the Debugger. Using the Debugger with Interactive Scripts When your script creates interactive elements, the Debugger hands control back to the main instance of JMP so that you can interact with it. When you are finished, control returns to the Debugger. 1. Open the interactive.jsl sample script and click the Debug Script button. 2. Click Step Over twice. The New Window expression is evaluated, and a modal window waiting for input is created. You might need to move the Debugger window to see the new modal window. 3. Enter two numbers in the Assign X and Y window and click OK. Control is given back to the Debugger. 4. Click Step Over three times and look at the log in the Debugger. The log shows the two new numbers that you entered in the window. 5. Click Step Into to exit the Debugger. Using the JSL Profiler Use the JSL Profiler to see how much time is spent executing particular lines or how many times a particular line is executed. 1. Open the string.jsl sample script. 82 Scripting Tools Debug or Profile Scripts Chapter 4 Scripting Guide 2. Click the Debug Script button . 3. Click the Profile JSL Script button . Figure 4.16 Initial JSL Profiler Window 4. Click the Run button to start profiling. The profiler collects information on the number of times a statement is executed and the time it takes to execute it. Time is cumulative and collected each time a JSL statement is executed. Figure 4.17 Profiled Script Window In the left margin, the selected statistics are displayed. Percent of time is displayed by default. Click the Show Profile by Count button to switch to percent of statement counts instead. The left margin is color‐coded to allow for quick identification of problematic performance areas. Chapter 5 JSL Building Blocks Learning the Basics of JSL Studying the syntax and basics of JSL is crucial, whether you are a beginning or an advanced user. Some concepts (such as loops and variables) are common among many scripting languages, but punctuation rules differ in JSL. Figure 5.1 Example of a JSL Script comment multiplication operator concatenate operator quoted text string variables functions Commas separate arguments. Semicolons separate certain expressions. This chapter introduces you to the basic concepts of JSL, from syntax rules and file path conventions to conditions and namespaces. Contents JSL Syntax Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Value Separators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Global and Local Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Local Namespaces. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Named Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Show Symbols, Clear Symbols, and Delete Symbols. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Lock and Unlock Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Rules for Name Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Resolving Unscoped Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Troubleshooting Variables and Column Names. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Troubleshooting Variables and Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Alternatives for Gluing Expressions Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Iterate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Summation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Product . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Break and Continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Conditional Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 If . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Match . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Choose. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Interpolate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Step . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Compare Incomplete or Mismatched Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Inquiry Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Chapter 5 Scripting Guide JSL Building Blocks JSL Syntax Rules 85 JSL Syntax Rules All scripting and programming languages have their own syntax rules. JSL looks familiar if you have programmed in languages such as C and Java. However, rules for punctuation and spaces differ in JSL. The following sections describe JSL syntax rules for the following basic components of the language: • “Value Separators” on page 85 • “Numbers” on page 88 • “Names” on page 88 • “Comments” on page 89 Value Separators Words in JSL are separated by parentheses, commas, semicolons, spaces, and various operators (such as +, –, and so on). This section describes the rules for using these separators and delimiters in JSL. Commas A comma separates items, such as items in a list, rows in a matrix, or arguments to a function. my list = {1, 2, 3}; your list = List(4, 5, 6); my matrix = [3 2 1, 0 -1 -2]; If(Y < 20, X = Y); If(Y < 20, X = Y; Z < 3, A); TableBox( stringColBox("Age",a), NumberColBox("Count",c),...) Note: To glue a sequence of commands into a single argument inside a function, separate each sequence with a semicolon. For more information, see “Semicolons” on page 86. Parentheses Parentheses have several purposes in JSL: • Parentheses group operations in an expression. The following parentheses group the operations in the If() expression. If( Y < 20, X = Y, 86 JSL Building Blocks JSL Syntax Rules Chapter 5 Scripting Guide X = 20 ); • Parentheses delimit arguments to a function. In the following example, parentheses enclose the argument to the Open() function. Open("$SAMPLE_DATA/Big Class.jmp") • Parentheses also mark the end of a function name, even when arguments are not needed. For example, the Pi function has no arguments. However, the parentheses are required so that JMP can identify Pi as a function. Pi(); Note: Be careful that parentheses match. Every ( needs a ), or errors result. The script editor can match fences (parentheses, brackets, and braces). Press CTRL‐] (COMMAND‐b on Macintosh) with your cursor in any part of a script. The editor searches for fences, highlighting the text between the first set of opening and closing fences that it finds. Repeat this process to highlight the next‐higher fence. See “Match Parentheses, Brackets, and Braces” on page 59 in the “Scripting Tools” chapter for an example. Semicolons Expressions separated by a semicolon are evaluated in succession, returning the result of the last expression. In the following code, 0 is assigned to the variable i and then 2 is assigned the variable j. i=0; j=2; You can also use semicolons to join arguments that are separated by commas as shown in the following If() expression. If(x <5, y = 3; z++; ...); The semicolon in other languages is used as an expression terminator character. In JSL, the semicolon is a signal to continue because more commands might follow. For details about separating expressions with semicolons, see “Alternatives for Gluing Expressions Together” on page 104. Semicolons at the end of a script or at the end of a line of arguments are harmless, so you can also think of semicolons as terminating characters. Trailing semicolons are allowed at the end of a script stream and after a closing parenthesis or closing curly brace. In fact, terminating each complete JSL expression with a semicolon helps avoid errors when you copy and paste small scripts into a larger one. The semicolon is equivalent to the Glue() function. See “Operators” on page 90 for more information about semicolons and Glue(). Chapter 5 Scripting Guide JSL Building Blocks JSL Syntax Rules 87 Double Quotes Double quotes enclose text strings. Anything inside double quotes is taken literally, including spaces and upper‐ or lower‐case; nothing is evaluated. If you have "Pi() ^ 2" (inside double quotes), it is just a sequence of characters, not a value close to ten. You do have to be a careful with text strings. Extra spaces and punctuation do affect the output, because text strings inside double quotes are used literally, exactly as you enter them. To have double quotes inside a quoted string, precede each quotation mark with the escape sequence \! (backslash‐bang). For example, run the following script and look at the title of the window: New Window( "\!"Hello\!" is a quoted string.", Text Box( Char( Repeat( "*", 70 ) ) ) ); Table 5.1 Escape Sequences for Quoted Strings \!b blank \!t tab \!r carriage return only \!n linefeed (newline) only \!N inserts line breaking characters appropriate for the host environmenta \!f formfeed (page break) \!0 null character Note: The null character is dangerous to use, because it is typically treated as the end of the string. Be sure to type the number zero, not the letter O. \!\ backslash \!" double quotation mark a. On Macintosh, this escape sequence is CR (carriage return character, hexadecimal ‘0D’). On Windows, this sequence is CR LF (carriage return followed by a linefeed, hexadecimal ‘0D0A’). Sometimes, long passages require a lot of escaped characters. In these cases, use the notation \[...]\ and everything between the brackets does not need or support escape sequences. Here is an example where \[...]\ is used inside a double‐quoted string. jslPhrase = "The JSL to do this is :\[ 88 JSL Building Blocks JSL Syntax Rules Chapter 5 Scripting Guide a = "hello"; b = a|| " world."; show(b); ]\ and you use the Submit command to run it."; Spaces JSL allows whitespace characters inside names; spaces, tabs, returns, and blank lines inside or between JSL words are ignored. This is because most JSL words come from the user interface, and most of those commands have spaces in them. For example, the JSL expression for the Fit Model platform is Fit Model() or FitModel(). Spaces inside an operator or between digits in a single number are not allowed. In these cases, the script generates errors. For example, you cannot put spaces between the two plus signs in i++ (i+ +) or in numbers (4 3 is not the same as 43). Note: Why does JSL allow whitespace characters inside names? For one reason, the names of commands and options match the equivalent commands in JMP menus and windows. Another reason is that data table column names often include spaces. Numbers Numbers can be written as integers, decimal numbers, dates, times, or datetime values. They can also be included in scientific notations with an E preceding the power of ten. For example, these are all numbers: . 1 12 1.234 3E3 0.314159265E+1 1E-20 01JAN98 Note: A single period by itself is considered a missing numeric value (sometimes called NaN for “not a number”). For more information about dates, times, and date‐time values, see “Date‐Time Functions and Formats” on page 130 in the “Types of Data” chapter. See “Currency” on page 142 in the “Types of Data” chapter for details about combining numbers with currency symbols. Names A name is simply something to call an item. When you assign the numeric value 3 to a variable in the expression a = 3, a is a name. Commands and functions have names, too. In the expression Log( 4 ), Log is the name of the logarithmic function. Names have a few rules: Chapter 5 Scripting Guide • JSL Building Blocks JSL Syntax Rules 89 Names must start with an alphabetic character or underscore and can continue with the following: ‒ alphabetic characters (a‐z A‐Z) ‒ numeric digits (0‐9) ‒ whitespace characters (spaces, tabs, line endings, and page endings) ‒ mathematical symbols in Unicode (such as ) ‒ a few punctuation marks or special characters (apostrophes (‘), percent signs (%), periods (.), backslashes (\), and underscores (_)) • When comparing names, JMP ignores whitespace characters (such as spaces, tabs, and line endings). Upper case and lower case characters are not distinguished. For example, the names Forage and for age are equivalent, despite the differences in white space and case. You can still have a name that is any other sequence of characters. If the name does not follow the rules above, it needs to be quoted and placed inside a special parser directive called Name(). For example, to use a global variable with the name taxable income(2011), you must use Name() every time the variable appears in a script: Name("taxable income(2011)") = 456000; tax = .25; Print(tax * Name("taxable income(2011)")); 114000 Name() is harmless when it is not needed. For example, tax and Name("tax") are equivalent. For more information about how JMP interprets names, see “Rules for Name Resolution” on page 97. Comments Comments are notes in the code that are ignored by the JSL processor (or parser). You include comments to describe sections of the script. Comments are also convenient for removing portions of a script temporarily. For example, you can insert comment symbols around code that might be causing an error and then rerun the script. Type the comment symbols around code that you want to comment. The following example shows code commented with /* */ in the middle of a line. When the script is run, JMP considers both expressions to be identical. tax /*percentage*/ = .25; tax = .25; Table 5.2 describes the comment symbols. 90 JSL Building Blocks Operators Chapter 5 Scripting Guide Table 5.2 Comment Symbols Symbol Syntax Explanation // // comment Begins a comment. The comment does not have to be at the beginning of a line, but everything up to the end of the line is a comment. /* */ /* comment */ Begins and ends a comment. This comment can appear in the middle of a line. Script text before and after the comment is parsed normally. //! //! Add //! to the first line of the script, and the script runs automatically when opened in JMP. (In other words, the script editor does not open.) Operators Operators are one‐ and two‐character symbols for common arithmetic actions. Operators come in several varieties: • infix (with arguments on either side, such as + in 3 + 4, or = in a = 7) • prefix (with one argument on its right side, such as !a for logical negation) • or postfix (with one argument on its left side, such as a++ for incrementing a) JSL operators all have function equivalents. To make writing algebraic expressions easier, JSL uses certain special character operators. These operators have the same meaning as if the phrase had been written as a function. For example, the following two expressions are equivalent. Net Income After Taxes = Net Income - Taxes; Assign(Net Income After Taxes, Subtract(Net Income, Taxes)); The assignment operation can be written either as the Assign() function or as an infix operator =. Similarly, subtraction can be done with the Subtract() function or the infix minus sign; they are equivalent inside JMP. Note: Usually white space is ignored in JSL, so that “netincomeaftertaxes” and “net income after taxes” are the same thing. There is one exception: the two‐character operators must not have a space between characters. Always enter the following operators without spaces in between: ||, |/, <=, >=, !=, ==, +=, -=, *=, /=, ++, --, <<, ::, :*, :/, /*, */ Another common operator is the semicolon ( ; ). You use the semicolon to: Chapter 5 Scripting Guide JSL Building Blocks Operators 91 • Separate yet join one expression to another in a programming sequence. The semicolon returns the result of its last argument, so a;b is the same as Glue(a,b). • End an expression. Though the semicolon is permitted at the end of an expression, it is not the expression terminator used in other languages. An expression can contain more than one operator. In these instances, the operators are grouped in order of precedence with decreasing priority. For example, * takes precedence over +: a + b * c So b * c is evaluated first, and then the result is added to a. + takes precedence over -: a + b * c - d So b * c is evaluated, and then the result is added to a. d is then subtracted from the result of a + b * c. Table 5.3 shows operators shaded in order of precedence and each operator’s function equivalent. Table 5.3 Operators and Their Function Equivalents in Order of Precedence Operator Function Syntax Explanation { } List {a,b} List(a,b) Construct a list. [ ] Subscript a[b,c] Subscripts identify specific elements within a data element a, where a could be a list, a matrix, a data column, a platform object, a display box, and so on. Subscript(a,b,c) ++ –– ^ Post Increment a++ Post Decrement a–– Power a^b Post Increment(a) Post Decrement(a) Power(a,b) Power(x) – Minus –a Minus(a) Adds one (1) to a, in place. Subtracts one (1) from a, in place. Raise a to exponent power b. With only one argument, 2 is assumed as the power, so Power(x) computes x2. Reverses sign of a. 92 JSL Building Blocks Operators Chapter 5 Scripting Guide Table 5.3 Operators and Their Function Equivalents in Order of Precedence (Continued) Operator Function Syntax Explanation ! Not !a Not(a) Logical Not. Maps nonzero (or true) values to 0 (which means false). Maps 0 (or false) values to 1 (which means true). * Multiply a*b Multiplies a by b. Multiply(a,b) :* EMult a:*b EMult(a,b) / Divide a/b Divide(a,b) Divide(x) Elementwise multiplication for matrices a and b. (Each element in matrix a is multiplied by each element in matrix b.) Divide(a, b) divides a by b. Divide(x) interprets the argument as a denominator and implies 1 as the numerator, yielding the reciprocal 1/x. :/ EDiv a:/b EDiv(a,b) + Add a+b Add(a,b) – Subtract a–b Subtract(a,b) || Concat a||b Concat(a,b) |/ VConcat matrix1|/matrix2 VConcat(matrix1, matrix2) Elementwise division for matrices a and b. (Each element in matrix a is divided by each element in matrix b.) Adds a and b. Subtracts b from a. Joins two or more strings; two or more lists; and horizontally concatenates matrices. See “Concatenate Lists” on page 172 in the “Data Structures” chapter or the JSL Syntax Reference for details. Vertically concatenate matrices. (Use || or Concat() to horizontally concatenate matrices.) Chapter 5 Scripting Guide JSL Building Blocks Operators Table 5.3 Operators and Their Function Equivalents in Order of Precedence (Continued) Operator :: Index Function Syntax Explanation a::b For matrices, generates the integers from a to b. Index(a,b) (Colons are also used as prefix operators for scoping, where :a means data table column a, and ::a means JSL global variable a. See “Scoping Operators” on page 98 for details.) << Send object << message Send(object, message) Send message to object. == Equal a==b Boolean values for comparisons. They all return 1 if true, 0 if false. Missing values in either a or b causes a return value of missing, which evaluates as neither true nor false. See “Missing Values” on page 117, for treatment of missing values. Equal(a,b)... != Not Equal a!=b Not Equal(a,b)... < Less a Greater a>b Greater(a,b) >= <=, < <, <= & Greater or Equal a>=b Less Equal Less a<=b Stop Script. On Macintosh, Edit > Stop Script is available only when the script is running. Comparing For Loops in JSL to C and C++ The JSL For() loop works just like it does in the C (and C++) programming language, although the punctuation is different. Tip: If you know C, watch out for the difference between JSL and C in the use of semicolons and commas. In JSL, For() is a function where commas separate arguments and semicolons join expressions. In C, for is a special clause where semicolons separate arguments and commas join them. 106 JSL Building Blocks Iterate Chapter 5 Scripting Guide While A related function is While(), which repeatedly tests the condition and evaluates its body script as long as the condition is true. The syntax is: While(condition, body); For example, here are two different programs that use a While() loop to find the least power of 2 that is greater than or equal to x (287). The result of both programs is 512. x = 287; // loop 1: y = 1; While(y < x, y *= 2); Show(y); // loop 2: k = 0; While(2 ^ k < x, k++); Show(2 ^ k); The scripts work like this: x = 287; Sets x to 287. // loop 1 y = 1; Sets y to 1. While( Begins the While() loop. y < x, As long as y is less than x, continues evaluating the loop. y *= 2 Multiplies 1 by 2 and then assigns the result to y. The loop then repeats while y is less than 287. ); Ends the loop. Show(y); Shows the value of y (512). // loop 2 k = 0; Sets k to 0. While( Begins the While() loop. 2 ^ k < x, Raises 2 to the exponent power of k and continues evaluating the loop as long as the result is less than 287. Chapter 5 Scripting Guide JSL Building Blocks Iterate k++ 107 Increments k to 1. The loop then repeats while 2 ^ k is less than 287. ); Ends the loop. Show(2 ^ k); Shows the value of 2 ^ k (512). As with For() loops, Which() loops that always evaluate as true create an infinite loop, which never stops. To stop the script, press ESC on Windows (or COMMAND‐PERIOD on Macintosh). You can also select Edit > Stop Script. On Macintosh, Edit > Stop Script is available only when the script is running. Summation The Summation() function adds the body results over all i values. The syntax is: Summation(initialization, limitvalue, body); For example: s = Summation(i = 1, 10, i); returns 55, the result of 1+2+3+4+5+6+7+8+9+10. The script works like this: s = Sets the s variable to the value of the function. Summation( Begins the Summation() loop. i = 1, Sets i to 1. 10, Sets the limit of i to 10. i All values of i from 1 to 10 are added together, resulting in 55. ); Ends the loop. This behavior is similar to in the Formula Editor. The following expression: Summation(i = 1, N Row(), x ^ 2); is equivalent to the following formula in the Formula Editor: NRow 2 x i = 1 108 JSL Building Blocks Iterate Chapter 5 Scripting Guide Product The Product() function is similar to Summation() except that it multiplies the body results rather than adding them. The syntax is the same as for Summation(). For example: p = Product(i = 1, 5 , i); returns 120, the result of 1*2*3*4*5. In this example, the initial value of i is 1, the upper limit is 5, then all integer values of i up to 5 are multiplied. Here is the equivalent in the Formula Editor: 5 i = 1 i Break and Continue The Break() and Continue() functions give you more control over looping. Break() immediately stops the loop and proceeds to the next expression that follows the loop. Continue() is a gentler form of Break(). It immediately stops the current iteration of the loop and continues with the next iteration of the loop. Break Break() is typically used inside a conditional expression. For example: For(i = 1, i <= 5, i++, If(i == 3, Break()); Print("i=" || Char(i)); ); results in: "i=1" "i=2" The script works like this: For( Begins the For() loop. i = 1, Sets i to 1. i <= 5, As long as i is less than or equal to 5, continues evaluating the loop. i++, Increments i by 1. Note that this step is done after the If loop is evaluated. Chapter 5 Scripting Guide JSL Building Blocks Iterate If( i == 3, Break() 109 Begins the If() loop. If i is equal to 3, breaks the loop. ); Ends the loop. Print( When i equals 3, opens the Print() loop. "i=" Prints the string "i=" to the log. || Places "i=" on the same line as the value that follows. Char(i)); Prints the value of i to the log. The For() loop then repeats until the value of i is less than or equal to 5, breaking and printing only when i is less than 3. ); Ends the loop. Note that when the If() and Break() expressions follow Print(), the script prints the values of i from 1 to 3, because the loop breaks after ʺi=3ʺ is printed. "i=1" "i=2" "i=3" Continue As with Break(), Continue() is typically used inside a conditional expression. For example: For(i = 1, i <= 5, i++, If(i < 3, Continue()); Print("i=" || Char(i)); ); results in: "i=3" "i=4" "i=5" The script works like this: For( Begins the For() loop. i = 1, Sets i to 1. i <= 5, Evaluates 1 as less than or equal to 5. 110 JSL Building Blocks Conditional Functions Chapter 5 Scripting Guide i++, Increments i by 1. Note that this step is done after the If loop is evaluated. If( Begins the If() loop. i < 3, Continue() Evaluates i as 1 and continues as long as i is less than 3. ); Ends the If() loop. Print( When i is no longer less than 3, opens the Print() loop. "i=" Prints the string "i=" to the log. || Places "i=" on the same line as the value that follows. Char(i)); Prints the value of i to the log. The For() loop then repeats until the value of i is less than or equal to 5, continuing and printing only when i is equal to or greater than 3. ); Ends the loop. Conditional Functions JSL provides five functions to evaluate an expression conditionally: If(), Match(), Choose(), Interpolate(), and Step(). If The If() function evaluates the first result expression when its condition evaluates as true (a nonzero or nonmissing value). Otherwise, it evaluates the second result expression. The syntax is: If (condition, result1, result2) For example, the following script returns ʺYoungʺ when the age is less than 12. Otherwise, the script returns ʺYoung at Heartʺ. If (age < 12, "Young", "Young at Heart" ); You can also string together multiple conditions and results. The syntax is: If (condition1, result1, condition2, result2, Chapter 5 Scripting Guide JSL Building Blocks Conditional Functions 111 ..., resultElse); In the preceding example, if condition1 is not true, the function continues evaluating until it finds a true condition. Then that condition’s result is returned. The last result is returned when all conditions are false. And when a value is missing, the missing value is returned. For these reasons, it’s very important to include a default result at the end of the expression. Consider the following example, which recodes gender abbreviations in Big Class.jmp: For Each Row(sex = If( sex == "F", "Female", sex == "M", "Male", "Unknown"); ); The script works like this: For Each Row(sex = For each row in the table, sex is the column that is recoded. If( Begins the If() loop. ); sex == "F", "Female", If the value of sex is F, replaces the value with Female. sex == "M", "Male", If the value of sex is M, replaces the value with Male. "Unknown"); If neither of the above conditions are true, replaces the value with Unknown. If this result were omitted and the value of sex were missing, the script would return a missing value. Ends the loop. You can also put actions and assignments in the result expression. The following example assigns 20 to x, because the first condition (y < 20) is false: y = 25; z = If( y < 20, x = y, x = 20 ); Note: Be careful to use two equal signs (==) for equality tests, not one equal sign (=). An If with an argument such as name=value assigns rather than tests the value. 112 JSL Building Blocks Conditional Functions Chapter 5 Scripting Guide Match You can use the Match() function to make several equality comparisons without needing to rewrite the value to be compared. The syntax is: Match(x, value1, result1, value2, result2, ..., resultElse) For example, the following script recodes gender abbreviations in Big Class.jmp: For Each Row (sex = Match( sex, "F", "Female", "M", "Male", "Unknown"); ); The script works like this: For Each Row(sex = For each row in the table, sex is the column that is recoded. Match( Begins the Match() loop. ); sex, Specifies sex as the match argument. "F", "Female", If the value matches ʺFʺ replace it with “Female”. "M", "Male", If the value matches ʺMʺ, replace it with ʺMale. "Unknown"); If F or M are not matched, replaces the value with ʺUnknownʺ. Ends the loop. This Match() example is a simplified version of the example in “If” on page 110. The advantage of Match() is that you define the comparison value once rather than repeat it in each condition. The disadvantage is that you cannot use expressions with operators as you can with If; the argument sex == "F" returns an error in a Match() expression. With more groups of conditions and results, the value of Match() becomes more apparent. The following script would require many additional lines of code with If(). dt=open("$SAMPLE_DATA/Travel Costs.jmp"); For Each Row(Booking Day of Week = Match(Booking Day of Week, "Sunday", "SUN", "Monday", "MON", "Tuesday", "TUE", "Wednesday", "WED", "Thursday", "THU", "Friday", "FRI", "Saturday", "SAT", "Not Specified"); ); Chapter 5 Scripting Guide JSL Building Blocks Conditional Functions 113 Be careful with the data type of the condition and result. In the preceding example, the conditions and results are both character data. If the data types do not match, JMP automatically changes the column’s data type. The results are not what you want. The following script changes the column’s data type from numeric to character based on the first cell’s data type. The first value, ʺ12ʺ, is replaced with ʺTwelveʺ, and the remaining cells are filled with ʺOtherʺ. dt=open("$SAMPLE_DATA/Big Class.jmp"); For Each Row(age = Match(age, 12, "Twelve", 13, "Thirteen", 14, "Fourteen", 15, "Fifteen", 16, "Sixteen", "Other"); ); When data consists of integers such as 1, 2, and 3, you can save even more typing by using Choose(). See “Choose” on page 113 for more information. Choose The Choose() function shortens scripts even more than Match(), provided the arguments are tested against integers. The syntax is: Choose(expr, result1, result2, result3, ..., resultElse) Suppose you have a data table with a column of numeric values from 1 through 7. If the first cell contains the number 1, the following script returns x = ʺLowʺ. x = (Choose(group, "Low", "Medium", "High", "Unknown" ); ); Show(x); The script works like this: x = Creates the x variable. Choose( Begins the Choose() loop. group, Evaluates the value of group. "Low", If the value of group is 1, return ʺLowʺ. "Medium", If the value of group is 2, return ʺMediumʺ. "High", If the value of group is 3, return ʺHighʺ. 114 JSL Building Blocks Conditional Functions Chapter 5 Scripting Guide "Unknown" Otherwise, return ʺUnknownʺ. ) Ends the loop. ); Closes the x variable. Show(x); Returns the value of x. If the expression evaluates to an out‐of‐range integer (such as 7 when only 4 replacement values are listed), the last result is returned. In the preceding example, ʺUnknownʺ is returned. Notice that If() and Match() require more code to achieve the same results as the Choose function: if(group==1, "Low", group==2, "Medium", group==3, "High", "Unknown"); match(group, 1, "Low", 2, "Medium", 3, "High", "Unknown"); Note: If the data types in the expression do not match, JMP automatically changes the column’s data type. Interpolate The Interpolate() function finds the y value corresponding to a given x value between two points (x1, y1 and x2, y2). A linear interpolation is applied to the values. You might use Interpolate() to calculate missing values between data points. The data points can be specified as a list: Interpolate(x, x1, y1, x2, y2, ...) or as matrices containing the x and y values: Interpolate(x, xmatrix, ymatrix) Suppose that your data set includes the height of individuals from age 20 through 25. However, there is no data for age 23. To estimate the height for 23‐year‐olds, use interpolation. The following example shows the value that you want to evaluate (age 23), followed by matrices for ages (20 through 25) and heights (59 through 75). Interpolate(23, [20 21 22 24 25], [59 62 56 69 75]); returns: 62.5 The value 62.5 is halfway between the y values 56 and 69, just as 23 is halfway between the x values 22 and 24. Notes: Chapter 5 Scripting Guide JSL Building Blocks Compare Incomplete or Mismatched Data 115 • The data points in each list or matrix must create a positive slope. For example, Interpolate(2,1,1,3,3) returns 2. However, Interpolate(2,3,3,1,1) returns a missing value (.). • Interpolate is best used for continuous data, but Step() is for discrete data. See “Step” on page 115 for details. Step The Step() is like Interpolate() except that it finds the corresponding y for a given x from a step‐function fit rather than a linear fit. Use Step() with discrete y values (that is, when the y value’s corresponding x value can be only y1 or y2). However, when the y value’s corresponding x value can fall between y1 and y2, use Interpolate(). As with Interpolate, the data points can be specified as a list: Step(x, x1, y1, x2, y2, ...) or as matrices containing the x and y values: Step(x, xmatrix, ymatrix) Suppose that your data table shows the discount percentage for purchases of $25, $50, $75, and $100. You want to create a graph that shows the discount for a $35 purchase, which the data table does not specify. The following example shows the value that you want to evaluate, 35, followed by matrices for purchases from $25 to $100. Step(35, [25 50 75 100], [5 10 15 25]); returns: 5 If the discounts were on a sliding scale (in this example, between 5 and 10, you would use Interpolate(): Interpolate(35, [25 50 75 100], [5 10 15 25]); returns: 7 As with Interpolate(), the data points must create a positive slope. Compare Incomplete or Mismatched Data Comparing data that contains missing values can return misleading results unless you specify a condition that is always true or use functions such as Is Missing() or Zero Or Missing(). Comparisons of data with mismatched types (numeric versus character) or data in matrices can also be confusing. 116 JSL Building Blocks Compare Incomplete or Mismatched Data Chapter 5 Scripting Guide Table 5.5 shows examples of such comparisons and matrices and explanations of the results. For a review of operators used in comparisons, see “Operators” on page 90. The sections that follow the table provide more details about comparison and logical operators. Note: Matrices must include the same number of columns or rows. Table 5.5 Some Special‐Case Comparison Tests Test Result Explanation m=.; m==1 . An equality test with a missing value returns missing. m=.; m!=1 . An inequality test with a missing value returns missing. m=.; m<1; m>1; and so on . A comparison with a missing value returns missing (unless it could not possibly be true, see next). m=.; 1 /AppData/Roaming/SAS/ JMP/Addins/" • Macintosh: "/Users/ /Library/Application Support/JMP/Addins/" Chapter 6 Scripting Guide Types of Data Path Variables 127 Table 6.1 Predefined Path Variable Definitions (Continued) Variable Path ALL_HOME • • Windows (JMP): "/C:/ProgramData/SAS/JMP/ /" Windows (JMP Pro): "/C:/ProgramData/SAS/JMPPro/ /" DESKTOP DOCUMENTS • Windows (JMP Shrinkwrap): "/C:/ProgramData/SAS/ JMPSW/ /" • Macintosh: "/Library/Application Support/JMP/ /" • Windows: "/C:/Users/ /Desktop/" • Macintosh "/Users/ /Desktop/" • Windows: "/C:/Users/ /Documents/" • Macintosh: "/Users/ /Documents/" GENOMICS_HOME "/ /" HOME • • Windows (JMP): "C:/Users/ /AppData/Roaming/ SAS/JMP/ /” Windows (JMP Pro): "/C:/ProgramData/SAS/JMPPro/ /" • Windows (JMP Shrinkwrap): "/C:/ProgramData/SAS/ JMPSW/ /" SAMPLE_APPS SAMPLE_DATA SAMPLE_IMAGES • Macintosh: "/Users/ /" • Windows: /C:/ /Samples/Apps/" • Macintosh: "/Library/Application Support/ /Samples/Apps/" • Windows: ʺ/C:/ /Samples/Data/" • Macintosh: "/Library/Application Support/ /Samples/Data/" • Windows: "/C:/ /Samples/ Images/" • Macintosh: "/Library/Application Support/ /Samples/Images/" 128 Types of Data Path Variables Chapter 6 Scripting Guide Table 6.1 Predefined Path Variable Definitions (Continued) Variable Path SAMPLE_IMPORT_DATA • Windows: "/C:/ /Samples/Import Data/" • Macintosh: "/Library/Application Support/ /Samples/Import Data/" SAMPLE_SCRIPTS • Windows: "/C:/ /Samples/ Scripts/" • TEMP • Macintosh: "/Library/Application Support/ /Samples/Scripts/" Windows: "/C:/Users/ /AppData/Roaming/ Temp/" USER_APPDATA Changes to JMP preferences, menus, and the Home Window are stored here, along with Debugger session settings. • Macintosh: "/private/var/folders/.../Temporary Items/" • Windows (JMP): "/C:/Users/ /AppData/ Roaming/SAS/JMP/ /" • Windows (JMP Pro): "/C:/ProgramData/SAS/JMPPro/ /" • Windows (JMP Shrinkwrap): "/C:/ProgramData/SAS/ JMPSW/ /" • Macintosh: "/Users/ /Library/Application Support/JMP/ /" Path variable definitions are updated automatically based on the version of JMP you are using. For example, when you run a JMP 9 script in JMP 12, the JMP 12 path variable definitions are used. To see the definition of any path variable, use the function Get Path Variable: Get Path Variable("HOME"); "/C:/Users/ /AppData/Roaming/SAS/JMP/12/" Note that you don’t include a dollar sign for Set Path Variable() or Get Path Variable(). But you must include the dollar sign when using the variable in a script. Trailing Slashes Make sure to include a trailing slash after the path variable. In the following example, the root name "Big Class" is assigned to the dtName variable. The Open expression evaluates $SAMPLE_DATA and the trailing slash and then appends the dtName value along with the file extension .jmp. Chapter 6 Scripting Guide Types of Data Path Variables 129 dtName = "Big Class"; dt = Open("$SAMPLE_DATA/"|| dtName ||".jmp"); The path is interpreted as: C:/Program Files/SAS/JMP/11/Samples/Data/Big Class.jmp Without the slash that follows $SAMPLE_DATA, the path is interpreted as: C:/Program Files/SAS/JMP/11/Samples/DataBig Class.jmp Create and Customize Path Variables You can create your own path variables or override some of the built‐in variables with the Set Path Variable(). In the following example, the path variable is called root. The variable points to the c:/ directory. Set Path Variable("root", "c:/"); To get the value of the new variable, use Get Path Variable(). Get Path Variable("root"); // returns "c:/" Use your path variable as you would other variables. The following expression opens the myimportdata.txt file in the c:/ directory. Open("$root/myimportdata.txt") As with getting path variables, omit the dollar sign when setting path variables. Relative Paths If you plan to use relative paths in variables, you must set the default directory. Then any path not preceded by a drive letter is relative to the default directory. Here is an example: Set Default Directory("c:/users/smith/data"); To return the value of the default directory, use Get Default Directory(). Get Default Directory(); // returns "c:/users/smith/data" So the following expression: Open("cleansers.jmp"); resolves as C:/users/smith/data/cleansers.jmp. File Path Separators In JMP, the preferred file path format is the Portable Operating System Interface (POSIX), or UNIX, format with forward slashes (/) as separators. This means that you do not have to 130 Types of Data Date-Time Functions and Formats Chapter 6 Scripting Guide identify the current operating system in scripts run on both Windows and Macintosh. However, each host still accepts its native format for compatibility. You can a convert file path format from Windows to POSIX (and vice versa) using Convert File Path(). Converting from a POSIX to a Windows path might be useful when you need to output a path to a file or to another application. The syntax is: Convert File Path (path, , , ); For example, the following script converts a POSIX path to a Windows path: Convert File Path("c:/users/smith", windows); //returns c:\users\smith You can substitute a path variable (such as $HOME) for the path inside quotes. Date-Time Functions and Formats A date‐time value consists of any portion of a date or time. The value can be seconds (3388594698), a complete date (such as “Wednesday, May 18, 2011”), the date and time (“05/ 18/2011 8:18:18 PM”), the week number (3), and so on. JMP lets you convert date‐time values to common formats, perform arithmetic on the values, and manipulate the data in a number of ways. Tip: For descriptions of all date‐time functions and their arguments, see the JSL Syntax Reference. Date-Time Values Date‐time values are stored and calculated as the number of seconds since midnight, January 1, 1904. For example: Today(); // returns 3388649872 on May 19, 2011 at 12:00:00 AM As with Today(), the Date DMY() and Date MDY() functions also return month, day, and year arguments as seconds. For example, if it were 12:00:00 a.m. on May 19, 2011, all of the following statements would return the same value: Date DMY(19,5,2011); Date MDY(5,19,2011); Today(); 3388608000 The As Date() function takes the number of seconds and displays it as a date or duration. • Values that represent one year or more are returned as dates: As Date(3388608000); 19May2011 Chapter 6 Scripting Guide • Types of Data Date-Time Functions and Formats 131 Values that represent less than a year are returned as durations. As Date(50000); :0:13:53:20 You can use date‐time values in two ways: • a literal value, for example 19May2011:10:10 • a string, for example "Thursday, May 19, 2011" You can perform arithmetic with date‐time literals, which use the number of seconds as the base number. As Date( 19May2011 + 1 ); 19May2011:00:00:01 Program with Date-Time Functions Table 6.2 shows functions that convert seconds into date‐time values and date‐time values into seconds. Table 6.2 Date‐Time Functions Function Explanation Abbrev Date(date) Returns a string representation for the date supplied. The format is based on your computer’s regional setting. So for the English (United States) locale, the date is formatted like "02/29/2004". Even if you are running JMP in English with a different locale, the locale format is applied. As Date(expression) Formats a number or expression so that it shows as a date or duration in a text window. For example, values that represent one year or more are returned as dates. x = As Date(8Dec2000 + inDays(2)); shows as: 10Dec2000 Values that represent less than a year are returned as durations. As Date(50000); shows as: :0:13:53:20 132 Types of Data Date-Time Functions and Formats Chapter 6 Scripting Guide Table 6.2 Date‐Time Functions (Continued) Function Explanation Date DMY(day, month, year) Returns the specified date expressed as the number of seconds since midnight, 1 January 1904. For example, the second Leap Day of the third millennium is DateDMY(29,2,2004), which returns 3160857600. Date MDY(month, day, year) Returns the specified date expressed as the number of seconds since midnight, 1 January 1904. For example, the second Leap Day of the third millennium is DateMDY(2,29,2004), which returns 3160857600. Day Of Week(date) Returns an integer representation for the day of the week of the date supplied. Weeks are Sunday–Saturday. Day Of Year(date) Returns an integer representation for the day of the year of the date supplied. Day(date) Returns an integer representation for the day of the month of the date supplied. Format(date, "format") Returns the value in the format specified in the second argument. Most typically used for formatting datetime values from a number of seconds to a formatted date. Format choices are those shown in the Column Info dialog box. Also see Table 6.3 “How JMP Interprets Two‐Digit Years” on page 137. Hour(datetime) Returns an integer representation for the hour part of the date-time value supplied. In Days(n) These functions return the number of seconds per n minutes, hours, days, weeks, or years. Divide by these functions to express an interval in seconds as an interval in other units. In Hours(n) In Minutes(n) In Weeks(n) In Years(n) Long Date(date) Returns a string representation for the specified date. The format is based on your computer’s regional setting. So for the English (United States) locale, the date is formatted like "Sunday, February 29, 2004". Even if you are running JMP in English with a different locale, the locale format is applied. MDYHMS(date) Returns a string representation for the date supplied, formatted like "2/29/2004 00:02:20 AM". Chapter 6 Scripting Guide Types of Data Date-Time Functions and Formats 133 Table 6.2 Date‐Time Functions (Continued) Function Explanation Minute(date-time) Returns an integer representation for the minute part of the date-time value supplied. Month(date) Returns an integer representation for the month of the date supplied. InFormat(string, "format") Parse Date(string, "format") Parses a string of a given format and returns datetime value expressed as if surrounded by As Date(), returning the date in ddMonyyyy format. Second(date-time) Returns an integer representation for the second part of the date-time value supplied. Short Date(date) Returns a string representation for the date supplied, in the format mm/dd/yyyy, regardless of locale (for example, "02/29/ 2004"). Time Of Day(date) Returns an integer representation for the time of day of the date-time supplied. Today() Returns the current date and time expressed as the number of seconds since midnight, 1 January 1904. No arguments are accepted, but the parentheses are still needed. Week Of Year(date, ) Returns the week of the year as a date‐time value. Three rules determine when the first week of the year begins. Year(date) • With rule 1 (the default), weeks start on Sunday, with the first Sunday of the year being week 2. Week 1 is a partial week or empty. • With rule 2, the first Sunday begins with week 1, with previous days being week 0. • With rule 3, the ISO‐8601 week number is returned. Weeks start on Monday. Week 1 is the first week of the year with four days in that year. It is possible for the first or last three days of the year to belong to the neighboring year’s week number. Returns an integer representation for the year of the specified date. 134 Types of Data Date-Time Functions and Formats Chapter 6 Scripting Guide Examples of Common Date-Time Functions You can use any function that returns seconds within a function that returns a date‐time. For example, if today is May 19, 2011 and the time is 11:37:52 AM, Today() returns the number of seconds, and the functions that follow show that number of seconds since the base time in different date‐time formats: Today() 3388649872 Short Date(Today()); "05/19/2011" Long Date(Today()); "Thursday, May 19, 2011" Abbrev Date(Today()); "5/19/2011" MDYHMS(Today()); "05/19/2011 11:37:52 AM" The date argument in parentheses can be seconds (or any function that returns seconds), or any date‐time literal value. For example, both of the following expressions return the same value: Long Date(3388649872); Long Date(19May2011); "Thursday, May 19, 2011" Note: Long Date() and Abbrev Date() values are formatted according to your computer’s regional settings. Extract Parts of Dates You can extract parts of date values using the functions Month(), Day(), Year(), Day Of Week(), Day Of Year(), Week Of Year(), Time Of Day, Hour(), Minute(), and Second(), which all return integers. If today is May 24th, 2011, each of the following examples returns the 144th day of the year: Day of Year(Today()); Day of Year(24May2011); Day of Year(Date MDY(5,24,2011)); 144 Example A data table column named Date contains date‐time values that are formatted as "m/d/y". You want to create a column that shows only the time. In the following script, the second column’s formula extracts the time of day from the Date value in the first column. Chapter 6 Scripting Guide Types of Data Date-Time Functions and Formats 135 New Table( "Assembly Tests", Add Rows( 1 ), New Column( "Date", Numeric, Continuous, Format( "m/d/y" ), Set Values( [3389083557] ) ), New Column( "Time", Numeric, Continuous, Formula(Format(Time Of Day( :Date ), "h:m:s")) ) ); Figure 6.1 shows the result. Note that the time of day does not appear in the Date column, because the Format function applies the “m/d/y” format. Figure 6.1 Example of Extracting the Time Rules for Determining the Week of the Year Week of Year() returns the week of the year as a date‐time value. Three rules determine when the first week of the year begins. • With rule 1 (the default), weeks start on Sunday, with the first Sunday of the year being week 2. Week 1 is a partial week or empty. Week Of Year(Date DMY(19,6,2013),1); 25 • With rule 2, the first Sunday begins with week 1, with previous days being week 0. Week Of Year(Date DMY(19,6,2013),2); 24 • With rule 3, the ISO‐8601 week number is returned. Weeks start on Monday. Week 1 is the first week of the year with four days in that year. It is possible for the first or last three days of the year to belong to the neighboring year’s week number. Week Of Year( Date DMY(19,6,2013),3); 25 Arithmetic on Dates You can perform the usual arithmetic operations with date‐time data as with any other numeric data. One option is simple arithmetic, such as subtracting a number from a date‐time value. Another option is writing a formula to perform the arithmetic. 136 Types of Data Date-Time Functions and Formats Chapter 6 Scripting Guide Example The Date column in your data table shows when a customer uses his credit card to buy gas. You want to know how many days elapse between purchases. The following script creates a Days elapsed column. The formula in that column subtracts the Date value in the current row from that of the previous row. New Table("Gas Purchases", Add Rows(3), New Column("Date", Numeric, "Continuous", Format("m/d/y"), Set Values([3392323200 3393532800 3394828800]) ), New Column("Days elapsed", Formula( If(row()==1, ., // returns a missing value for the first row (:Date[row()]-:Date[row() - 1])/in days()))); ); Figure 6.2 shows the result. Figure 6.2 Example of Calculating Date‐Time Values Time Intervals The In Minutes, In Hours, In Days, In Weeks, and In Years functions are used to express time intervals in units rather than seconds. Each of these functions returns the number of seconds associated with a particular period of time. For example, the following expression returns the number of weeks between now and July 4, 2012. (Date DMY(04,07,2012)-Today())/InWeeks(); 55.6559441137566 When the argument for the interval function is empty, JMP counts by 1. You can enter another number to change the count. For example, In Years(10) converts the interval to decades. The following expression returns the number of decades between now and December 31, 2037. (Date DMY(31,12,2037)-Today())/InYears(10); 2.65581440286967 Chapter 6 Scripting Guide Types of Data Date-Time Functions and Formats 137 Two- and Four-Digit Years JMP applies its own algorithms for interpreting and displaying datetime strings rather than supporting operating system‐specific datetime formats. However, JMP uses the datetime separators selected in the Region and Language control panel (Windows) or the Date & Time preferences (Macintosh) to interpret and display dates. Two‐digit years are interpreted according to the current system clock year and JMP rules. For example, when the year in a script is 11, and you run the script after 1990, the year shows as 2011. Long Date(25May11); "Wednesday, May 25, 2011" To avoid ambiguity, enter four‐digit years. The following expression returns 1911 (rather than 2011) as indicated: Long Date(25May1911); "Thursday, May 25, 1911" Table 6.3 explains how JMP interprets two‐digit years. Table 6.3 How JMP Interprets Two‐Digit Years Two-Digit Year Value When it is Evaluated Result Examples Result 00–10 before 1990 (on Windows) 19__ enter 5 in year 1979 1905 20__ enter 5 in year 1991 2005 current century enter 13 in year 1988 1913 enter 13 in year 2024 2013 before or during 1990 (on Macintosh) during or after 1990 (on Windows) after 1990 (on Macintosh) 11–89 (on Windows) any time 11–90 (on Macintosh ) 90–99 (on Windows) before 2011 19__ enter 99 in year 1999 1999 91–99 (on Macintosh ) during or after 2011 20__ enter 99 in year 2015 2099 138 Types of Data Date-Time Functions and Formats Chapter 6 Scripting Guide Note: JMP always displays four‐digit years regardless of the regional settings. If you need to show two‐digit years, use character string functions. See the “Types of Data” chapter on page 123. Date-Time Values in Data Tables Change Date-Time Input and Display Formats In data tables, JMP can accept the input of date‐time values in one format (the input format), store them internally as the number of seconds since the base date, and display them in a different date‐time format. The Informat() and Format() functions give you this control. • Informat() takes a string date‐time value, defines the date format used in that string, and returns the date in ddMonyyyy format. Informat("19May2011 11:37:52 AM","ddMonyyyy h:m:s"); 19May2011:11:37:52 • Format() takes the number of seconds since the base date (or a date‐time function that returns that number) and returns the date in the specified format. Format(3388649872,"ddMonyyyy h:m:s"); "19May2011 11:37:52 AM" Format(Today(),"ddMonyyyy h:m:s"); "19May2011 11:37:52 AM" Suppose that you are entering dates into a column using the d/m/y h:m format, but you want to see the dates in the m/d/y format. The Informat() function defines the input format, and the Format() function defines the display format. For example, New Table("Widget Assembly", Add Rows(1 ), New Column("Date", Numeric, "Continuous", Format("m/d/y" ), Informat("d/m/y h:m" ), Set Values([3126917100] ) ) ); The Format() and Informat() values are shown in the data table’s column properties (Figure 6.3). Note that when you click in the cell to edit it, the date‐time value appears in the input format. When you edit the value, or add a new value, the format specified in the data table column Format list is used to display the value. Chapter 6 Scripting Guide Types of Data Date-Time Functions and Formats 139 Figure 6.3 Example of Date‐Time Display and Input Values Notes: • In a script that converts a column from character to numeric, specify Format() and Informat() to prevent missing values. See “Convert Character Dates to Numeric Dates” on page 657 in the “Common Tasks” chapter for details. • The date‐separator character on your computer might differ from the forward slash (/) character shown in this book. • You can enter time values in 24‐hour format (military time) or with AM or PM designators. Table 6.4 describes the formats used as arguments in date‐time functions or as data table formats. You can also use the formats for the format argument to a Format message to a data column. See “Set or Get Formats” on page 325 in the “Data Tables” chapter. For descriptions of specific date‐time functions, see the JSL Syntax Reference. Table 6.4 Date‐Time Formats Type Format argument Example Date only "m/d/y" "01/02/1999" "mmddyyyy" "01021999" "m/y" "01/1999" "d/m/y" "02/01/1999" "ddmmyyyy" "02011999" "ddMonyyyy" "02Jan1999" "Monddyyyy" "Jan021999" "y/m/d" "1999/01/02" "yyyymmdd" "19990102" 140 Types of Data Date-Time Functions and Formats Chapter 6 Scripting Guide Table 6.4 Date‐Time Formats (Continued) Type Date and time Day number and time Format argument Example "yyyy-mm-dd" “1999-01-02“ "yyyyQq" 1999Q1 "m/d/y h:m" "01/02/1999 13:01" "01/02/1999 1:01 PM" "m/d/y h:m:s" "01/02/1999 13:01:55" "01/02/1999 1:01:55 PM" "d/m/y h:m" "02/01/1999 13:01" "02/01/1999 1:01 PM" "d/m/y h:m:s" "02/01/1999 13:01:55" "02/01/1999 1:01:55 PM" "y/m/d h:m" ‘1999/01/02 13:01’ ‘1999/01/02 1:01 PM’ "y/m/d h:m:s" ‘1999/01/02 13:01:02 ‘1999/01/02 1:01:02 PM’ "ddMonyyyy h:m" "02Jan1999 13:01" "02Jan1999 1:01 PM" "ddMonyyyy h:m:s" "02Jan1999 13:01:02" "02Jan1999 1:01:02 PM" "ddMonyyyy:h:m" "02Jan1999:13:01" "02Jan1999:1:01 PM" "ddMonyyyy:h:m:s" "02Jan1999:13:01:02" "02Jan1999:1:01:02 PM" "Monddyyyy h:m" "Jan021999 13:01" "Jan021999 1:01 PM" "Monddyyyy h:m:s" "Jan021999 13:01:02" "Jan021999 1:01:02 PM" ":day:hr:m" "34700:13:01" ":33:001:01 PM" ":day:hr:m:s" "34700:13:01:02" ":33:001:01:02 PM" "h:m:s" "13:01:02" "01:01:02 PM" "h:m" "13:01" "01:02 PM" Chapter 6 Scripting Guide Types of Data Date-Time Functions and Formats 141 Table 6.4 Date‐Time Formats (Continued) Type Duration Format argument Example "yyyy-mm-ddThh:mm" 1999-01-02T13:01 "yyyy-mm-ddThh:mm:ss" 1999-01-02T13:01:02 ":day:hr:m" “52:03:01” reads fifty‐two days, three hours, and one minute ":day:hr:m:s" “52:03:01:30” reads fifty‐two days, three hours, one minute, and thirty seconds "hr:m" “17:37” reads seventeen hours and thirty‐seven minutes "hr:m:s" “17:37:04” reads seventeen hours, thirty‐seven minutes, and 4 seconds "min:s" “37:04” reads thirty‐seven minutes and 4 seconds Note: The following formats display the date‐time according to your computer’s regional settings. They are available only for the display of dates, not for date input in a data table. Examples are shown for the United States locale. Abbreviated date "Date Abbrev" (Display only) “01/02/1999" Long date "Date Long" (Display only) "Saturday, January 02, 1999" Locale date “Locale Date” (Display only) “01/02/1999" Locale date and time “Locale Date Time h:m” (Display only) “01/02/1999 13:01“ or “01/ 02/1999 01:01 PM“ “Locale Date Time h:m:s” (Display only) “01/02/1999 13:01:02“ or “01/02/1999 01:01:02 PM“ 142 Types of Data Currency Chapter 6 Scripting Guide Currency JMP displays numbers as currency using the Format() function, which uses the following syntax: Format(x,"Currency", <"currency code">, ); Where: • x is a column or a number • "currency code" is an International Standards Organization (ISO) 4217 code • decimal is the number of decimal places To illustrate the Format function: Format(12345.6, "Currency", "GBP", 3); "£12,345.600" If you do not specify the currency code, the currency symbol is based on the computer’s operating system locale. For example, running the following script in a Japanese operating system formats the number with the yen symbol. Format(12345.6, "Currency", 3); "¥12,345.600" If the currency code is not supported by JMP, the currency code string appears before the number. Format(12345.6, "Currency", "BBD", 3); "BBD 12,345.600" Table 6.5 lists the currencies supported in JMP. Table 6.5 Currencies Supported in JMP Code Currency Code Currency Code Currency AUD Australian dollar HKD Hong Kong dollar PHP Philippine peso BRL Brazilian real ILS Israeli new shekel PLN Polish zloty CAD Canadian dollar INR Indian rupee RUB Russian ruble CHF Swiss franc JPY Japanese yen SEK Swedish krone CNY Chinese yuan KRW South Korean won SGD Singapore dollar COP Colombian peso MXN Mexican peso THB Thai baht DKK Danish krone MYR Malaysian ringgit TWD New Taiwan dollar EUR Euro NOK Norwegian krone USD US dollar Chapter 6 Scripting Guide Types of Data Hexadecimal and BLOB Functions 143 Table 6.5 Currencies Supported in JMP (Continued) Code Currency Code Currency Code Currency GBP British pound NZD New Zealand dollar ZAR South African rand Hexadecimal and BLOB Functions JMP can also handle binary (large) objects, commonly called BLOBs. The functions below convert between hexadecimal values, numbers, characters, and BLOBs. Some of the functions are covered in more detail following Table 6.6. These functions are listed in the JSL Syntax Reference. Table 6.6 Hexadecimal and BLOB Functions Syntax Explanation Hex("text") Hex(num) Hex(blob) Returns the hexadecimal codes for the characters in text, number, or blob. Hex To Blob(“hexstring”) Returns a BLOB representation of the hexadecimal code supplied as a quoted string. Hex To Char(“hexstring”, encoding) Returns a character string that corresponds to the hexadecimal code suppled as a quoted string. Char To Hex is an alias. The default encoding supported for the hex code is utf‐8. You can also specify one of these encodings: utf‐16le, utf‐16be, us‐ascii, iso‐8859‐1, ascii‐hex, shift‐jis, and euc‐jp. Hex to Number Returns the number that corresponds to the hexadecimal code suppled as a quoted string. Char To Blob(string) Char To Blob(string, encoding) Converts a string of characters into a binary (blob). Blob To Char(blob) Blob To Char(blob, encoding) The default encoding supported for the hex code is utf‐8. You can also specify one of these encodings: utf‐8, utf‐16le, utf‐16be, us‐ascii, iso‐8859‐1, and ascii‐hex. Converts binary data to a Unicode string. The default encoding supported for the hex code is utf‐8. You can also specify one of these encodings: utf‐8, utf‐16le, utf‐16be, us‐ascii, iso‐8859‐1, and ascii‐hex. 144 Types of Data Hexadecimal and BLOB Functions Chapter 6 Scripting Guide Table 6.6 Hexadecimal and BLOB Functions (Continued) Syntax Explanation Blob Peek(blob, offset, length) Returns a new BLOB that is a subset of the given BLOB that is length bytes long and begins at the offset. Note that the offset is 0‐based. Hex (string) returns the hexadecimal codes for each character in the argument. For example, Hex("Abc") returns "416263" since 41, 62, and 63 are the hexadecimal codes (in ASCII) for “A”, “b”, and “c”. Hex to Char (string) converts hexadecimal to characters. The resulting character string might not be valid display characters. All the characters must be in pairs, in the ranges 0‐9, A‐Z, and a‐z. Blanks and commas are allowed, and skipped. For example, Hex To Char (“4142”) returns "AB" since 41 and 42 are the hexadecimal equivalents of “A” and “B”. Hex and Hex To Char are inverses of each other, so Hex To Char ( Hex("Abc") ) returns "Abc" Hex To Blob(string) takes a string of hexadecimal codes and converts it to a binary object. a = Hex To Blob("6A6B6C"); Show(a); a = Char To Blob("jkl", "ascii~hex") Blob Peek(blob,offset,length) extracts bytes as defined by the arguments from a blob. b = Blob Peek(a,1,2); Show(b); b = Char To Blob("kl", "ascii~hex") b = Blob Peek(a,0,2); Show(b); b = Char To Blob("jk", "ascii~hex") b = Blob Peek(a,2); Show(b); b = Char To Blob("l", "ascii~hex") Hex(blob) converts a blob into hexadecimal. c = Hex(a); Show(c); c = "6A6B6C" Chapter 6 Scripting Guide Types of Data Work with Character Functions 145 d = Hex To Char(c); Show(d); d = "jkl" Concat(blob1,blob2) or blob1 || blob2 concatenates two blobs. e = Hex To Blob("6D6E6F"); Show(e); f = a||e; show(f); e = Char To Blob("mno", "ascii~hex") f = Char To Blob("jklmno", "ascii~hex") length(blob) returns the number of bytes in a blob. g = length(f); show(g); g = 6 Note: When blobs are listed in the log, they are shown with the constructor function Char To Blob("..."). Any hex code outside the ASCII range (space to }, or hex 20 ‐ 7D) is encoded as the three‐character sequence [~][hexdigit][hexdigit]. For example, h= Hex To Blob("19207D7E"); Show(h); i = Hex(h); Show(i); h = Char To Blob("~19 }~7E", "ascii~hex") i = "19207D7E" Char To Blob(string) creates a blob from a string, converting ~hex codes. Blob To Char(blob) creates a string with ~hex codes to indicate non‐visible and non‐ASCII codes. Work with Character Functions This section shows how to use some of the more complex character functions that are described in the JSL Syntax Reference. Concat In the Concat function, expressions yielding names are treated like character strings, but globals that have the name values are evaluated. The following example demonstrates that if you have a stored name value, you need to either use Char before storing it in a global, or Name Expr on the global name. n = { abc }; c=n[1] || "def"; show(c); //result is "abcdef" m=expr(mno); 146 Types of Data Work with Character Functions Chapter 6 Scripting Guide c = m || "xyz"; show(c); //result is an error message that mno is unresolved m = expr(mno); c = Name Expr(m) || "xyz"; show(c); //result is "mnoxyz" m=char(expr(mno)); c=m || "xyz"; show(c); //result is "mnoxyz" Concat Items() converts a list of string expressions into a single string, with each item separated by a delimiter. If unspecified, the delimiter is a blank. Its syntax is resultString = Concat Items ({list of strings}, <“delimiter string”>); For example, a = {“ABC”, “DEF”, “HIJ”}; result = Concat Items(a, “/”); returns “ABC/DEF/HIJ” Alternatively, result = Concat Items(a); returns “ABC DEF HIJ” Munger Munger works many different ways, depending on what you specify for its arguments: Munger(string, offset, find | length, ); Table 6.7 Munger behaviors for various types of arguments Find, length, and replace arguments Example If you specify a string as the find and specify no replace string, Munger returns the position (after offset) of the first occurrence find string. Munger("the quick brown fox", 1, "quick"); 5 Chapter 6 Scripting Guide Types of Data Work with Character Functions 147 Table 6.7 Munger behaviors for various types of arguments (Continued) Find, length, and replace arguments Example If you specify a positive integer as the length and specify no replace string, Munger returns the characters from offset to offset + length. Munger("the quick brown fox",1,5); If you specify a string as the find and specify a replace string, Munger replaces the first occurrence after offset of text with replace. Munger("the quick brown fox", 1, "quick", "fast"); If you specify a positive integer as the length and specify a replace string, Munger replaces the characters from offset to offset + length with replace. Munger("the quick brown fox", 1, 5, "fast"); If you specify a positive integer as the length, and offset + length exceeds the length of text, Munger either returns text from offset to the end or replaces that portion of text with the replace string, if it exists. Munger("the quick brown fox",5,25); "quick brown fox" Munger("the quick brown fox",5,25, "fast"); If you specify zero as the length and specify no replace string, Munger returns a blank string. Munger("the quick brown fox", 1, 0); If you specify zero as the length and specify a replace string, the string is inserted before the offset position. Munger("the quick brown fox", 1, 0, "see "); If you specify a negative integer as the length value and specify no replace string, Munger returns all characters from the offset to the end of the string. Munger("the quick brown fox", 5, -5); If you specify a negative integer for length and specify a replace string, Munger replaces all characters from the offset to the end with the replace string. Munger("the quick brown fox", 5, -5, "fast"); "the q" "the fast brown fox" "fastuick brown fox" "the fast" "" "see the quick brown fox" "quick brown fox" "the fast" 148 Types of Data Regular Expressions Chapter 6 Scripting Guide Repeat The Repeat function makes copies of its first argument into a result. The second (and sometimes a third) argument is the number of repeats, where 1 means a single copy. If the first argument evaluates to a character value or list, the result is that many copies. repeat("abc",2) "abcabc" repeat({"A"},2) {"A","A"} repeat({1,2,3},2) {1,2,3,1,2,3} If the first argument evaluates to a number or matrix, the result is a matrix. The second argument is the number of row repeats, and a third argument can specify the number of column repeats. If only two arguments are specified, the number of column repeats is 1. repeat([1 2, 3 [ 1 2 1 2 1 3 4 3 4 3 1 2 1 2 1 3 4 3 4 3 repeat(9,2,3) [ 9 9 9, 9 9 9] 4],2,3) 2, 4, 2, 4] The repeat function is compatible with the function of the same name in the SAS/IML language, but is incompatible with the SAS character DATA step function, which repeats one more time than this function. Regular Expressions A regular expression is a specification of a pattern frequently used to clean up or extract pieces of data. You can search for a pattern and replace it with a different string or extract specific parts of the string. Define the pattern in the Regex() or Regex Match() function. Regex() Regex() searches for a pattern within a source string and returns a string. It simply identifies a pattern in a string or transforms a string into another string. Regex(source, pattern, ( , ), , ); IGNORECASE disregards case. GLOBALREPLACE repeats the match until the entire string is processed. format is a backreference to the matched group. Regex() returns missing if the match fails. Chapter 6 Scripting Guide Types of Data Regular Expressions 149 Example of Matching a String bus|car is the regular expression (in quotation marks because it is also a string). The expression means match “bus” or “car”. sentence = "I took the bus to work."; vehicle = Regex( sentence, "bus|car" ); "bus" Examples of Replacing a String The third argument in Regex() is a specification of the result string. In the previous example, the value defaults to \0, which means replace everything that was matched. The example could also be written as follows: sentence = "I took the bus to work."; Regex( sentence, "bus|car", "\0" ); "bus" \0 is a backreference to everything that was matched by the regular expression. A more interesting variation uses parentheses to create additional backreferences. sentence = "I took the bus to work."; Regex( sentence, "(.*) bus (.*)", "\1 car \2" ); "I took the car to work." The (.*) before and after bus are part of the regular expression. The parentheses create a capturing group. The . matches any character. The * matches zero or more of the previous expression. As a result, the first parenthesis pair matches everything before bus, and the second parenthesis pair matches everything after bus. The third argument, \1 car \2, reassembles the text; it leaves out bus and substitutes car. See “Backreferences and Capturing Groups” on page 157 for more information. Example of Global Replacement GLOBALREPLACE changes the behavior of Regex(). If the match succeeds, the entire source string is returned with substitutions made for each place where the pattern matches. If there are no matches, an unchanged source string is returned. sentence = "I took the red bus followed by the blue bus to get to work today."; Regex( sentence, "bus", "car", GLOBALREPLACE); "I took the red car followed by the blue car to get to work today." You can also use backreferences. This example starts with a different sentence. sentence = "I took the red bus followed by the blue car to get to work today."; Regex( sentence, 150 Types of Data Regular Expressions Chapter 6 Scripting Guide "(\w*) (bus|car)", "bicycle (not \2) that was \1", GLOBALREPLACE ); "I took the bicycle (not bus) that was red followed by the bicycle (not car) that was blue to get to work today." The \w* matches zero or more word characters and becomes backreference 1 because of the parentheses. bus|car becomes backreference 2 because of the parentheses. The third argument, bicycle (not \2) that was \1, describes how to build the substitution text for the part of the source text that was matched. Notice how the backreferences can be used to swap data positions. This might be useful for swapping the position of first names and last names. Regex Match() Regex Match() returns an empty list with zero elements if the match fails. If the match succeeds, the first list is the text of the entire match (backreference 0). The second list is the text that matches backreference 1, and so on. Regex Match(source, pattern, , ); Unlike Regex(), Regex Match() is case insensitive. Include MATCHCASE for a case‐sensitive match. Include NULL if you want to match case but there is no replacement text. Example of Parsing Name‐Value Pairs The following example parses pairs of names and values. Regex Match( "person=Fred id=77 friend= favorite=tea", "(\w+)=(\S*) (\w+)=(\S*) (\w+)=(\S*) (\w+)=(\S*)" ); {"person=Fred id=77 friend= favorite=tea", "person", "Fred", "id", "77", "friend", "", "favorite", "tea"} The \w+ matches one or more word characters. The \S* matches zero or more characters that are not spaces. In the resulting JSL list, the field names (person, id, friend, favorite) and their corresponding values (fred, 77, "", tea) are separate strings. If the first argument to Regex Match() is a variable and a third argument specifies the replacement value, the matched text is replaced in the variable. Comparing Regex() and Regex Match() Regex() and Regex Match() match a pattern in a given string but return different results. To transforms your string into another string, use Regex(). To identify the substrings that match specific parts of the pattern, use Regex Match(). Chapter 6 Scripting Guide Types of Data Regular Expressions 151 This example shows the efficiency of Regex Match() compared to Regex(). The source is a list of six strings. The goal is to extract portions of those six strings into the subject, verb, and object columns of a data table (Figure 6.4). Figure 6.4 Final Data Table source = {"the cat ate the chicken", "the dog chased the cat", "did ralph like mary", "the girl pets the dog", "these words are strange", "the cat was chased by the dog"}; // Create the data table. dt = New Table( "English 101", New Column( "subject", character ), New Column( "verb", character ), New Column( "object", character ) ); // Iterate through the strings in the list. For( i = 1, i <= N Items( source ), i++, // Assign the result of each match to matchList. matchList = Regex Match( source[i], // Scan each string. Match zero or more characters // and one item in each group. ".*?(cat|dog|ralph|girl).*?(ate|chased|like|pets).*?(chicken|cat|mary|dog)" ); // If matchList has zero items (string 5), don’t add a row // to the table. Put each matched string in separate // data table cells. If( N Items( matchList ) > 0, dt << Add Rows( 1 ); dt:subject = matchList[2]; // Match the first open parenthesis. dt:verb = matchList[3]; // Match the second open parenthesis. dt:object = matchList[4]; // Match the third open parenthesis. ); ); 152 Types of Data Regular Expressions Chapter 6 Scripting Guide Regex Match() returns {"the cat was chased by the dog", "cat", "chased", "dog"} in a single try with each answer in a separate string. Compare this example to a similar one using Regex(), which returns one answer at a time and builds the final string using backreferences. For( i = 1, i <= N Items( source ), i++, s = Regex( source[i], ".*?(cat|dog|ralph|girl).*?(ate|chased|like|pets).*?(chicken|cat|mary|dog) ", "\1"); // Match an item in the first group. v = Regex( source[i], ".*?(cat|dog|ralph|girl).*?(ate|chased|like|pets).*?(chicken|cat|mary|dog) ", "\2" ); // Match an item in the second group. o = Regex( source[i], ".*?(cat|dog|ralph|girl).*?(ate|chased|like|pets).*?(chicken|cat|mary|dog) ", "\3" ); // Match an item in the third group. If( !Is Missing( s ) & !Is Missing( v ) & !Is Missing( o ), dt << Add Rows( 1 ); dt:subject = s; // Return the match for \1. dt:verb = v; // Return the match for \2. dt:object = o; // Return the match for \3. ); ); Backreferences are discussed in “Backreferences and Capturing Groups” on page 157. Special Characters in Regular Expressions Special characters are commonly used in regular expressions. The period is a special character that matches one instance of the specified character. It must be escaped with a backslash to be interpreted as a period. In the following expression, the period is replaced with an exclamation point. Regex( "Bicycling makes traveling to work fun.", "\.", "!", GLOBALREPLACE ); "Bicycling makes traveling to work fun!" Table 6.8 describes the special characters and provides examples. Table 6.8 Special Characters in Regular Expressions \ • Precedes a literal character. <\/a> interprets the forward slash literally in the end HTML anchor tag. • Precedes an escape sequence. \n matches a newline character. ^ Matches the beginning of a string, not including the newline character. ^apple matches “apple” at the beginning of a string. Chapter 6 Scripting Guide Types of Data Regular Expressions 153 Table 6.8 Special Characters in Regular Expressions (Continued) $ Matches the end of a string, not including the newline character. apple$ matches “apple” at the end of a string. . Matches any single character including a newline character. .apple matches any single character and then “apple”. | Represents a logical OR to separate alternative values. (apple|orange|banana) matches “apple”, “orange”, or “banana”. ? Matches zero or one instance. apple (pie)? matches one or more instances of “pie”. * Matches zero or more instances. + Matches one or more instances. ( ) Encloses a sub‐expression. (apple|orange|banana) matches “apple”, “orange”, or “banana”. ^(\w+) matches the beginning of a line and then one or more word characters. [ ] Encloses an expression that matches set of characters. [\s] matches a whitespace character or a digit. [a-z0-9] matches “a” through “z” and numbers “0” through “9”. { } Encloses an expression that represents repetition. apple{3} repeats three times. apple{3,} repeats at least three times as many times as possible. apple{3, 10} repeats three times but no more than 10 times. Append a question mark to indicate repeating as few times as possible. For example, apple{3,}? repeats at least three times as few times as possible. Escaped Characters in Regular Expressions The backslash in a regular expression precedes a literal character. You also escape certain letters that represent common character classes, such as \w for a word character or \s for a space. The following example matches word characters (alphanumeric and underscores) and spaces. 154 Types of Data Regular Expressions Chapter 6 Scripting Guide Regex( "Are you there, Alice?, asked Jerry.", // source "(here|there).+(\w+).+(said|asked)(\s)(\w+)\." ); // regular expression "there, Alice?, asked Jerry." (here|there).+ Matches “there”, a comma, and a space. (\w+) Matches “Alice”. .+ Matches “?, “. (said|asked)(\s) Matches “asked” followed by a space. Without the space, the match would end here; “asked” is followed by a space in the source string. (\w+)\. Matches “Jerry” and a period. Table 6.9 describes the escaped characters supported in JMP. \C, \G, \X, and \z are not supported. J Table 6.9 Escaped Characters \A start of a string \b word boundary. The zero‐length string between \w and \W or \W and \w. \B not at a word boundary \cX ASCII control character \d single digit [0-9] \D single character that is NOT a digit [^0-9] \l match a single lowercase letter [a-z] \L single character that is not lowercase [^a-z] \s single whitespace character \S single character that is NOT white space \u single uppercase character [A-Z] \U single character that is not uppercase [^A-Z] \w word character [a-zA-Z0-9_] \W single character that is NOT a word character [^a-zA-Z0-9_] Chapter 6 Scripting Guide Types of Data Regular Expressions 155 Table 6.9 Escaped Characters (Continued) \x00-\xFF hexadecimal character \x{0000}-\x{FFFF} Unicode code point \Z end of a string before the line break Greedy and Reluctant Regular Expressions The ?, *, and + operators are greedy by default. They match as many of the preceding character as possible. The ? operator makes them reluctant; ?? matches 0, then 1 if needed; +? matches 1 and then additional characters; *? matches 0 and then additional characters. The following example starts at the letter n and compares it to the first \d (digits) in the pattern. No digit matches. Because the pattern does not begin with ^ (start of line), the matcher advances to u. The process repeats until the 3 matches the first \d and the 2 matches the second \d. Regex( "number=32.5", "\d\d" ); "32" Change the pattern to use the greedy + (match one or more). Regex( "number=324.5", "\d+" ); "324" The preceding example begins much the same, but as soon as the 3 is found and the \d matches, the + greedily matches the 2 and the 4. Usually, the greedy behavior makes pattern matching faster because the string is consumed sooner. Sometimes a reluctant behavior is better. Adding the ? after the * or + changes them from greedy to reluctant. Regex( "number=324.5", "\d+?" ); "3" Here, + requires at least one match of a digit character, but ? changes it from “as many as possible” to “as few as possible”. It stopped after the 3 because the pattern was satisfied. Compare the following results. Greedy: Regex( "number=324.5", "(\d+)(\d+)\.", "first=\1 second=\2" ); "first=32 second=4" Reluctant: Regex( "number=324.5", "(\d+?)(\d+?)\.", "first=\1 second=\2" ); "first=3 second=24" 156 Types of Data Regular Expressions Chapter 6 Scripting Guide In the greedy example above, the matcher greedily matched 3, 2, and 4 for the first \d+. The matcher then had to give back the 4 so that the second \d+ could match something. The reluctant example followed a different path to get a different answer. Initially, the second value was 2, but the pattern could not match the period to the 4, so the second \d+? reluctantly matched the 4 as well. Use the Reluctant Match for Speed The greedy and reluctant matches usually produce the same result but not always. See the previous section. One reason you might need the reluctant match is for speed. Suppose that you have a million‐character string that begins “The quick fox…” and you want to find the word before “fox”. You might write the following expression and expect \1 to contain “quick”. The (.+) fox \1 might contain “quick” eventually, after the .* grabs the million characters to the end of the string and then gives them up, one at a time, until “fox” is found. If there is more than one “fox”, it will be the last fox, not this one. To speed it up and make sure we get the first fox, add the ? operator. The (.+?) fox The ? advances one character at a time to get past “quick” and find the first “fox”. This method is much faster than going too far. Typically, the + or * operator is applied to a more restrictive expression such as \d* to match a run of digits, and greedy is faster than reluctant. Aside from the multiple fox possibility, greedy and reluctant eventually get the same answer. Using the right operator speeds up the match. The right one might be greedy, or it might be reluctant. It depends on what is being matched. The greedy .* finds the last fox after backing up. Regex( "The quick fox saw another fox eating grapes", "The (.*) fox", "\1" ); "quick fox saw another" The reluctant .*? stops on the first fox. Regex( "The quick fox saw another fox eating grapes", "The (.*?) fox", "\1" ); "quick" Chapter 6 Scripting Guide Types of Data Regular Expressions 157 The greedy .* has to back up a lot. There is no second fox. Regex( "The quick fox saw another animal eating grapes", "The (.*) fox", "\1" ); "quick" The greedy word character match is an even better choice for this problem. Regex( "The quick fox saw another fox eating grapes", "The (\w*) fox", "\1" ); "quick" Backreferences and Capturing Groups A regular expression can consist of patterns grouped in parentheses, also known as capturing groups. In ([a-zA-Z])\s([0-9]), ([a-zA-Z]) is the first capturing group; ([0-9]) is the second capturing group. Use a backreference to replace the pattern matched by a capturing group. In Perl, these groups are represented by the special variables $1, $2, $3, and so on. ($1 indicates text matched by the first parenthetical group.) In JMP, use a backslash followed by the group number (\1, \2, \3). The following example includes a third argument that specifies the replacement text and backreferences. Regex( " Are you there, Alice?, asked Jerry.", // source " (here|there).+ (\w+).+(said|asked) (\w+)\.", // regular expression " I am \1, \4, replied \2." ); // optional format argument " I am there, Jerry, replied Alice." " I am \1, Creates the text “I am”, a space, “there”, and then the first matched pattern, “there”. \4, Creates the text “Jerry” with the fourth matched pattern (\w+). replied \2." Creates the text “replied” and a space. Matches “Alice.” with the second matched pattern (\w+). 158 Types of Data Pattern Matching Chapter 6 Scripting Guide Lookaround Assertions Lookaround assertions check for a pattern but do not return that pattern in the results. Lookaheads look forward for a pattern. Lookbehinds look back for a pattern. Negative Lookahead Example Negative lookaheads check for the absence of a pattern ahead of a specific pattern. ?! indicates a negative lookahead. The following expression matches a comma not followed by a number or space and replaces the pattern with a comma and space: Regex( "one,two 1,234 cat,dog,duck fish, and chips,to go", ",(?!\d|\s)", ", ",GLOBALREPLACE); "one, two 1,234 cat, dog, duck fish, and chips, to go" Positive Lookahead Example Positive lookaheads check for the presence of a pattern ahead of a specific pattern. ?= indicates a positive lookahead. The following expression has the same result as the preceding negative lookahead but matches a comma followed by any lowercase character: Regex( "one,two 1,234 cat,dog,duck fish, and chips,to go", ",(?=[a-z])", ", ",GLOBALREPLACE); "one, two 1,234 cat, dog, duck fish, and chips, to go" Positive Lookbehind Example In this example, the positive lookbehind regular expression matches the “ssn=” or “salary=” keywords without including the keyword in the matched text. The matched text is the string of characters that consists of zero or more dollar signs, digits, and hyphens. data = "name=bill salary=$5 ssn=123-45-6789 age=13,name=mary salary=$6 ssn=987-65-4321 age=14"; redacted = Regex(data, "(?<=(ssn=)|(salary=))[$\d-]*", "###", GLOBALREPLACE); "name=bill salary=### ssn=### age=13,name=mary salary=### ssn=### age=14" Here is another way to get the same result using a backreference substitution. ((ssn=)|(salary=)) is the capturing group. "\1" is the backreference to that group. data = "name=bill salary=$5 ssn=123-45-6789 age=13,name=mary salary=$6 ssn=987-65-4321 age=14"; redacted = Regex(data, "((ssn=)|(salary=))[$\d-]*", "\1###", GLOBALREPLACE); "name=bill salary=### ssn=### age=13,name=mary salary=### ssn=### age=14" Backreferences are discussed in “Backreferences and Capturing Groups” on page 157. Pattern Matching Pattern matching in JSL is a flexible method for searching and manipulating strings. Chapter 6 Scripting Guide Types of Data Pattern Matching 159 You define and use pattern variables just like any JMP variable: i a t p = = = = 3; // a numeric variable "Ralph"; // a character variable textbox("Madge"); // a display box variable ( "this" | "that" ) + patSpan(" ") + ( "car" | "bus" ); // a pattern variable When the above statement executes, p is assigned a pattern value. The pattern value can be used either to construct another pattern or to perform a pattern match. The patSpan function returns a pattern that matches a span of characters specified in the argument; patSpan("0123456789") matches runs of digits. p2 = "Take " + p + "."; // using p to build another pattern if( patMatch( "Take this bus.", p2 ), print("matches"), print("no match") ); // performing a match Sometime all you need to know is that the pattern matched the source text, as above. Other times, you might want to know what matched; for example, was it a bus or a car? p = ("this" | "that") + Pat Span( " " ) + ("car" | "bus") >? vehicleType; // conditional assignment ONLY if pattern matches If( Pat Match( "Take this bus.", p ), Show( vehicleType ), Print( "no match" ) ); // do not use vehicleType in the ELSE because it is not set You could pre‐load vehicleType with a default value if you do not want to check the outcome of the match with an if. The >? conditional assignment operator has two arguments, the first being a pattern and the second a JSL variable. >? constructs a pattern that matches the pattern (first argument) and stores the result of the match in the JSL variable (second argument) after the pattern succeeds. Similarly, >> does not wait for the pattern to succeed. As soon (and as often) as the >> pattern matches, the assignment is performed. findDelimString = patLen(3)>>beginDelim + patArb()>?middlePart + expr(beginDelim); testString = "SomeoneSawTheQuickBrownFoxJumpOverTheLazyDog'sBack"; rc = PatMatch( testString, findDelimString, "<<<" || middlePart || ">>>" ); show( rc, beginDelim, middlePart, testString ); The above example shows a third argument in the patMatch function: the replacement string. In this case, the replacement is formed from a concatenation (|| operator) of three strings. One of the three strings, middlePart, was extracted from the testString by >? because the replacement cannot occur unless the pattern match succeeds (rc == 1). Look at the pattern assigned to findDelimString. It is a concatenation of 3 patterns. The first is a >> operator that matches 3 characters and assigns them to beginDelim. The second is a >? operator that matches an arbitrary number of characters and, when the entire match succeeds, assigns them to middlePart. The last is an unevaluated expression, consisting of whatever 160 Types of Data Pattern Matching Chapter 6 Scripting Guide string is in beginDelim at the time the pattern is executing, not at the time the pattern is built. Just like expr(), the evaluation of its argument is postponed. That makes the pattern hunt for two identical three letter delimiters of the middle part. Other pattern functions might be faster and represent the problem that you are trying to solve better than writing a lot of alternatives; for example, "a"|"b"|"c" is the same as patAny("abc"). The equivalent example for patNotAny("abc") is much harder. Similar to patSpan (above), patBreak("0123456789") matches up to, but not including, the first number. Here is a pattern that matches numbers with decimals and exponents and signs. It also matches some degenerate cases with no digits; look at the pattern assigned to digits. digits = patSpan("0123456789") | ""; number = ( patAny("+-") | "" ) >? signPart + ( digits ) >? wholePart + ( "." + digits | "" ) >? fractionPart + ( patAny("eEdD") + ( patAny("+-") | "" ) + digits | "" ) >? exponentPart; if( patMatch( "-123.456e-78", number ), show( signPart, wholePart, fractionPart, exponentPart ) ); Parsing Strings in Fixed Fields Sometimes data is in fixed fields. The patTab, patRTab, patLen, patPos, and patRPos functions make it easy to split out the fields in a fixed field string. PatTab and patRTab work from the left and right end of the string and take a number as their argument. They succeed by matching forward to the specified tab position. For example: p = patPos(10) + patTab(15); PatPos(10) matches the null string if it is in position 10. So at match time, the matcher works its way forward to position 10, then patTab(15) matches text from the current position (10) forward to position 15. This pattern is equivalent to patPos(10)+patLen(5). Another example: p = patPos(0) + patRTab(0); This example matches the entire string, from 0 characters from the start to 0 characters from the end. the patRem() function takes no argument and is shorthand for patRTab(0); it means the remainder of the string. Pattern matching can also be anchored to the beginning of the string like this: patMatch( "now is the time", patLen(15) + patRPos(0), NULL, ANCHOR ); The above pattern uses NULL rather than a replacement value, and ANCHOR as an option. Both are uppercase, as shown. NULL means that no replacement is done. ANCHOR means that the match is anchored to the beginning of the string. The default value is UNANCHORED. Patterns can be built up like this, but this is not recursive: Chapter 6 Scripting Guide Types of Data Pattern Matching 161 p = "a" | "b"; // matches one character p = p + p; // two characters p = p + p; // four characters patMatch( "babb", patPos(0) + p + patRPos(0) ); A recursive pattern refers to its current definition using expr(): p = "<" + expr(p) + "*" + expr(p) + ">" | "x"; patMatch( "< >*x>", patPos(0) + p + patRPos(0) ); Remember, expr() is the procrastination operator; when the pattern is assigned to the variable p, expr() delays evaluating its argument (p) until later. In the next statement, patMatch performs the pattern match operation, and each time it encounters expr(), it looks for the current value of the argument. In this example, the value does not change during the match). So, if p is defined in terms of itself, how can this possibly work? p consists of two alternatives. The right hand choice is easy: a single letter x. The left side is harder: . Each p could be a single letter x, since that is one of the choices p could match, or it could be
. The last few example have used patPos(0) + ... + patRPos(0) to make sure the pattern matches the entire source text. Sometimes this is what you want, and sometimes you would rather the pattern match a subtext. If you are experimenting with these examples by changing the source text, you probably want to match the entire string to easily tell what was matched. The result from patMatch is 0 or 1. This example uses “Left” recursion: x = expr(x) + "a" | "b"; // + binds tighter than | If the pattern is used in FULLSCAN mode, it eventually uses up all memory as it expands. By default, the patMatch function does not use FULLSCAN, and makes some assumptions that allow the recursion to stop and the match to succeed. The pattern matches either a “b”, or anything the pattern matches followed by an “a”. rc = patMatch( "baaaaa", x ); Patterns and Case Unlike regular expressions, pattern matching is case insensitive. To force case sensitivity, you can add the named argument MATCHCASE to either Pat Match or Regex Match. For example: string = "abcABC"; result = Regex Match( string, Pat Regex( "[aBc]+" ) ); Show( string, result ); string = "abcABC" result = {"abcABC"} result = Regex Match( string, Pat Regex( "[cba]+" ), NULL, MATCHCASE ); 162 Types of Data Pattern Matching Show( string, result ); string = "abcABC" result = {"abc"} Chapter 6 Scripting Guide Chapter 7 Data Structures Working with Collections of Data JSL provides these basic data structures that can hold a variety of data in a single variable: • A list holds a number of other values, including nested lists and expressions. • A matrix is a row‐by‐column table of numbers. • An associative array maps keys to values, which can be almost any other type of data. Contents Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Evaluate Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Assignments with Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Perform Operations in Lists. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Find the Number of Items in a List. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Subscripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Locate Items in a List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 List Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Iterate through a List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Concatenate Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Construct Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Subscripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Inquiry Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Comparisons, Range Checks, and Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Numeric Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 Concatenation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 Transpose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 Matrices and Data Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 Matrices and Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Loc Functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Ranking and Sorting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Special Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Inverse Matrices and Linear Systems. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 Decompositions and Normalizations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 Build Your Own Matrix Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Statistical Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Associative Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 Chapter 7 Scripting Guide Data Structures Lists 165 Lists Lists are containers to store items, such as the following: • numbers • variables • character strings • expressions (for example, assignments or function calls) • matrices • nested lists Create a list in one of the following ways: • use the List function • use { } curly braces Examples Use the List() function or curly braces to create a list that includes numbers and variables: x = List(1, 2, b); x = {1, 2, b}; A list can contain text strings, other lists, and function calls: {"Red", "Green", "Blue", {1, "true"}, sqrt(2)}; You can place a variable into a list and assign it a value at the same time: x = {a=1, b=2}; Evaluate Lists When you run a script that contains a list, a copy of the list is returned. The items inside the list are not evaluated. b = 7; x = {1, 2, b, Sqrt(3)}; Show(x); x = {1, 2, b, Sqrt(3)}; To evaluate items in a list, use the Eval List function. b = 7; x = {1, 2, b, Sqrt(3)}; c = Eval List(x); {1, 2, 7, 1.73205080756888} 166 Data Structures Lists Chapter 7 Scripting Guide Assignments with Lists Create a list to assign values to variables. Examples {a, b, c} = {1, 2, 3}; // assigns 1 to a, 2 to b, and 3 to c {a, b, c}--; // decrements a, b, and c {{a}, {b, c}}++; // increments a, b, and c by 1 mylist = {1, log(2), e()^pi(), height[40]}; // stores the expressions Perform Operations in Lists In lists, you can perform operations. a = {{1, 2}, 3, {4, 5}}; b = {{10, 20}, 30, {40, 50}}; c = a + b; c = {{11, 22}, 33, {44, 55}} Find the Number of Items in a List To determine the number of items in a list, use the N Items() function. x = {1, 2, y, Sqrt(3), {a, b, 3}}; N = N Items(x); Show(n); n = 5; Subscripts Subscripts extract specified items from a list. Use a list as a subscript to return multiple items from a list. Note: JSL starts counting from 1, so the first element in a list is [1], not [0] as in some other languages. Examples List a contains four items. a = {"bob", 4, [1,2,3], {x,y,z}}; Show( a[1] ); a[1] = "bob"; Show( a[{1,3}] ); a[{1, 3}] = {"bob", [1, 2, 3]}; a[2] = 5; // assigns 5 to the second list item Chapter 7 Scripting Guide Data Structures Lists 167 You can also use subscripts to select or change items in a list: Show( a ); a = {"bob", 5, [1, 2, 3], {x, y, z}}; c = {1, 2, 3}; c[{1, 2}] = {4, 4}; // c[{1, 2}] = 4 produces the same result Show( c ); c = {4, 4, 3}; When you have assignments or functions in a list, you can use a quoted name for the subscript to extract the value. x={sqrt(4), log(3)}; xx={a=1, b=3, c=5}; x["sqrt"]; 4 xx["b"]; 3 The name must be in quotation marks, or else JMP tries to evaluate it and use its value. The following example shows the values of the second item in the list, rather than the value of a in the list. a = 2; Show(xx[a]); xx[a] = b = 3; Note the following: • Multiple left‐side subscripts (for example, a[i][j] = value where a contains a list of things that are subscriptable) are allowed in the following circumstances: ‒ Each level except the outermost level must be a list. So, in the example above, a must be a list but a[i] can be anything subscriptable. ‒ Each subscript except the last must be a number. So, in the example above, i must be a number, but j could be a matrix or list of indices. • Subscripting can be done to any level of nesting, such as the following: a[i][j][k][l][m][n] = 99; Locate Items in a List Use the Loc() function or the Contains() function to find values in a list: Loc(list, value) Contains(list, value) Loc() and Contains() return the positions of the values. Loc() returns the results in a matrix, and Contains() returns the results as a number. 168 Data Structures Lists Chapter 7 Scripting Guide Note the following: • The Loc function returns each occurrence of a repeated value. Contains() returns only the first occurrence of a repeated value. • If the value is not found, the Loc function returns an empty matrix and Contains() returns a zero. • To assess whether an item is in a list, use Loc() and Contains() with >0. A returned value of zero means that the item is not in the list. A returned value of 1 means that the item is in the list at least once. Note: For details about matrix manipulation and a description of the equivalent Loc() command for matrices, see “Matrices” on page 173. Examples nameList = {“Katie”, “Louise”, “Jane”, “Jane”}; numList = {2, 4, 6, 8, 8}; Search for the value "Katie" in the nameList: Loc(nameList, “Katie”); [1] Contains(nameList, "Katie"); 1 Search for the value "Erin" in the nameList: Loc(nameList, “Erin”); [] Contains(nameList, "Erin"); 0 Search for the number 8 in the numList: Loc(numList, 8); [4, 5] Contains(numList, 8); 4 Find out if the number 5 exists in the numList: NRow(Loc(numList, 5)) >0; 0 Contains(numList, 5) >0; 0 List Operators Table 7.1 describes the list operators and their syntax. Chapter 7 Scripting Guide Data Structures Lists 169 Table 7.1 List Operators Operator and Function = += -= *= /= ++ -- Syntax Explanation As List() As List(matrix) Returns the matrix as a list. A matrix with multiple columns is returned as a list of lists, one list per row. Assign() Add To() SubtractTo() MultiplyTo() DivideTo() Post Increment() Post Decrement() {list} = {list} {list} += value {list} -= {list} ... If the target of an assignment operator is a list and the value to be assigned is a list, then it assigns item by item. The ultimate values in the left list must be L‐values (in other words, names capable of being assigned values). Notes: • If you want to test equality of lists, use ==, not =. • JMP does not have a pre‐decrement operator. Use the SubtractTo() operator instead (-=). ||= Concat To() Concat To(list1, list2, ...) Inserts the second and subsequent lists at the end of the first list. || Concat() Concat(list1, list2, ...); Returns a copy of the first list with any additional lists inserted at after it. Eval List() Eval List(list) Returns a list of the evaluated expressions inside list. See “Evaluate Lists” on page 165. Insert Into() Insert Into(list, x, ) Inserts a new item (x) into the list at the given position (i). If i is not given, the item is added to the end of the list. This function does change the original list. 170 Data Structures Lists Chapter 7 Scripting Guide Table 7.1 List Operators (Continued) Operator and Function { } Syntax Explanation Insert() list = Insert(list, x, ) Returns a copy of the list with a new item (x) inserted into the list at the given position (i). If i is not given, the item is added to the end of the list. This function does not change the original list. Is List() Is List(arg) Returns true (1) if arg is a classical list (in other words, one that would result from the construction by List(items) or {items}) and returns false (0) otherwise. An empty list is still a list, so IsList({ }) returns true. If miss=., then IsList(miss) returns false, not missing. List List(a, b, c) {a, b, c} Constructs a list from a set of items. An item can be any expression, including other lists. Items must be separated by commas. Text should either be enclosed in double quotation marks ( " " ) or stored in a variable and called as that variable. N Items N Items(list) Returns the number of elements in the list specified. Can be assigned to a variable. Remove From() Remove From(list, ,
) Deletes n items from the list, starting from the indicated position (i). If n is omitted, the item at i is deleted. If n and i are omitted, the item at the end is removed. This function does change the original list. Remove() Remove(list, , ) Returns a copy of the list with the n items deleted, starting from the indicated position (i). If n is omitted, the item at i is deleted. If n and i are omitted, the item at the end is removed. This function does not change the original list. Chapter 7 Scripting Guide Data Structures Lists 171 Table 7.1 List Operators (Continued) Operator and Function [ ] Syntax Explanation Reverse Into() Reverse Into(list) Reverses the order of the items in the list. This function does change the original list. Reverse() Reverse(list) Returns a copy of the list with the items in reverse order. This function does not change the original list. Shift Into() Shift Into(list, ) Shifts n items from the front of the list to the end of the list. If n is omitted, the first item is moved to the end of the list. This function does change the original list. Shift() Shift(list, ) Returns a copy of the list with n items shifted from the front of the list to the end of the list. If n is omitted, the first item is moved to the end of the list. This function does not change the original list. Sort Ascending() Sort Ascending(list) Returns a copy of the list sorted in ascending order. This function does not change the original list. Sort Descending() Sort Descending(list) Returns a copy of the list sorted in descending order. This function does not change the original list. Sort List Into() Sort List Into(list) Sorts the list in ascending order. This function does change the original list. Sort List() Sort List(list) Returns a copy of the list sorted in ascending order. This function does not change the original list. Subscript() list[i] x = list[i] list[i] = value a[b, c] Subscript(a, b, c) Subscripts for lists extract the ith item from the list. Subscripts can in turn be lists or matrices. 172 Data Structures Lists Chapter 7 Scripting Guide Table 7.1 List Operators (Continued) Operator and Function Substitute() Substitute Into() Syntax Explanation Substitute(list, pattExpr1, replExpr1, ...) Returns a copy of a list or expression, replacing instances of each pattern expression with the corresponding replacement expression. Substitute Into(list, Changes a list or expression, replacing instances of each pattern expression with the corresponding replacement expression. Note: The list or expression must be a variable. pattExpr1, replExpr1, ...) Iterate through a List Iterate through a list to do something with each value or look for a particular value. The following script looks at each item in the list. If the item in the list is less than or equal to 10, it is replaced with its square. x = {2, 12, 8, 5, 18, 25}; n = N Items (x); for (i=1, i<=n, i++, if (x[i]<=10, x[i]=x[i]^2) ); Show (x) x = {4, 12, 64, 25, 18, 25}; You can use Loc() to locate the items in the new list that are equal to 25: Loc (x,25) [4, 6] // The fourth and sixth items in the list are equal to 25. Concatenate Lists Join two or more lists into one list with Concat() or the || operator. The following example uses Concat() to join lists a and b: a = {1, 2}; b = {7, 8, 9}; Concat( a, b ); {1, 2, 7, 8, 9} The following example joins the same lists using the || operator: {1, 2} || {7, 8, 9} Chapter 7 Scripting Guide Data Structures Matrices 173 {1, 2, 7, 8, 9} Lists of different types can be concatenated (for example, lists that contain character strings and numbers). d = {"apples", "bananas"}; e = {"oranges", "grapes"}; f = {1, 2, 3}; Concat( d, e, f); {"apples", "bananas", "oranges", "grapes", 1, 2, 3} Matrices A matrix is a rectangular array of numbers that are arranged in rows and columns. Use matrices to store numbers and perform calculations on those numbers using matrix algebra. Note the following for this section: • Matrices are represented with an uppercase bold variable (for example, A). • A matrix with one row or one column is a vector (or more specifically, a row vector or a column vector respectively). • For clarity, we represent matrices that are vectors with lowercase bold letters (such as x). • A scalar is a numeric value that is not in a matrix. Construct Matrices Note the following when creating matrices: • Place matrix literals in square brackets. [...] • Matrix values can contain decimal points, can be positive or negative, and can be in scientific notation. • Separate items across a column with blank spaces. You can use any number of blank spaces. • Separate rows with a comma. For constructing more advanced matrices, see “Special Matrices” on page 188. Examples Create matrix A with 3 rows and 2 columns: A = [1 2, 3 4, 5 6]; R is a row vector and C is a column vector: R = [10 12 14]; 174 Data Structures Matrices Chapter 7 Scripting Guide C = [11, 13, 15]; B is a 1‐by‐1 matrix, or a matrix with one row and one column: B = [20]; E is an empty matrix: E = []; Specifying the number of rows and columns in an empty matrix is optional. JMP creates the matrix as necessary. A script can return an empty matrix. In Big Class.jmp, the following expression looks for rows in which age equals 8, finds none, and returns an empty matrix: a = dt << Get Rows Where( age == 8 ); Show( a ); a = [](0,1); Construct Matrices from Lists If you want to convert lists into a matrix, use the Matrix() function. A single list is converted into a column vector. Two or more lists are converted into rows. Create a column vector from a single list: A = matrix({1,2,3}); [1,2,3] Create a matrix from a list of lists. Each list is a row in the matrix. A = matrix({{1,2,3}, {4,5,6}, {7,8,9}}); [1 2 3, 4 5 6, 7 8 9] Construct Matrices from Expressions To construct matrices from expressions, use Matrix(). Elements must be expressions that resolve to numbers. A = matrix({4*5, 8^2, sqrt(9)}); [20, 64, 3] Subscripts Use the subscript operator ([ ]) to pick out elements or submatrices from matrices. The Subscript() function is usually written as a bracket notation after the matrix to be subscripted, with arguments for rows and columns. Chapter 7 Scripting Guide Data Structures Matrices 175 Single Element The expression A[i,j] extracts the element in row i, column j, returning a scalar number. The equivalent functional form is Subscript(A,i,j). P=[1 2 3, 4 5 6, 7 8 9]; P[2,3]; // returns 6 Subscript(P,2,3); // returns 6 Assign the value that is in the third row and the first column in the matrix A (which is 5) to the variable test. A=[1 2, 3 4, 5 6]; test = A[3,1]; Show(test); test = 5; Matrix or List Subscripts To extract a sub‐matrix, use matrix or list subscripts. The result is a matrix of the selected rows and columns. The following expressions select the 2nd and 3rd rows with the 2nd and 1st columns. P=[1 2 3, 4 5 6, 7 8 9]; P[[2 3],[1 3]]; // matrix subscripts P[{2,3},{1,3}]; // list subscripts Both of these methods provide the following output: [4 6, 7 9] Single Subscripts A single subscript addresses matrices as if all the rows were connected end‐to‐end in a single row. This makes the double subscript A[i,j] the same as the single subscript A[(i-1)*ncol(A)+j]. Examples Q = [2 4 6,8 10 12,14 16 18]; Q[8]; // same as Q[3,2] 16 The following examples all return the column vector [10, 14, 18]: Q = [2 4 6, 8 10 12, 14 16 18]; Q[{5, 7, 9}]; Q[[5 7 9]]; ii = [5 7 9]; Q[ii]; 176 Data Structures Matrices Chapter 7 Scripting Guide ii = {5, 7, 9}; Q[ii]; Subscript( Q, ii ); This script returns the values 1 through 9 from the matrix P in order: P = [1 2 3, 4 5 6, 7 8 9]; For( i = 1, i <= 3, i++, For( j = 1, j <= 3, j++, Show( P[i, j] ) ) ); Delete Rows and Columns Deleting rows and columns is accomplished by assigning an empty matrix to that row or column. A[k, 0] = []; A[0, k] = []; // to delete the kth row // to delete the kth column Select Whole Rows or Columns A subscript argument of zero selects all rows or columns. P = [1 2 3, 4 5 6, 7 8 9]; Select column 2: P[0, 2]; [2, 5, 8] Select columns 3 and 2: P[0, [3, 2]]; [3 2, 6 5, 9 8] Select row 3: P[3, 0]; [7 8 9] Select rows 2 and 3: P[[2, 3], 0]; [4 5 6, 7 8 9] Select all columns and rows (the whole matrix): P[0, 0]; [1 2 3, 4 5 6, 7 8 9] Chapter 7 Scripting Guide Data Structures Matrices 177 Assignment through Subscripts You can change values in matrices using subscripts. The subscripts can be single indices, matrices or lists of indices, or the zero index representing all rows or columns. The number of selected rows and columns for the insertion must either match the dimension of the inserted argument, or the argument can be inserted repeatedly into the indexed positions. Examples Change the value in row 2, column 3 to 99: P = [1 2 3, 4 5 6, 7 8 9]; P[2, 3] = 99; Show( P ); P=[1 2 3, 4 5 99, 7 8 9] Change the values in four locations: P = [1 2 3, 4 5 6, 7 8 9]; P[[1 2], [2 3]] = [66 77, 88 99]; Show( P ); P=[1 66 77, 4 88 99, 7 8 9] Change three values in one column: P = [1 2 3, 4 5 6, 7 8 9]; P[0, 2] = [11, 22, 33]; Show( P ); P=[1 11 3, 4 22 6, 7 33 9] Change three values in one row: P = [1 2 3, 4 5 6, 7 8 9]; P[3, 0] = [100 102 104]; Show( P ); P=[1 2 3, 4 5 6, 100 102 104] Change all the values in one row to the same value: P = [1 2 3, 4 5 6, 7 8 9]; P[2, 0] = 99; Show( P ); P=[1 2 3, 99 99 99, 7 8 9] Operator Assignment You can use operator assignments (such as +=) on matrices or subscripts of matrices. For example, the following statement adds 1 to the i ‐ jth element of the matrix: P=[1 2 3, 4 5 6, 7 8 9]; P[1,1]+=1; Show(P); 178 Data Structures Matrices Chapter 7 Scripting Guide P=[2 2 3, 4 5 6, 7 8 9]; P[1,1]+=1; Show(P); P=[3 2 3, 4 5 6, 7 8 9]; Ranges of Rows or Columns If you are working with a range of subscripts, use the Index() function :: to create matrices of ranges. T1=1::3; // creates the vector [1 2 3] T2=4::6; // creates the vector [4 5 6] T3=7::9; // creates the vector [7 8 9] T=T1|/T2|/T3; // concatenates the vectors into a single matrix T[1::3, 2::3]; // refers to rows 1 through 3, columns 2 and 3 [2 3, 5 6, 8 9] T[index(1,3), index(2,3)]; // equivalent Index function [2 3, 5 6, 8 9] Inquiry Functions The NCol() and NRow() functions return the number of columns and rows in a matrix (or data table), respectively: NCol([1 2 3,4 5 6]); // returns 3 (for 3 columns) NRow([1 2 3,4 5 6]); // returns 2 (for 2 rows) To determine whether a value is a matrix, use the Is Matrix() function, which returns a 1 if the argument evaluates to a matrix. A = [20, 64, B = {20, 64, IsMatrix(A); IsMatrix(B); 3]; 3}; // returns 1 for yes // returns 0 for no Comparisons, Range Checks, and Logical Operators JMP’s comparison, range check, and logical operators work with matrices and produce matrices of elementwise Boolean results. You can compare conformable matrices. AB; // greater than A>=B; // greater or equal Chapter 7 Scripting Guide Data Structures Matrices 179 A==B; // equal to A!=B; // not equal to A Show Tree Structure. The parameter estimates are contained in NumberColBox(13). Continue with the script as follows: colBox=Report(biv) [NumberColBox(13)]; beta = colBox< |t|", probt), NumberColBox("Lower95%", betal95), NumberColBox("Upper95%", betau95))); Chapter 7 Scripting Guide Data Structures Matrices 203 ANOVA Example You can implement your own one‐way ANOVA. This example presents a problem involving a three‐level factor indicating Low, Medium, and High doses and a response measurement. Therefore, this example solves the general linear model, as follows: Y = a + bX + e Where: • Y is a vector of responses • a is the intercept term • b is a vector of coefficients • X is a design matrix for the factor • e is an error term factor=[1,2,3,1,2,3,1,2,3]; y=[1,2,3,4,3,2,5,4,3]; First, build a design matrix for the factor: designNom(factor); [1 0, 0 1, -1 -1, 1 0, 0 1, -1 -1, 1 0, 0 1, -1 -1] Next, add a column of 1s to the design matrix for the intercept term. You can do this by concatenating J and Design Nom(), as follows: x = J(9,1,1) || designNom(factor); [1 1 0, 1 0 1, 1 -1 -1, 1 1 0, 1 0 1, 1 -1 -1, 1 1 0, 1 0 1, 1 -1 -1] Now, to solve the normal equation, you need to construct a matrix M with partitions: XX Xy yX yy You can construct matrix M in one step by concatenating the pieces, as follows: 204 Data Structures Matrices Chapter 7 Scripting Guide M=(x`*x || x`*y) |/ (y`*x || y`*y); [ 9 0 0 27, 0 6 3 2, 0 3 6 1, 27 2 1 93] Now, sweep M over all the columns in X’X for the full fit model, and over the first column only for the intercept‐only model: FullFit=sweep(M,[1,2,3]); InterceptOnly=sweep(M,[1]); // full fit model // model with intercept only Recall that some of the standard ANOVA results are calculated by comparing the results of these two models. This example focuses on the full fit model, which produces this swept matrix: [0.111111111111111 0 0 3, 0 0.222222222222222 -0.11111111111111 0.333333333333333, 0 -0.11111111111111 0.222222222222222 0, -3 -0.33333333333333 0 11.33333333333333] Examine the model coefficients from the upper right partition of the matrix. The lower left partition is the same, except that the signs are reversed: 3, 0.333, 0. The results can be interpreted as follows: • The coefficient for the intercept term is 3. • The coefficient for the first level of the factor is 0.333. • The coefficient for the second level is 0. • Because of the use of Design Nom(), the coefficient for the third level is the difference, –0.333. • The lower right partition of the matrix holds the sum of squares, 11.333. You could modify this into a generalized ANOVA script by replacing some of the explicit values in the script with arguments. These results match those from the Fit Model platform. See Figure 7.1. Chapter 7 Scripting Guide Data Structures Matrices 205 Figure 7.1 ANOVA Report Within Fit Model Construct the report in Figure 7.1 as follows: 1. Build a data table (described in the “Data Tables” chapter on page 275): dt = New Table( "foo" ); dt << New Column( "y", Set Values( [1, 2, 3, 4, 3, 2, 5, 4, 3] ) ); dt << New Column( "factor", "Nominal", Values( [1, 2, 3, 1, 2, 3, 1, 2, 3] ) ); 2. Run a model (described in “Launching Platforms” on page 382 in the “Scripting Platforms” chapter): obj = Fit Model( Y( :y ), Effects( :factor ), Personality( "Standard Least Squares" ), Run Model( y << {Plot Actual by Predicted( 0 ), Plot Residual by Predicted( 0 ), Plot Effect Leverage( 0 )} ) ); 3. Use JSL techniques for navigating displays (described in “Display Box Object References” on page 408 in the “Display Trees” chapter): ranova = obj << report; ranova[OutlineBox(6)] << Close(0); ranova[OutlineBox(7)] << Close(1); ranova[OutlineBox(9)] << Close(1); ranova[OutlineBox(5), NumberColBox( 2 )] << select; ranova[OutlineBox(6), NumberColBox( 1 )] << select; 206 Data Structures Associative Arrays Chapter 7 Scripting Guide Associative Arrays An associative array maps unique keys to values that can be non‐unique. An associative array is also called a dictionary, a map, a hash map, or a hash table. Keys are placed in quotes. The value associated with a key can be a number, date, matrix, list, and so on. Note: You can use matrices as both keys and values, or lists as both keys and values, but you cannot mix the two. In other words, you cannot use a matrix as a key and a list as a value, or the other way around. Though associative arrays are not usually ordered, in JMP, keys are returned in alphanumeric order for the purpose of iteration and serialization. For very large lists, using an associative array instead is more efficient and faster. Create Associative Arrays To create an empty associative array, use the Associative Array() function or [=>]. cary = Associative Array(); cary = [=>]; [=> ] Keys and values can be any JSL objects. Items can be added and changed with subscripting, as follows: cary = Associative Array(); cary["state"] = "NC"; cary["population"] = 116234; cary["weather"] = "cloudy"; cary["population"] += 10; cary["weather"] = "sunny"; cary["high schools"] = {"Cary", "Green Hope", "Panther Creek"}; Default Values A default value determines the value of a key that does not exist in an associative array. If you try to access a key that does not exist in an associative array, an error results. If you define a default value for your associative array, accessing a key that does not exist results in the following: • adds the key to the associative array • assigns the default value to the new key • returns the new key’s (default) value instead of an error Chapter 7 Scripting Guide Data Structures Associative Arrays 207 If you construct an associative array from a list of strings without assigning values to the keys, then the keys are assigned values of 1. The default value for the associative array is set to 0. To set the default value: cary = Associative Array(); cary << Set Default Value("Cary, NC"); To determine whether there is a default value set for an associative array, use the < value without a key. counts = ["a"=>10, "b"=>3, =>0]; // default value of 0 counts["c"] += 1; Show (counts); ["a" => 10, "b" => 3, "c" => 1, => 0] In the first line, the default value is set to 0. In the second line, the key "c" does not exist in counts. In the output, the key "c" is created with the default value of 0 and then incremented by 1. Associative Array Constructors Create an empty associative array: map = [=>]; map = Associative Array(); Create an empty associative array with a default value: map = [=>0]; map = Associative Array(0); Create an associative array with specific values: map = ["yes" => 0, "no" => 1]; Create an associative array with specific values with a default value: map = ["yes" => 0, "no" => 1, => 2]; Create an associative array from a list that contains two lists of a key‐value pair: map = Associative Array({{"yes", 0}, {"no", 1}}); Create an associative array from a list that contains two lists of a key‐value pair with a default value: 208 Data Structures Associative Arrays Chapter 7 Scripting Guide map = Associative Array({{"yes", 0}, {"no", 1}}, 2); Create an associative array from a list of keys and a list of values: map = Associative Array({"yes", "no"}, {0, 1}); Create an associative array from a list of keys and a list of values with a default value: map = Associative Array({"yes", "no"}, {0, 1}, 2); Create an associative array from two column references. The first column contains the keys and the second contains the values. map = Associative Array(:name, :height); Create an associative array from two column references with a default value: map = Associative Array(:name, :height, .); Create an associative array from a single list of keys or a single column reference of keys with a default value of 0: set = Associative Array({"yes", "no"}); set = Associative Array(:name); Work with Associative Arrays Find the Number of Keys To determine the number of keys that an associative array contains, use the N Items() function. cary = Associative Array(); cary["state"] = "NC"; cary["population"] = 116234; cary["weather"] = "cloudy"; cary["population"] += 10; cary["weather"] = "sunny"; cary["high schools"] = {"Cary", "Green Hope", "Panther Creek"}; N Items(cary); 4 Add and Delete Keys and Values To add or delete key‐value pairs from an associative array, use the following functions: • Insert() • Insert Into() • Remove() • Remove From() Chapter 7 Scripting Guide Data Structures Associative Arrays 209 Note the following: • Insert() and Remove() return a named copy of the given associative array with the key‐value pair added or removed. • Insert Into() and Remove From() add or remove the key‐value pairs directly from the given associative array. • Insert() and Insert Into() take three arguments: the associative array, a key, and a value. • Remove() and Remove From() take two arguments: the associative array and a key. • If you insert a key with no value provided, the key is assigned a value of 1. Examples The following examples illustrate Insert() and Insert Into(): newcary = Insert(cary, "time zone", "Eastern"); show(cary, newcary); cary = Associative Array({ {"high schools",{"Cary", "Green Hope", "Panther Creek"}}, {"population", 116244}, {"state", "NC"}, {"weather", "sunny"} }); newcary = Associative Array({ {"high schools", {"Cary", "Green Hope", "Panther Creek"}}, {"population", 116244}, {"state", "NC"}, {"time zone", "Eastern"}, {"weather", "sunny"} }); Insert Into(cary, "county", "Wake"); show(cary); cary = Associative Array({ {"county", "Wake"}, {"high schools", {"Cary", "Green Hope", "Panther Creek"}}, {"population", 116244}, {"state", "NC"}, {"weather", "sunny"} }); Note that aa << Insert is a message sent to an associative array that does the same thing as the function Insert Into(). For example, these two statements are equivalent: cary << Insert("county", "Wake"); Insert Into(cary, "county", "Wake"); The following examples illustrate Remove and Remove From: newcary = Remove(cary, "high schools"); show(cary, newcary); 210 Data Structures Associative Arrays Chapter 7 Scripting Guide cary = Associative Array({ {"county", "Wake"}, {"high schools", {"Cary", "Green Hope", "Panther Creek"}}, {"population", 116244}, {"state", "NC"}, {"weather", "sunny"} }) newcary = ["county" => "Wake", "population" => 116244, "state" => "NC", "weather" => "sunny"]; Remove From(cary, "weather"); show(cary); cary = Associative Array({ {"county", "Wake"}, {"high schools", {"Cary", "Green Hope", "Panther Creek"}}, {"population", 116244}, {"state", "NC"} }); Note that aa << Remove is a message sent to an associative array that does the same thing as the function Remove From(). For example, these two statements are equivalent: cary << Remove("weather"); Remove From(cary, "weather"); Find Keys or Values in an Associative Array To determine whether a certain key is contained within an associative array, use the Contains() function. cary = Associative Array(); cary["state"] = "NC"; cary["population"] = 116234; cary["weather"] = "cloudy"; cary["population"] += 10; cary["weather"] = "sunny"; cary["high schools"] = {"Cary", "Green Hope", "Panther Creek"}; Contains(cary, “high schools”); 1 Contains(cary, “lakes”); 0 To obtain a list of all keys contained in an associative array, use the << Get Keys message. cary < ]; Applications for Associative Arrays You can use associative arrays to quickly and efficiently perform other tasks. 212 Data Structures Associative Arrays Chapter 7 Scripting Guide Get the Unique Values from a Data Table Column A key can exist only once in an associative array, so putting a column’s values into one automatically results in the unique values. For example, the Big Class.jmp sample data table contains 40 rows. To see how many unique values are in the column height, run this script: dt = Open("$SAMPLE_DATA/Big Class.jmp"); unique heights = associative array(dt:height); nitems(unique heights); 17 There are only 17 unique values for height. You can use those unique values by getting the keys: unique heights << get keys; {51, 52, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70} Note: This is possible because you can use any JMP data type as keys in an associative array, not only strings. Using an associative array to discover unique values in a column is efficient and fast. The following script takes some time to create a data table with 100,000 rows. Finding the 39 unique values takes very little time. dt = Open( "$SAMPLE_DATA/Big Class.jmp" ); nms = dt:name << getvalues; dtbig = New Table( "BigBigClass", New Column( "name", character, setvalues( nms[J( 100000, 1, Random Integer( N Items( nms ) ) )] ) ) ); Wait( 0 ); t1 = Tick Seconds(); Write( "\!N# names from BigBigClass = ", N Items( Associative Array( dtbig:name ) ), ", elpased time=", Tick Seconds() - t1 ); Sort a Column’s Values in Lexicographic Order Because keys are ordered lexicographically, putting the values into an associative array also sorts them. For example, the < ...); log=expr(print("In control at "||char( long date(today())))); break=expr(...