LoginSignup
2
3

More than 5 years have passed since last update.

カイ二乗検定アプリをReactでつくる

Last updated at Posted at 2018-02-28

概要

  • スマートフォン片手にカイ二乗検定できるアプリをreactで書きました
  • create-react-app自体にPWAの準備が整っていますので何もしなくてもPWAとしてうごきます
  • Androidならホーム画面から起動できるアプリとして動作させられます

動作画像

https://gyazo.com/6a6ddac95469d1ee243221f2b253f62d

  • 解析結果をテキストデータとしてコピー

赤矢印の箇所を押すと解析結果をテキスト形式でコピーできます。

https://gyazo.com/e47f897b41aad096795801ac5069badf


* 入力データ
        treat non-treat
case        5         2
control    12         8

* 検定結果
χ2 0.290
p値 0.590 (有意差なし)

* 解析日時
Wed Feb 28 2018 18:52:18 GMT+0900 (JST)

* Powered by
https://case-control-test.firebaseapp.com

すぐ使いたい人

サイトで使いたい

Firebaseのhostingで公開しています。

PWAとしてホーム画面に追加したい

現在は、iOSでは不可。Androidのみです。

でも、このような情報があるのでiOSでPWAでアプリっぽく使える日も近いです。

とりあえず、現状可能なAndroid(chrome)での追加方法の説明をします。

  • Andoridのchromeブラウザでサイトを開き、右上からブラウザのメニューを呼び出し、ホーム画面に追加を押す

https://gyazo.com/e6ca90147b803801816364a6b995cdb6

  • ホーム画面に追加されます。ホーム画面上のアイコンをクリックすればアプリの様にスプラッシュ画面が出て起動できます!

https://gyazo.com/3799b37198a69746f647ed860cc699fb

localで動かしたい

> yarn install
> npm run build

環境

手順

コード概要

  • componentsとcontainersフォルダ
    reactのcomponentをこちらに保存する

  • modulesフォルダ

    • 関数とか(今回であればカイ二乗検定を計算する所とか)
      • Graph: グラフを描画するためのデータを用意する
      • Stat: カイ二乗検定の計算する
    • サービス
      • LocationHref: mailtoなどのリンクを出力
    • 定数
      • MyProfile: 自己紹介の用のURL
      • Site: サイトのURL

https://gyazo.com/fdb4858141db28fab92b93ac02cfef43

コンポーネントの紹介

  • <TwoByTwoTable/>: stateはここだけで管理。あとはバケツリレー。
    • <StatHeader/>: ロゴ
    • <StatBody/>: 結果の表示(統計量、表、グラフ)
      • <CopyToClipboardButton/>: 結果をコピーするためのコンポーネント
      • <SendMailButton/>: 結果をメールで送信するためのコンポーネント
    • <StatForm/>: データを入力するコンポーネント。stateの変更はthis.props.handleChangeでおこなう。
    • <StatFooter/>
      • <AboutMe/>: 自己紹介
      • <AboutThis/>: アプリ紹介

TwoByTwoTable

いつもは、reduxを使うのだけど、今回のアプリには過剰なので素直にバケツリレーで作りました。久しぶりにバケツリレーで書いた。階層が2階層で、非同期のタスクを書く必要がなければ、バケツリレーのほうが書いていて楽しいですね。

src/containers/TwoByTwoTable.js
  handleChange = name => event => {
    const value = event.target.value ? parseInt(event.target.value, 10) : ''
    this.setState({[name]: value})
  }

formで使うメソッド。子コンポーネントでonChange={this.props.handleChange('caseTreatment')}として使うと、state.caseTreatmentを変更することができます。すごい便利。

StatHeader

そんなに説明するところないな。

StatBody

src/containers/StatBody.js
    const chiSq = Stat.chiSq({a: caseTreatment, b: caseNonTreatment, c: controlTreatment, d: controlNonTreatment})
    const chiP = Stat.chiP(chiSq)

今回χ2検定を行うための関数を呼び出しています。

  • χ2値を計算する(Stat.chiSq)
  • chiSq値を累積分布関数にわたしてあげる(Stat.chiSq)とp値を出力してくれる

StatForm

src/containers/StatForm.js
                    <TextField
                      id={'number'}
                      autoFocus
                      type={'number'}
                      margin={'normal'}
                      onChange={this.props.handleChange('caseTreatment')}
                      value={this.props['caseTreatment']}
                    />

onChangeのhandleChangeでstateを変化させ、propsとして受け取った値をvalueに入れる。

PWA用のカスタマイズ

create-react-appで作ると、最初からPWAの準備はできています。

public/index.html
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

なので、デフォルトで作られているサイト名やアイコン(logo.svgとfavicon.icoとlogo.png)を若干カスタマイズすればOKです。

public/manifest.json
  "short_name": "2x2 STAT",
  "name": "Case control data analysis by chi squared test",

統計解析

Stat.js

χ2値の計算。適当に教科書から取ってきました。ごく一般的な数式。このサイトとおなじです。

export const chiSq = ({a, b, c, d}) => {
  if (!isValid({a, b, c, d})) return 'error'
  const n = a + b + c + d
  const calc = ((a * d - b * c) ** 2) * (n / ((a + b) * (c + d) * (a + c) * (b + d)))
  return (calc.toFixed(3))
}

p値の計算。自由度1のχ2の累積分布関数から計算する。累積分布関数はchi-squaredをつかいました。

export const chiP = (chiSq) => {
  if (!(chiSq > 0)) return 'error'
  const df = 1 // dfは自由度
  const calc = 1 - chi.cdf(chiSq, df) // cdfは累積分布関数
  return calc.toFixed(3)
}

その他ライブラリの紹介

fontawesome

  • twitterとgithubとfacebookのアイコン画像が欲しいので導入。fontawesomeってここ半年でバージョンが5になったのですね。svgになったので、表現力が向上したっぽい。
src/components/AboutThis.js
import FontAwesomeIcon from '@fortawesome/react-fontawesome'
import { faGithub } from '@fortawesome/fontawesome-free-brands/index'

省略
 <FontAwesomeIcon icon={faGithub} size="lg" fixedWidth/>

react-chartjs-2

グラフを作成するためのライブラリ。chart.jsをreact用のコンポーネントとして使えるされたラッパー。

dataをobjectで渡せば描画できます。

src/containers/StatBody.js
import { Doughnut } from 'react-chartjs-2'

省略
<Doughnut data={Graph.data(controlTreatment, controlNonTreatment)} options={Graph.options}/>
src/modules/Graph.js
export const data = (t = 10, nt = 10) => {
  return {
    labels: [
      'Non Treat',
      'Treat',
    ],
    datasets: [{
      data: [nt, t],
      backgroundColor: [
        color.nonTreat,
        color.treat,
      ],
      hoverBackgroundColor: [
        color.nonTreat,
        color.treat,
      ],
    }],
  }
}

list-it

  • 表をテキストで出力する時に、ずれないようにうまい具合に空白を入れてくれる。すごい便利。

src/modules/Stat.js
export const tableString = ({a, b, c, d}) => {
  if (!isValid({a, b, c, d})) return 'no result'
  const arr = [
    ['', 'treat', 'non-treat'],
    ['case', a, b],
    ['control', c, d],
  ]
  let buf = listIt.buffer({'autoAlign': true})
  buf.d(arr)
  return (buf.toString())
}

react-scroll-to-component

任意の場所に移動するためのメソッド。

移動したい所にrefを定義してscrollToComponent(ref, option)を実行すると、refの場所にスクロールします。

src/containers/TwoByTwoTable.js
  componentDidMount () {
    this.scrollToForm()
  }

  scrollToForm = () => {
    scrollToComponent(this['form'], {
      align: 'bottom',
      duration: 1000,
    })
  }
省略
            <StatForm {...this.state}
                      handleChange={this.handleChange}
                      ref={(section) => {this['form'] = section}}
            />

react-share

有名どころのシェアボタンを作成出来るreact component。ボタンと画像を別々にimpportして、画像(TwitterIcon)をボタン(TwitterShareButton)囲むところがミソ。

import {
  TwitterShareButton,
  TwitterIcon,
} from 'react-share'

省略
<TwitterShareButton
  title={Site.title}
  url={Site.rootUrl}
  hashtags={[Site.title]}
  style={styles.buttonMarginRight}
>
  <TwitterIcon
    size={32}
    round/>
</TwitterShareButton>

発展

  • 統計量を増やすかも(オッズ比とか陽性的中率とか検出力とか)
  • 分散データの解析(t検定は作るつもり)。ただし、ノンパラはライブラリがあれば実装します。自分で計算書くのはつらいので。

備考

もっと色々やりたい場合は、PCの目の前に腰を据えて、RとかSASとSPSSとかSとか使ってください。

以上。

Happy Statistics.

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3