1
1
import { useZustand } from '../lib/useZustand'
2
- import { Select , Input , Button , Form } from 'antd'
2
+ import { Select , Input , Button , Form , InputNumber , Space } from 'antd'
3
3
import { useState } from 'react'
4
- import ttest from '@stdlib/stats/ttest'
5
4
import { flushSync } from 'react-dom'
6
5
import { generatePResult } from '../lib/utils'
7
- import { std } from 'psych-lib'
6
+ import { OneSampleTTest as T } from 'psych-lib'
8
7
9
8
type Option = {
10
9
/** 变量名 */
11
10
variable : string
12
11
/** 检验值, 默认 0 */
13
12
expect : number
14
- /** 单双尾检验, 默认 two-sided */
15
- alternative : 'two-sided' | 'less' | 'greater'
13
+ /** 单双尾检验, 默认双尾 */
14
+ twoside : boolean
15
+ /** 显著性水平, 默认 0.05 */
16
+ alpha : number
16
17
}
17
18
type Result = {
18
- [ key : string ] : unknown
19
+ m : T
19
20
} & Option
20
21
21
22
export function OneSampleTTest ( ) {
@@ -27,17 +28,12 @@ export function OneSampleTTest() {
27
28
try {
28
29
messageApi ?. loading ( '正在处理数据...' )
29
30
const timestamp = Date . now ( )
31
+ const { variable, expect, twoside, alpha } = values
30
32
const data = dataRows
31
- . map ( ( row ) => row [ values . variable ] )
33
+ . map ( ( row ) => row [ variable ] )
32
34
. filter ( ( v ) => typeof v !== 'undefined' && ! isNaN ( Number ( v ) ) )
33
35
. map ( ( v ) => Number ( v ) )
34
- const result = ttest ( data , { mu : + values . expect , alternative : values . alternative } )
35
- setResult ( {
36
- variable : values . variable ,
37
- expect : + values . expect ,
38
- std : std ( data ) ,
39
- ...result
40
- } as Result )
36
+ setResult ( { ...values , m : new T ( data , expect , twoside , alpha ) } )
41
37
messageApi ?. destroy ( )
42
38
messageApi ?. success ( `数据处理完成, 用时 ${ Date . now ( ) - timestamp } 毫秒` )
43
39
} catch ( error ) {
@@ -62,7 +58,8 @@ export function OneSampleTTest() {
62
58
autoComplete = 'off'
63
59
initialValues = { {
64
60
expect : 0 ,
65
- alternative : 'two-sided' ,
61
+ twoside : true ,
62
+ alpha : 0.05 ,
66
63
} }
67
64
disabled = { disabled }
68
65
>
@@ -93,19 +90,35 @@ export function OneSampleTTest() {
93
90
type = 'number'
94
91
/>
95
92
</ Form . Item >
96
- < Form . Item
97
- label = '单双尾检验'
98
- name = 'alternative'
99
- rules = { [ { required : true , message : '请选择单双尾检验' } ] }
100
- >
101
- < Select
102
- className = 'w-full'
103
- placeholder = '请选择单双尾检验'
104
- >
105
- < Select . Option value = 'two-sided' > 双尾检验</ Select . Option >
106
- < Select . Option value = 'less' > 单尾检验(左)</ Select . Option >
107
- < Select . Option value = 'greater' > 单尾检验(右)</ Select . Option >
108
- </ Select >
93
+ < Form . Item label = '单双尾检验和显著性水平' >
94
+ < Space . Compact block >
95
+ < Form . Item
96
+ noStyle
97
+ name = 'twoside'
98
+ rules = { [ { required : true , message : '请选择单双尾检验' } ] }
99
+ >
100
+ < Select
101
+ className = 'w-full'
102
+ placeholder = '请选择单双尾检验'
103
+ >
104
+ < Select . Option value = { true } > 双尾检验</ Select . Option >
105
+ < Select . Option value = { false } > 单尾检验</ Select . Option >
106
+ </ Select >
107
+ </ Form . Item >
108
+ < Form . Item
109
+ noStyle
110
+ name = 'alpha'
111
+ rules = { [ { required : true , message : '请输入显著性水平' } ] }
112
+ >
113
+ < InputNumber
114
+ className = 'w-full'
115
+ placeholder = '请输入显著性水平'
116
+ min = { 0 }
117
+ max = { 1 }
118
+ step = { 0.01 }
119
+ />
120
+ </ Form . Item >
121
+ </ Space . Compact >
109
122
</ Form . Item >
110
123
< Form . Item >
111
124
< Button
@@ -125,29 +138,29 @@ export function OneSampleTTest() {
125
138
{ result ? (
126
139
< div className = 'w-full h-full overflow-auto' >
127
140
128
- < p className = 'text-lg mb-2 text-center w-full' > 单样本T检验 ({ result . alternative === 'two-sided' ? '双尾' : '单尾' } )</ p >
129
- < p className = 'text-xs mb-3 text-center w-full' > 方法: Student's T Test | H< sub > 0</ sub > : 均值={ result . expect } | 显著性水平(α): 0.05 </ p >
141
+ < p className = 'text-lg mb-2 text-center w-full' > 单样本T检验 ({ result . twoside ? '双尾' : '单尾' } )</ p >
142
+ < p className = 'text-xs mb-3 text-center w-full' > 方法: Student's T Test | H< sub > 0</ sub > : 均值={ result . expect } | 显著性水平(α): { result . alpha } </ p >
130
143
< table className = 'three-line-table' >
131
144
< thead >
132
145
< tr >
133
146
< td > 样本均值</ td >
134
147
< td > 自由度</ td >
135
148
< td > t</ td >
136
149
< td > p</ td >
137
- < td > 95 %置信区间</ td >
150
+ < td > { ( 100 - result . alpha * 100 ) . toFixed ( 3 ) } %置信区间</ td >
138
151
< td > 效应量 (Cohen's d)</ td >
139
152
< td > 测定系数 (R< sup > 2</ sup > )</ td >
140
153
</ tr >
141
154
</ thead >
142
155
< tbody >
143
156
< tr >
144
- < td > { ( result . mean as number ) . toFixed ( 3 ) } </ td >
145
- < td > { ( result . df as number ) . toFixed ( 3 ) } </ td >
146
- < td > { generatePResult ( result . statistic , result . pValue ) . statistic } </ td >
147
- < td > { generatePResult ( result . statistic , result . pValue ) . p } </ td >
148
- < td > { `[${ ( result . ci as [ number , number ] ) [ 0 ] . toFixed ( 3 ) } , ${ ( result . ci as [ number , number ] ) [ 1 ] . toFixed ( 3 ) } )` } </ td >
149
- < td > { ( ( ( result . mean as number ) - result . expect ) / ( result . std as number ) ) . toFixed ( 3 ) } </ td >
150
- < td > { ( ( ( result . statistic as number ) ** 2 ) / ( ( ( result . statistic as number ) ** 2 ) + ( result . df as number ) ) ) . toFixed ( 3 ) } </ td >
157
+ < td > { result . m . mean . toFixed ( 3 ) } </ td >
158
+ < td > { result . m . df . toFixed ( 3 ) } </ td >
159
+ < td > { generatePResult ( result . m . t , result . m . p ) . statistic } </ td >
160
+ < td > { generatePResult ( result . m . t , result . m . p ) . p } </ td >
161
+ < td > { `[${ result . m . ci [ 0 ] . toFixed ( 3 ) } , ${ result . m . ci [ 1 ] . toFixed ( 3 ) } )` } </ td >
162
+ < td > { result . m . cohenD . toFixed ( 3 ) } </ td >
163
+ < td > { result . m . r2 . toFixed ( 3 ) } </ td >
151
164
</ tr >
152
165
</ tbody >
153
166
</ table >
@@ -164,10 +177,10 @@ export function OneSampleTTest() {
164
177
</ thead >
165
178
< tbody >
166
179
< tr >
167
- < td > { ( result . mean as number ) . toFixed ( 3 ) } </ td >
168
- < td > { ( result . std as number ) . toFixed ( 3 ) } </ td >
169
- < td > { ( result . df as number ) + 1 } </ td >
170
- < td > { ( result . df as number ) } </ td >
180
+ < td > { result . m . mean . toFixed ( 3 ) } </ td >
181
+ < td > { result . m . std . toFixed ( 3 ) } </ td >
182
+ < td > { result . m . df + 1 } </ td >
183
+ < td > { result . m . df } </ td >
171
184
</ tr >
172
185
</ tbody >
173
186
</ table >
0 commit comments