SAS Viyaでデータをカウントする

[SAS Viya](https://www.sas.com/ja_jp/software/viya.html)はAIプラットフォームになります。Webブラウザ上で機械学習の設計、実行ができるStudioという環境も用意されていますが、開発者はプログラミングコードで開発することも可能です。プログラミング言語はJava/Python/R/SASが選べます。

機械学習を用いる際に専用のテーブル（casTable）を用いますが、今回はデータのカウントについて紹介します。

## データを確認する

今回は organics.sas7bdat を用います。

```python
organics = sess.upload('organics.sas7bdat')
```

データは以下のようになっています。

```python
organics.casTable.head()
```

<table border="1" class="dataframe"><caption>Selected Rows from Table ORGANICS</caption>
  <thead>
    <tr style="text-align: right;">
      <th title=""></th>
      <th title="Customer Id">CUSTID</th>
      <th title="GENDER">GENDER</th>
      <th title="Date of Birth">DOB</th>
      <th title="Date data taken from data base">EDATE</th>
      <th title="Age">AGE</th>
      <th title="Age Group 1">AGEGRP1</th>
      <th title="Age Group 2">AGEGRP2</th>
      <th title="TV Region">TV_REG</th>
      <th title="Neighborhood Group">NGROUP</th>
      <th title="Type of Residential Neighborhood">NEIGHBORHOOD</th>
      <th title="Loyalty card application date">LCDATE</th>
      <th title="Number of Organic Products Purchased">ORGANICS</th>
      <th title="Total Amount Spent">BILL</th>
      <th title="Geographic Region">REGION</th>
      <th title="Customer Loyalty Status">CLASS</th>
      <th title="Organics Purchased?">ORGYN</th>
      <th title="Affluence grade">AFFL</th>
      <th title="Years as Loyalty Card Member">LTIME</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0000000140</td>
      <td>U</td>
      <td>1921-09-16</td>
      <td>1998-02-23</td>
      <td>76.0</td>
      <td>60-80</td>
      <td>70-80</td>
      <td>Wales &amp; West</td>
      <td>C</td>
      <td>16</td>
      <td>1994-11-07</td>
      <td>0.0</td>
      <td>16000.00</td>
      <td>Midlands</td>
      <td>Gold</td>
      <td>0.0</td>
      <td>10.0</td>
      <td>4.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>0000000620</td>
      <td>U</td>
      <td>1949-02-12</td>
      <td>1998-02-23</td>
      <td>49.0</td>
      <td>40-60</td>
      <td>40-50</td>
      <td>Wales &amp; West</td>
      <td>D</td>
      <td>35</td>
      <td>1993-06-04</td>
      <td>0.0</td>
      <td>6000.00</td>
      <td>Midlands</td>
      <td>Gold</td>
      <td>0.0</td>
      <td>4.0</td>
      <td>5.0</td>
    </tr>
  </tbody>
</table>

## カウントを取る

カウントは district メソッドを使います。

```py
organics.distinct()
```

結果は例えば以下のように返ってきます。

<div class="cas-results-key"><b>&#167; Distinct</b></div>
<div class="cas-results-body">
<div>
<table border="1" class="dataframe"><caption>Distinct Counts for ORGANICS</caption>
  <thead>
    <tr style="text-align: right;">
      <th title=""></th>
      <th title="Analysis Variable">Column</th>
      <th title="Number of Distinct Values">NDistinct</th>
      <th title="Number of Missing Values">NMiss</th>
      <th title="Truncated">Trunc</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>CUSTID</td>
      <td>22223.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>GENDER</td>
      <td>4.0</td>
      <td>2512.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>DOB</td>
      <td>12868.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>EDATE</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>AGE</td>
      <td>63.0</td>
      <td>1508.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>5</th>
      <td>AGEGRP1</td>
      <td>5.0</td>
      <td>1508.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>6</th>
      <td>AGEGRP2</td>
      <td>8.0</td>
      <td>1508.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>7</th>
      <td>TV_REG</td>
      <td>14.0</td>
      <td>465.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>8</th>
      <td>NGROUP</td>
      <td>8.0</td>
      <td>674.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>9</th>
      <td>NEIGHBORHOOD</td>
      <td>56.0</td>
      <td>674.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>10</th>
      <td>LCDATE</td>
      <td>3535.0</td>
      <td>281.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>11</th>
      <td>ORGANICS</td>
      <td>4.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>12</th>
      <td>BILL</td>
      <td>2606.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>13</th>
      <td>REGION</td>
      <td>6.0</td>
      <td>465.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>14</th>
      <td>CLASS</td>
      <td>4.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>15</th>
      <td>ORGYN</td>
      <td>2.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>16</th>
      <td>AFFL</td>
      <td>34.0</td>
      <td>1085.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>17</th>
      <td>LTIME</td>
      <td>40.0</td>
      <td>281.0</td>
      <td>0.0</td>
    </tr>
  </tbody>
</table>
</div>
</div>
<div class="cas-output-area"></div>
<p class="cas-results-performance"><small><span class="cas-elapsed">elapsed 0.0482s</span> &#183; <span class="cas-user">user 0.104s</span> &#183; <span class="cas-sys">sys 0.005s</span> &#183; <span class="cas-memory">mem 11.4MB</span></small></p>

データ数によって絞り込みも行えます。

```py
organics.distinct(maxnvals=500)
```


<div class="cas-results-key"><b>&#167; Distinct</b></div>
<div class="cas-results-body">
<div>
<table border="1" class="dataframe"><caption>Distinct Counts for ORGANICS</caption>
  <thead>
    <tr style="text-align: right;">
      <th title=""></th>
      <th title="Analysis Variable">Column</th>
      <th title="Number of Distinct Values">NDistinct</th>
      <th title="Number of Missing Values">NMiss</th>
      <th title="Truncated">Trunc</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>CUSTID</td>
      <td>500.0</td>
      <td>0.0</td>
      <td>1.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>GENDER</td>
      <td>4.0</td>
      <td>2512.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>DOB</td>
      <td>500.0</td>
      <td>0.0</td>
      <td>1.0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>EDATE</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>AGE</td>
      <td>63.0</td>
      <td>1508.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>5</th>
      <td>AGEGRP1</td>
      <td>5.0</td>
      <td>1508.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>6</th>
      <td>AGEGRP2</td>
      <td>8.0</td>
      <td>1508.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>7</th>
      <td>TV_REG</td>
      <td>14.0</td>
      <td>465.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>8</th>
      <td>NGROUP</td>
      <td>8.0</td>
      <td>674.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>9</th>
      <td>NEIGHBORHOOD</td>
      <td>56.0</td>
      <td>674.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>10</th>
      <td>LCDATE</td>
      <td>500.0</td>
      <td>281.0</td>
      <td>1.0</td>
    </tr>
    <tr>
      <th>11</th>
      <td>ORGANICS</td>
      <td>4.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>12</th>
      <td>BILL</td>
      <td>500.0</td>
      <td>0.0</td>
      <td>1.0</td>
    </tr>
    <tr>
      <th>13</th>
      <td>REGION</td>
      <td>6.0</td>
      <td>465.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>14</th>
      <td>CLASS</td>
      <td>4.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>15</th>
      <td>ORGYN</td>
      <td>2.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>16</th>
      <td>AFFL</td>
      <td>34.0</td>
      <td>1085.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>17</th>
      <td>LTIME</td>
      <td>40.0</td>
      <td>281.0</td>
      <td>0.0</td>
    </tr>
  </tbody>
</table>
</div>
</div>
<div class="cas-output-area"></div>
<p class="cas-results-performance"><small><span class="cas-elapsed">elapsed 0.0299s</span> &#183; <span class="cas-user">user 0.075s</span> &#183; <span class="cas-sys">sys 0.003s</span> &#183; <span class="cas-memory">mem 5.96MB</span></small></p>

## 結果を別テーブルにする

以下のように書くと結果を別テーブルに出力できます。

```python
result = sess.CASTable('distinctOutput', replace=True)
organics.distinct(maxnvals=500, casout=result)
result.head()
```

結果は以下のようになります。

<div>
<table border="1" class="dataframe"><caption>Selected Rows from Table DISTINCTOUTPUT</caption>
  <thead>
    <tr style="text-align: right;">
      <th title=""></th>
      <th title="_Column_">_Column_</th>
      <th title="_NDis_">_NDis_</th>
      <th title="_NMiss_">_NMiss_</th>
      <th title="_Truncated_">_Truncated_</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>CUSTID</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>1.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>GENDER</td>
      <td>4.0</td>
      <td>2512.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>DOB</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>1.0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>EDATE</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>AGE</td>
      <td>63.0</td>
      <td>1508.0</td>
      <td>0.0</td>
    </tr>
  </tbody>
</table>
</div>

さらにこの結果テーブルをカウントごとに分類してみます。

```python
out1 = organics.columninfo()['ColumnInfo']
out2 = organics.distinct(maxnvals=1000)['Distinct']
out3 = pd.merge(out1, out2, left_on='Column', right_on='Column', how='left')
varlist = {'cats': [], 'conts': [], 'others': []}
for index, row in out3.iterrows():
    varname = row['Column'].lower()
    vartype = row['Type'].lower()
    if vartype == 'char' and row['NDistinct'] <= 128:
        varlist['cats'].append(varname)
    elif vartype == 'double' and row['NDistinct'] <= 16:
        varlist['cats'].append(varname)
    elif vartype == 'double' and row['NDistinct'] > 16:
        varlist['conts'].append(varname)
    else:
        varlist['others'].append(varname)
print(varlist)
```

```py
{
  'cats': ['gender', 'edate', 'agegrp1', 'agegrp2', 'tv_reg', 'ngroup', 'neighborhood', 'organics', 'region', 'class', 'orgyn'],
  'conts': ['dob', 'age', 'lcdate', 'bill', 'affl', 'ltime'],
  'others': ['custid']
}
```

## まとめ

Pythonと組み合わせることで分析とデータの傾向を確認するのが簡単になります。ぜひご利用ください。