R のサンプルデータを日本語で探してダウンロードしよう

# R のサンプルデータは宝の山！

## 探すのは大変です... 英語だし...

R では、膨大なサンプルデータが提供されています。
いずれも、R 本体やライブラリをインストールすると、利用できるようになります。
コマンド一発で、そのリストを取得できます。

でも、(当然ですけど) 全部英語なんですよね...
また、どんなデータで、何に使われるのかは短い description から想像するしかない。

```CSV:CSV
survival, imotor (reliability), Reliability data sets
survival, jasa (heart), Stanford Heart Transplant data
survival, jasa1 (heart), Stanford Heart Transplant data
survival, kidney (cancer), Kidney catheter data
...
```

筆者の環境では、826件ありましたが、その中から適切なサンプルデータを探すのは大変です。

## AI にお願いしてみよう

- 説明文を日本語にしてくれると見つけやすいよね
- いちいちダウンロードしなくても、どんな内容かが事前にわかれば、手間が省けるよね

というわけで、以下のプロンプトを **Anthropic Claude-3-haiku API** に投げました。
```$package, $dataset, $description``` には上記 CSV のデータを順次入れてゆきます。

```php:php
        $content = <<<EOT
        統計解析システム R の Package = "{$package}",  Item = "{$dataset}",  Title = "{$description}" の dataset について、日本語で解説せよ。正確な情報のみ出力すること。推測を入れてはならない。
        Title の正確な日本語訳を<title-ja></title-ja>に出力せよ。
        データセットの概要を<overview></overview>に出力せよ。ここには、カラム数、行数などの情報を入れよ。
        データセットの詳しい説明を<details></details>に出力せよ。
        データセットに含まれるカラムの説明を<columns></columns>に出力し、同じ内容を json 形式 (columns は "name", "description")で<columns-json></columns-json>に出力せよ。
        どのような統計解析にどのような目的で用いられるのかを<application></application>に出力せよ。
        あなたの回答がどの程度正確であるか、あなた自身が判断し、0(まったく正確でない)から100(完璧に正確である)のまでの整数値に表し<answer-confidence></answer-confidence>に出力せよ
        EOT;
```

全データについて返事を得るのに2時間近くかかりましたが、無事取得できました。期待以上でした。

例えば、Package = "survival",  Item = "pbc",  Title = "Mayo Clinic Primary Biliary Cholangitis Data" の dataset については、このような返答を得ました。

```<answer-confidence>``` に自分自身の評価を入れさせましたが、すべて90以上のスコアを出してきました。
私が知っているデータセットについては内容を読んで確認しましたが、概ね問題なかったです。もちろん、AI ですからハルシネーションが混ざっている可能性はあります。

```
<title-ja>メイヨークリニック原発性胆汁性胆管炎データ</title-ja>
<overview>
このデータセットは、統計解析システム R の Package "survival" に含まれる "pbc" データセットです。
このデータセットには 312 行 (症例) と 17 列 (変数) が含まれています。
</overview>
<details>
このデータセットは、メイヨークリニックで原発性胆汁性胆管炎と診断された患者の情報を収集したものです。
患者の生存時間、治療の有無、肝機能検査値などの情報が含まれています。
原発性胆汁性胆管炎は慢性の肝疾患で、予後不良な疾患です。
このデータセットは、原発性胆汁性胆管炎の病態や予後を解明するための研究に広く利用されています。
</details>
<columns>
- time: 生存時間 (日数)
- status: 生存状態 (0=生存, 1=死亡)
...中略...
- trig: トリグリセリド値 (mg/dl)
- platelet: 血小板数 (×10^4/μl)
</columns>
<columns-json>
[
  {
    "name": "time",
    "description": "生存時間 (日数)"
  },
  {
    "name": "status",
    "description": "生存状態 (0=生存, 1=死亡)"
  },
  ...中略...
  {
    "name": "trig",
    "description": "トリグリセリド値 (mg/dl)"
  },
  {
    "name": "platelet",
    "description": "血小板数 (×10^4/μl)"
  }
]
</columns-json>
<application>
このデータセットは、原発性胆汁性胆管炎の病態や予後を解明するための研究に広く利用されています。
具体的には、生存時間解析、リスク因子の同定、治療効果の評価などの統計解析に用いられます。
原発性胆汁性胆管炎は予後不良な疾患であり、適切な治療法の開発や予後予測モデルの構築が重要な課題です。
このデータセットを用いた研究成果は、臨床現場での意思決定や新しい治療法の開発に役立つことが期待されます。
</application>
<answer-confidence>95</answer-confidence>
```

## 得られたデータを使って、サンプルデータをダウンロードするためのウェブアプリを作りました

無料で使えます。
https://www.emuyn.net/stats/get_samples_from_r

データを簡単に検索・選択し、内容を確認して CSV でダウンロードすることができます。

AI の出力も含めたデータセットのリストを無料でダウンロードできるようにしてあります。ただし、商用利用はお控えください。

また、ダウンロードしなくても簡単に弊社の **[ブラウザだけで使える無料統計ソフト Reactive stat](https://www.emuyn.net/stats)** で利用することができます。

### 注意事項
- データのダウンロードには、Reactive stat へのログインが必要です
  - クラウドRサーバーで R スクリプトを動かすためのセキュリティ上必要です。あらかじめご了承ください
- 本プログラムは、R言語のパッケージに含まれるサンプルデータをダウンロードするための単なるインターフェイスです
  - データの正確性や完全性は保証されません
  - データの形式によっては対応していないものがあります
  - ご利用にあたっては、個々のパッケージのライセンス表記に従ってください
- データサイズが大きい場合には、処理に時間がかかる場合があります
- 表形式以外は対象外です
- カラム名に “.” (半角ピリオド) が入っていると動作に支障があるため、“_” に置換していますのでご注意ください
- 日本語の部分は、AI に解説させたものです。注意深くプロンプトを設計し、ある程度の確認は行っていますが、ハルシネーションが混ざっている可能性がありますのでご注意ください
- お気づきの点などありましたら、<a href="https://www.emuyn.net/stats/inquiry" class="wikilink1" title="stats:inquiry" data-wiki-id="stats:inquiry">Reactive stat に関するお問い合わせ</a> よりお問い合わせください

## 利用方法

### 一覧からデータセットを選択
![2024-06-07_06h33_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781632/cf0f3558-91ab-2eb4-45b6-189a297eb4ba.png)

### データの概要が表示されます

日本語の部分は AI の出力になります。

![2024-06-07_06h26_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781632/dffd29f2-95af-b58c-4bdd-e97e2e2c17ff.png)

### データが クラウドの R から取得され、基礎統計量が表示されます
データそのものだけでなく、カラムごとの基礎統計量なども表示しますので、どのようなデータなのか簡単に把握できます。

![2024-06-07_06h32_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781632/6ff94411-5d36-8447-86bf-24d009600dcb.png)

![2024-06-04_06h41_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781632/c6051949-5a47-3805-e57d-bae6a50abac0.png)
...以下4項目は省略...

## その他の技術的なこと

### R の全データセットのリストを取得

R には多数のパッケージが存在し、各パッケージには様々なデータセットが含まれています。
まず、R の全パッケージから利用可能なデータセットのリストを取得します。
(実際には、パッケージのリストはサーバーでキャッシュしています)

```R:R
datasets <- data(package = .packages(all.available = TRUE))$results[, c("Package", "Item", "Title")]
jsonlite::toJSON(datasets)
```

上記のコードを実行すると、以下のような JSON 形式のデータが出力されます。

```json:json
[
  ["package1", "dataset1", "Title of dataset1"],
  ["package2", "dataset2", "Title of dataset2"],
  ...
]
```

### R の個別のデータセットを取得

以下のコードで、指定したパッケージの個別のデータセットを取得できます。

```R:R
library(package_name)
data(dataset_name)
jsonlite::toJSON(dataset_name)
```

上記のコードを実行すると、指定したデータセットが JSON 形式で出力されます。出力の構造はデータセットによって異なります。
例えば、以下のような出力結果が得られます。

```json:json
[
  {
    "column1": "value1",
    "column2": "value2",
    ...
  },
  {
    "column1": "value3",
    "column2": "value4",
    ...
  },
  ...
]
```

#### データセット名が dataset (group) 形式の場合

R のデータセットの中には、データセット名が bladder (cancer) のように括弧を含む形式で表現されているものがあります。この形式のデータセット名を扱う場合、括弧の部分を適切に処理する必要があります。

```javascript:javascript
let dataset = row.dataset;
const datasetMatch = dataset.match(/^(.+)\s+\(.+?\)$/);
if (datasetMatch) dataset = datasetMatch[1];
```

#### 取得されたデータの内容が json + α の場合の処理

R からのレスポンスが json だけではない場合があります。
このような場合には、json 部分を抽出する処理を加えています。

```javascript:javascript
let data = [];
try {
  data = JSON.parse(result);
} catch (error) {
  const jsonMatch = result.match(/\[{.*}\]/s);
  if (jsonMatch) {
    data = JSON.parse(jsonMatch[0]);
  }
}
```

#### カラム名がない場合の処理

データが配列の配列になっていて、カラム名がない場合には、```col1, col2, col3...``` を自動的に付与します。

```javascript:javascript
if (Array.isArray(data[0])) {
    // カラム名がない場合は、col1, col2, col3... を自動的に付与
    const columnCount = data[0].length;
    this.sampleColumns = Array.from({
        length: columnCount
    }, (_, i) => ({
        label: `col${i + 1}`,
        field: `col${i + 1}`
    }));
    this.sampleRows = data.map(row => {
        return this.sampleColumns.reduce((obj, col, i) => {
            obj[col.field] = row[i];
            return obj;
        }, {});
    });
} 
```

#### 表形式以外は対象外です

なお、一部のデータセットは、このようなシンプルな表形式ではありません。
このアプリは表形式のデータのみを対象としていますので、例えば深い階層を持つ構造化データなどは対象外としています。