<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>article Using JSL to select the first or last record in a set in JMP Blog</title>
    <link>https://community.jmp.com/t5/JMP-Blog/Using-JSL-to-select-the-first-or-last-record-in-a-set/ba-p/30532</link>
    <description>&lt;P&gt;When considering my professional life, I'm a relative newcomer to JMP. In fact, my JMP and JSL (JMP Scripting Language) experience began the day I became a developer here in the JMP Life Sciences group, about four years ago.&amp;nbsp;In contrast, I've been using SAS since I was an undergraduate student in mathematics, giving me more than 20 years of experience.&amp;nbsp;Though there are a lot of differences between the two languages, one of the&amp;nbsp;things I enjoy&amp;nbsp;most about my job is using this very large and rich toolset to develop cool new features for &lt;A href="http://www.jmp.com/software/clinical/"&gt;JMP Clinical&lt;/A&gt;.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Even though I have access to both &lt;A href="http://jmp.com/software"&gt;JMP&lt;/A&gt; and &lt;A href="http://sas.com"&gt;SAS&lt;/A&gt;, I sometimes find myself wondering how to replicate a feature in SAS&amp;nbsp;using JSL. The subject of this blog post is how to replicate the SAS data step behavior to select first and last records within by groups.&amp;nbsp;In SAS, this is performed by first sorting the data and using&amp;nbsp;special keywords&amp;nbsp;within the data step.&amp;nbsp;For example, if I had the Big Class data table formatted in SAS and wanted to choose the first boy and girl alphabetically, the program below would accomplish this:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;PRE lang="SAS" escaped="true"&gt;&lt;/PRE&gt;&lt;/P&gt;&lt;P&gt;proc sort data = bigclass;&lt;/P&gt;&lt;P&gt;   by sex name;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;data first;&lt;/P&gt;&lt;P&gt;   set bigclass;&lt;/P&gt;&lt;P&gt;   by sex name;&lt;/P&gt;&lt;P&gt;   if first.sex;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;To choose the last boy and girl alphabetically, I would use &lt;EM&gt;if last.sex;&lt;/EM&gt;.&amp;nbsp;&amp;nbsp; Similar logic applies if&amp;nbsp;I wanted to select&amp;nbsp;first and last within additional by groups.&amp;nbsp;Say, I wanted to pick the shortest person for each name within gender, the following would do that:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;PRE lang="SAS" escaped="true"&gt;&lt;/PRE&gt;&lt;/P&gt;&lt;P&gt;proc sort data = bigclass;&lt;/P&gt;&lt;P&gt;   by sex name height;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;data first;&lt;/P&gt;&lt;P&gt;   set bigclass;&lt;/P&gt;&lt;P&gt;   by sex name height;&lt;/P&gt;&lt;P&gt;   if first.name;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;My colleague &lt;A href="http://blogs.sas.com/content/jmp/author/bradybrady/"&gt;Brady Brady&lt;/A&gt; was kind enough to help me solve this within JSL using Col Min() and Col Max().&amp;nbsp;Figure 1 contains a sample data set. The original data only included Letter (A through J) and Letter 2 (A through D).&amp;nbsp;The data table is sorted by these two variables. You can see below that First.Letter is equal to 1 for the first instance of each letter in Letter (0 otherwise); Last.Letter is a 1 for the last instance of&amp;nbsp;each letter in Letter (0 otherwise). The formulas for these variables is as follows:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;PRE lang="javascript" escaped="true"&gt;&lt;/PRE&gt;&lt;/P&gt;&lt;P&gt;First.Letter = If( Row() == Col Minimum( Row(), :Letter ),&lt;/P&gt;&lt;P&gt;	1,&lt;/P&gt;&lt;P&gt;	0&lt;/P&gt;&lt;P&gt;)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Last.Letter = If( Row() == Col Maximum( Row(), :Letter ),&lt;/P&gt;&lt;P&gt;	1,&lt;/P&gt;&lt;P&gt;	0&lt;/P&gt;&lt;P&gt;)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;To interpret these formulas, the Col M**imum() functions are using :Letter as a by group and getting the minimum or maximum row numbers within each value of Letter. The If() function sets First.Letter = 1 if the current row number equals the :Letter-specific minimum row number.&amp;nbsp;Note that if a particular value for :Letter only had a single row, that record would be considered both the first and the last, with &lt;EM&gt;First.Letter &lt;/EM&gt;= 1 and &lt;EM&gt;Last.Letter = 1&amp;nbsp;&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;A href="https://community.jmp.com/legacyfs/online/wp_images/2015/01/FirstLast.jpg"&gt;&lt;IMG class=" wp-image-15399" src="https://community.jmp.com/legacyfs/online/wp_images/2015/01/FirstLast.jpg" alt="Figure 1. Data Table FirstLast" width="379" height="565" /&gt;&lt;/A&gt;&lt;/P&gt;&lt;P class="wp-caption-text"&gt;&lt;STRONG&gt; Figure 1. Data Table FirstLast&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Similar to the above code for SAS, this can be extended for multiple by variables.&amp;nbsp;Say I wanted to select the first instance of each letter of Letter2 &lt;SPAN style="text-decoration: underline"&gt;within&lt;/SPAN&gt; Letter, I simply add an additional byvar to the function.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;PRE lang="javascript" escaped="true"&gt;&lt;/PRE&gt;&lt;/P&gt;&lt;P&gt;First.Letter2 = If( Row() == Col Minimum( Row(), :Letter, :Letter2 ),&lt;/P&gt;&lt;P&gt;	1,&lt;/P&gt;&lt;P&gt;	0&lt;/P&gt;&lt;P&gt;)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Last.Letter2 = If( Row() == Col Maximum( Row(), :Letter, :Letter2 ),&lt;/P&gt;&lt;P&gt;	1,&lt;/P&gt;&lt;P&gt;	0&lt;/P&gt;&lt;P&gt;)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;These functions have a useful feature in that it allows you to easily subset to&amp;nbsp;by groups&amp;nbsp;where duplicates occur.&amp;nbsp; Selecting rows where &lt;EM&gt;First.Letter &lt;/EM&gt;=&amp;nbsp;0 or &lt;EM&gt;Last.Letter &lt;/EM&gt;= 0&amp;nbsp;will select all rows where :Letter is repeated. In the context of Big Class, using these functions on :Height can allow you to create a subtable where specific heights may be repeated.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Note that in SAS, a sort is required to create the special first.XX last.XX variables.&amp;nbsp; Though the data table above is sorted, this is not a requirement for the JSL code above to work.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Many thanks to Brady Brady for his help!&lt;/P&gt;</description>
    <pubDate>Thu, 05 Feb 2015 18:02:08 GMT</pubDate>
    <dc:creator>Richard_Zink</dc:creator>
    <dc:date>2015-02-05T18:02:08Z</dc:date>
    <item>
      <title>Using JSL to select the first or last record in a set</title>
      <link>https://community.jmp.com/t5/JMP-Blog/Using-JSL-to-select-the-first-or-last-record-in-a-set/ba-p/30532</link>
      <description>&lt;P&gt;When considering my professional life, I'm a relative newcomer to JMP. In fact, my JMP and JSL (JMP Scripting Language) experience began the day I became a developer here in the JMP Life Sciences group, about four years ago.&amp;nbsp;In contrast, I've been using SAS since I was an undergraduate student in mathematics, giving me more than 20 years of experience.&amp;nbsp;Though there are a lot of differences between the two languages, one of the&amp;nbsp;things I enjoy&amp;nbsp;most about my job is using this very large and rich toolset to develop cool new features for &lt;A href="http://www.jmp.com/software/clinical/"&gt;JMP Clinical&lt;/A&gt;.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Even though I have access to both &lt;A href="http://jmp.com/software"&gt;JMP&lt;/A&gt; and &lt;A href="http://sas.com"&gt;SAS&lt;/A&gt;, I sometimes find myself wondering how to replicate a feature in SAS&amp;nbsp;using JSL. The subject of this blog post is how to replicate the SAS data step behavior to select first and last records within by groups.&amp;nbsp;In SAS, this is performed by first sorting the data and using&amp;nbsp;special keywords&amp;nbsp;within the data step.&amp;nbsp;For example, if I had the Big Class data table formatted in SAS and wanted to choose the first boy and girl alphabetically, the program below would accomplish this:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;PRE lang="SAS" escaped="true"&gt;&lt;/PRE&gt;&lt;/P&gt;&lt;P&gt;proc sort data = bigclass;&lt;/P&gt;&lt;P&gt;   by sex name;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;data first;&lt;/P&gt;&lt;P&gt;   set bigclass;&lt;/P&gt;&lt;P&gt;   by sex name;&lt;/P&gt;&lt;P&gt;   if first.sex;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;To choose the last boy and girl alphabetically, I would use &lt;EM&gt;if last.sex;&lt;/EM&gt;.&amp;nbsp;&amp;nbsp; Similar logic applies if&amp;nbsp;I wanted to select&amp;nbsp;first and last within additional by groups.&amp;nbsp;Say, I wanted to pick the shortest person for each name within gender, the following would do that:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;PRE lang="SAS" escaped="true"&gt;&lt;/PRE&gt;&lt;/P&gt;&lt;P&gt;proc sort data = bigclass;&lt;/P&gt;&lt;P&gt;   by sex name height;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;data first;&lt;/P&gt;&lt;P&gt;   set bigclass;&lt;/P&gt;&lt;P&gt;   by sex name height;&lt;/P&gt;&lt;P&gt;   if first.name;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;My colleague &lt;A href="http://blogs.sas.com/content/jmp/author/bradybrady/"&gt;Brady Brady&lt;/A&gt; was kind enough to help me solve this within JSL using Col Min() and Col Max().&amp;nbsp;Figure 1 contains a sample data set. The original data only included Letter (A through J) and Letter 2 (A through D).&amp;nbsp;The data table is sorted by these two variables. You can see below that First.Letter is equal to 1 for the first instance of each letter in Letter (0 otherwise); Last.Letter is a 1 for the last instance of&amp;nbsp;each letter in Letter (0 otherwise). The formulas for these variables is as follows:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;PRE lang="javascript" escaped="true"&gt;&lt;/PRE&gt;&lt;/P&gt;&lt;P&gt;First.Letter = If( Row() == Col Minimum( Row(), :Letter ),&lt;/P&gt;&lt;P&gt;	1,&lt;/P&gt;&lt;P&gt;	0&lt;/P&gt;&lt;P&gt;)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Last.Letter = If( Row() == Col Maximum( Row(), :Letter ),&lt;/P&gt;&lt;P&gt;	1,&lt;/P&gt;&lt;P&gt;	0&lt;/P&gt;&lt;P&gt;)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;To interpret these formulas, the Col M**imum() functions are using :Letter as a by group and getting the minimum or maximum row numbers within each value of Letter. The If() function sets First.Letter = 1 if the current row number equals the :Letter-specific minimum row number.&amp;nbsp;Note that if a particular value for :Letter only had a single row, that record would be considered both the first and the last, with &lt;EM&gt;First.Letter &lt;/EM&gt;= 1 and &lt;EM&gt;Last.Letter = 1&amp;nbsp;&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;A href="https://community.jmp.com/legacyfs/online/wp_images/2015/01/FirstLast.jpg"&gt;&lt;IMG class=" wp-image-15399" src="https://community.jmp.com/legacyfs/online/wp_images/2015/01/FirstLast.jpg" alt="Figure 1. Data Table FirstLast" width="379" height="565" /&gt;&lt;/A&gt;&lt;/P&gt;&lt;P class="wp-caption-text"&gt;&lt;STRONG&gt; Figure 1. Data Table FirstLast&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Similar to the above code for SAS, this can be extended for multiple by variables.&amp;nbsp;Say I wanted to select the first instance of each letter of Letter2 &lt;SPAN style="text-decoration: underline"&gt;within&lt;/SPAN&gt; Letter, I simply add an additional byvar to the function.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;PRE lang="javascript" escaped="true"&gt;&lt;/PRE&gt;&lt;/P&gt;&lt;P&gt;First.Letter2 = If( Row() == Col Minimum( Row(), :Letter, :Letter2 ),&lt;/P&gt;&lt;P&gt;	1,&lt;/P&gt;&lt;P&gt;	0&lt;/P&gt;&lt;P&gt;)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Last.Letter2 = If( Row() == Col Maximum( Row(), :Letter, :Letter2 ),&lt;/P&gt;&lt;P&gt;	1,&lt;/P&gt;&lt;P&gt;	0&lt;/P&gt;&lt;P&gt;)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;These functions have a useful feature in that it allows you to easily subset to&amp;nbsp;by groups&amp;nbsp;where duplicates occur.&amp;nbsp; Selecting rows where &lt;EM&gt;First.Letter &lt;/EM&gt;=&amp;nbsp;0 or &lt;EM&gt;Last.Letter &lt;/EM&gt;= 0&amp;nbsp;will select all rows where :Letter is repeated. In the context of Big Class, using these functions on :Height can allow you to create a subtable where specific heights may be repeated.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Note that in SAS, a sort is required to create the special first.XX last.XX variables.&amp;nbsp; Though the data table above is sorted, this is not a requirement for the JSL code above to work.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Many thanks to Brady Brady for his help!&lt;/P&gt;</description>
      <pubDate>Thu, 05 Feb 2015 18:02:08 GMT</pubDate>
      <guid>https://community.jmp.com/t5/JMP-Blog/Using-JSL-to-select-the-first-or-last-record-in-a-set/ba-p/30532</guid>
      <dc:creator>Richard_Zink</dc:creator>
      <dc:date>2015-02-05T18:02:08Z</dc:date>
    </item>
  </channel>
</rss>

