statsample 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +3 -0
- data/Manifest.txt +1 -1
- data/README.txt +40 -36
- data/demo/correlation_matrix.rb +11 -0
- data/demo/dominance_analysis_bootstrap.rb +0 -4
- data/demo/polychoric.rb +14 -6
- data/lib/distribution.rb +1 -0
- data/lib/distribution/normal.rb +18 -18
- data/lib/distribution/normalbivariate.rb +189 -11
- data/lib/statsample.rb +1 -1
- data/lib/statsample/bivariate/polychoric.rb +232 -129
- data/lib/statsample/bivariate/tetrachoric.rb +8 -4
- data/lib/statsample/combination.rb +2 -2
- data/lib/statsample/dominanceanalysis/bootstrap.rb +11 -6
- data/lib/statsample/factor/pca.rb +1 -1
- data/lib/statsample/graph/gdchart.rb +2 -2
- data/lib/statsample/graph/svgboxplot.rb +100 -100
- data/lib/statsample/graph/svggraph.rb +1 -1
- data/lib/statsample/graph/svghistogram.rb +1 -1
- data/lib/statsample/graph/svgscatterplot.rb +96 -98
- data/test/test_bivariate.rb +27 -4
- data/test/test_distribution.rb +17 -16
- metadata +5 -5
- data/lib/statsample/htmlreport.rb +0 -255
data/lib/statsample.rb
CHANGED
@@ -21,31 +21,51 @@ module Statsample
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
-
#
|
24
|
+
# == Polychoric correlation.
|
25
25
|
#
|
26
|
-
# The polychoric correlation
|
27
|
-
#
|
28
|
-
|
26
|
+
# The <em>polychoric</em> correlation is a measure of
|
27
|
+
# bivariate association arising when both observed variates
|
28
|
+
# are ordered, categorical variables that result from polychotomizing
|
29
|
+
# the two undelying continuous variables (Drasgow, 2006)
|
30
|
+
#
|
31
|
+
# According to Drasgow(2006), there are tree methods to estimate
|
32
|
+
# the polychoric correlation:
|
33
|
+
#
|
34
|
+
# 1. Maximum Likehood Estimator
|
35
|
+
# 2. Two-step estimator and
|
36
|
+
# 3. Polychoric series estimate.
|
37
|
+
#
|
38
|
+
# By default, Two-step estimation are used. You can select
|
39
|
+
# the estimation method with method attribute
|
40
|
+
#
|
41
|
+
# See extensive documentation on Uebersax(2002) and Drasgow(2006)
|
29
42
|
class Polychoric
|
30
43
|
include GetText
|
31
44
|
bindtextdomain("statsample")
|
32
45
|
# Name of the analysis
|
33
46
|
attr_accessor :name
|
34
|
-
# Max number of iterations used on iterative methods. Default to
|
47
|
+
# Max number of iterations used on iterative methods. Default to MAX_ITERATIONS
|
35
48
|
attr_accessor :max_iterations
|
36
49
|
# Debug algorithm (See iterations, for example)
|
37
50
|
attr_accessor :debug
|
38
51
|
# Minimizer type. Default GSL::Min::FMinimizer::BRENT
|
39
52
|
# See http://rb-gsl.rubyforge.org/min.html for reference.
|
40
|
-
attr_accessor :
|
41
|
-
|
42
|
-
#
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
|
53
|
+
attr_accessor :minimizer_type_two_step
|
54
|
+
|
55
|
+
# Minimizer type. Default GSL::Min::FMinimizer::BRENT
|
56
|
+
# See http://rb-gsl.rubyforge.org/min.html for reference.
|
57
|
+
attr_accessor :minimizer_type_joint
|
58
|
+
|
59
|
+
|
60
|
+
# Method of calculation of polychoric series.
|
61
|
+
#
|
62
|
+
# :two_step:: two-step ML, based on code by Gegenfurtner(1992)
|
63
|
+
# :polychoric_series:: polychoric series estimate, using
|
64
|
+
# algorithm AS87 by Martinson and Hamdan (1975)
|
65
|
+
# :joint: one-step ML, based on R package 'polycor'
|
66
|
+
# by J.Fox.
|
47
67
|
attr_accessor :method
|
48
|
-
# Absolute error for iteration.
|
68
|
+
# Absolute error for iteration.
|
49
69
|
attr_accessor :epsilon
|
50
70
|
|
51
71
|
# Number of iterations
|
@@ -54,12 +74,31 @@ module Statsample
|
|
54
74
|
# Log of algorithm
|
55
75
|
attr_reader :log
|
56
76
|
attr_reader :loglike
|
57
|
-
|
58
|
-
|
59
|
-
|
77
|
+
|
78
|
+
METHOD=:two_step
|
79
|
+
MAX_ITERATIONS=300
|
80
|
+
EPSILON=0.000001
|
81
|
+
MINIMIZER_TYPE_TWO_STEP="brent"
|
82
|
+
MINIMIZER_TYPE_JOINT="nmsimplex"
|
60
83
|
def new_with_vectors(v1,v2)
|
61
84
|
Polychoric.new(Crosstab.new(v1,v2).to_matrix)
|
62
85
|
end
|
86
|
+
# Calculate Polychoric correlation
|
87
|
+
# You should enter a Matrix with ordered data. For
|
88
|
+
# -------------------
|
89
|
+
# | y=0 | y=1 | y=2 |
|
90
|
+
# -------------------
|
91
|
+
# x = 0 | 1 | 10 | 20 |
|
92
|
+
# -------------------
|
93
|
+
# x = 1 | 20 | 20 | 50 |
|
94
|
+
# -------------------
|
95
|
+
#
|
96
|
+
# The code will be
|
97
|
+
#
|
98
|
+
# matrix=Matrix[[1,10,20],[20,20,50]]
|
99
|
+
# poly=Statsample::Bivariate::Polychoric.new(matrix, :method=>:joint)
|
100
|
+
# puts poly.r
|
101
|
+
|
63
102
|
|
64
103
|
def initialize(matrix, opts=Hash.new)
|
65
104
|
@matrix=matrix
|
@@ -68,68 +107,126 @@ module Statsample
|
|
68
107
|
raise "row size <1" if @m<=1
|
69
108
|
raise "column size <1" if @n<=1
|
70
109
|
|
71
|
-
@method
|
110
|
+
@method=METHOD
|
72
111
|
@name="Polychoric correlation"
|
73
112
|
@max_iterations=MAX_ITERATIONS
|
74
113
|
@epsilon=EPSILON
|
75
|
-
@
|
114
|
+
@minimizer_type_two_step=MINIMIZER_TYPE_TWO_STEP
|
115
|
+
@minimizer_type_joint=MINIMIZER_TYPE_JOINT
|
76
116
|
@debug=false
|
77
117
|
@iteration=nil
|
78
118
|
opts.each{|k,v|
|
79
119
|
self.send("#{k}=",v) if self.respond_to? k
|
80
120
|
}
|
81
121
|
@r=nil
|
122
|
+
compute_basic_parameters
|
82
123
|
end
|
124
|
+
# Returns the polychoric correlation
|
83
125
|
def r
|
84
126
|
if @r.nil?
|
85
127
|
compute
|
86
128
|
end
|
87
129
|
@r
|
88
130
|
end
|
131
|
+
# Returns the rows thresholds
|
89
132
|
|
90
133
|
def threshold_x
|
91
134
|
if @alpha.nil?
|
92
135
|
compute
|
93
136
|
end
|
94
|
-
@alpha
|
137
|
+
@alpha
|
95
138
|
end
|
139
|
+
# Returns the column thresholds
|
96
140
|
|
97
141
|
def threshold_y
|
98
142
|
if @beta.nil?
|
99
143
|
compute
|
100
144
|
end
|
101
|
-
@beta
|
145
|
+
@beta
|
102
146
|
end
|
103
147
|
|
104
148
|
|
105
|
-
|
149
|
+
# Start the computation of polychoric correlation
|
150
|
+
# based on attribute method
|
106
151
|
def compute
|
107
152
|
if @method==:two_step
|
108
153
|
compute_two_step_mle_drasgow
|
109
|
-
elsif @method==:
|
110
|
-
|
154
|
+
elsif @method==:joint
|
155
|
+
compute_one_step_mle
|
156
|
+
elsif @method==:polychoric_series
|
157
|
+
compute_polychoric_series
|
111
158
|
else
|
112
159
|
raise "Not implemented"
|
113
160
|
end
|
114
161
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
162
|
+
|
163
|
+
def loglike_data
|
164
|
+
loglike=0
|
165
|
+
@nr.times { |i|
|
166
|
+
@nc.times { |j|
|
167
|
+
res=@matrix[i,j].quo(@total)
|
168
|
+
if (res==0)
|
169
|
+
# puts "Correccion"
|
170
|
+
res=1e-16
|
171
|
+
end
|
172
|
+
loglike+= @matrix[i,j] * Math::log(res )
|
173
|
+
}
|
174
|
+
}
|
175
|
+
loglike
|
176
|
+
end
|
177
|
+
def chi_square
|
178
|
+
if @loglike_model.nil?
|
179
|
+
compute
|
180
|
+
end
|
181
|
+
-2*(@loglike_model-loglike_data)
|
182
|
+
end
|
183
|
+
def chi_square_df
|
184
|
+
(@nr*@nc)-@nc-@nr
|
185
|
+
end
|
186
|
+
def loglike(alpha,beta,rho)
|
187
|
+
if rho.abs>0.9999
|
188
|
+
rho= (rho>0) ? 0.9999 : -0.9999
|
189
|
+
end
|
190
|
+
|
191
|
+
loglike=0
|
192
|
+
pd=@nr.times.collect{ [0]*@nc}
|
193
|
+
pc=@nr.times.collect{ [0]*@nc}
|
194
|
+
@nr.times { |i|
|
195
|
+
@nc.times { |j|
|
196
|
+
#puts "i:#{i} | j:#{j}"
|
197
|
+
if i==@nr-1 and j==@nc-1
|
198
|
+
pd[i][j]=1.0
|
199
|
+
else
|
200
|
+
a=(i==@nr-1) ? 100: alpha[i]
|
201
|
+
b=(j==@nc-1) ? 100: beta[j]
|
202
|
+
#puts "a:#{a} b:#{b}"
|
203
|
+
pd[i][j]=Distribution::NormalBivariate.cdf(a, b, rho)
|
204
|
+
end
|
205
|
+
pc[i][j] = pd[i][j]
|
206
|
+
pd[i][j] = pd[i][j] - pc[i-1][j] if i>0
|
207
|
+
pd[i][j] = pd[i][j] - pc[i][j-1] if j>0
|
208
|
+
pd[i][j] = pd[i][j] + pc[i-1][j-1] if (i>0 and j>0)
|
209
|
+
res= pd[i][j]
|
210
|
+
#puts "i:#{i} | j:#{j} | ac: #{sprintf("%0.4f", pc[i][j])} | pd: #{sprintf("%0.4f", pd[i][j])} | res:#{sprintf("%0.4f", res)}"
|
211
|
+
if (res==0)
|
212
|
+
# puts "Correccion"
|
213
|
+
res=1e-16
|
214
|
+
end
|
215
|
+
loglike+= @matrix[i,j] * Math::log( res )
|
216
|
+
}
|
217
|
+
}
|
218
|
+
@pd=pd
|
219
|
+
-loglike
|
220
|
+
end
|
221
|
+
def compute_basic_parameters
|
125
222
|
@nr=@matrix.row_size
|
126
223
|
@nc=@matrix.column_size
|
127
224
|
@sumr=[0]*@matrix.row_size
|
128
225
|
@sumrac=[0]*@matrix.row_size
|
129
226
|
@sumc=[0]*@matrix.column_size
|
130
227
|
@sumcac=[0]*@matrix.column_size
|
131
|
-
@alpha=[0]
|
132
|
-
@beta=[0]
|
228
|
+
@alpha=[0]*(@nr-1)
|
229
|
+
@beta=[0]*(@nc-1)
|
133
230
|
@total=0
|
134
231
|
@nr.times do |i|
|
135
232
|
@nc.times do |j|
|
@@ -150,44 +247,31 @@ module Statsample
|
|
150
247
|
@beta[i]=Distribution::Normal.p_value(@sumcac[i] / @total.to_f)
|
151
248
|
ac=@sumcac[i]
|
152
249
|
end
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
if res==0.0
|
170
|
-
res=1e-15
|
171
|
-
end
|
172
|
-
|
173
|
-
# puts "i:#{i} | j:#{j} | ac: #{sprintf("%0.4f", pc[i][j])} | pd: #{sprintf("%0.4f", pd[i][j])} | res:#{sprintf("%0.4f", res)}"
|
174
|
-
loglike+= @matrix[i,j] * Math::log( res )
|
175
|
-
}
|
176
|
-
}
|
177
|
-
# p pd
|
178
|
-
@loglike=loglike
|
179
|
-
@pd=pd
|
180
|
-
-loglike
|
250
|
+
end
|
251
|
+
# Computation of polychoric correlation usign two-step ML estimation.
|
252
|
+
#
|
253
|
+
# Two-step ML estimation "first estimates the thresholds from the one-way marginal frequencies, then estimates rho, conditional on these thresholds, via maximum likelihood" (Uebersax, 2006).
|
254
|
+
#
|
255
|
+
# The algorithm is based on code by Gegenfurtner(1992).
|
256
|
+
#
|
257
|
+
# <b>References</b>:
|
258
|
+
# * Gegenfurtner, K. (1992). PRAXIS: Brent's algorithm for function minimization. Behavior Research Methods, Instruments & Computers, 24(4), 560-564. Available on http://www.allpsych.uni-giessen.de/karl/pdf/03.praxis.pdf
|
259
|
+
# * Uebersax, J.S. (2006). The tetrachoric and polychoric correlation coefficients. Statistical Methods for Rater Agreement web site. 2006. Available at: http://john-uebersax.com/stat/tetra.htm . Accessed February, 11, 2010
|
260
|
+
#
|
261
|
+
def compute_two_step_mle_drasgow
|
262
|
+
|
263
|
+
fn1=GSL::Function.alloc {|rho|
|
264
|
+
loglike(@alpha,@beta, rho)
|
181
265
|
}
|
182
266
|
@iteration = 0
|
183
267
|
max_iter = @max_iterations
|
184
268
|
m = 0 # initial guess
|
185
|
-
m_expected = 0
|
186
|
-
a=-0.
|
187
|
-
b=+0.
|
188
|
-
gmf = GSL::Min::FMinimizer.alloc(@
|
269
|
+
m_expected = 0
|
270
|
+
a=-0.9999
|
271
|
+
b=+0.9999
|
272
|
+
gmf = GSL::Min::FMinimizer.alloc(@minimizer_type_two_step)
|
189
273
|
gmf.set(fn1, m, a, b)
|
190
|
-
header=sprintf("using %s method\n", gmf.name)
|
274
|
+
header=sprintf("Two step minimization using %s method\n", gmf.name)
|
191
275
|
header+=sprintf("%5s [%9s, %9s] %9s %10s %9s\n", "iter", "lower", "upper", "min",
|
192
276
|
"err", "err(est)")
|
193
277
|
|
@@ -197,11 +281,11 @@ module Statsample
|
|
197
281
|
begin
|
198
282
|
@iteration += 1
|
199
283
|
status = gmf.iterate
|
200
|
-
status = gmf.test_interval(
|
284
|
+
status = gmf.test_interval(@epsilon, 0.0)
|
201
285
|
|
202
286
|
if status == GSL::SUCCESS
|
203
|
-
@log+="
|
204
|
-
puts "
|
287
|
+
@log+="converged:"
|
288
|
+
puts "converged:" if @debug
|
205
289
|
end
|
206
290
|
a = gmf.x_lower
|
207
291
|
b = gmf.x_upper
|
@@ -212,26 +296,66 @@ module Statsample
|
|
212
296
|
puts message if @debug
|
213
297
|
end while status == GSL::CONTINUE and @iteration < @max_iterations
|
214
298
|
@r=gmf.x_minimum
|
299
|
+
@loglike_model=-gmf.f_minimum
|
215
300
|
end
|
216
|
-
# Chi-square to test r=0
|
217
|
-
def chi_square_independence
|
218
|
-
Statsample::Test::chi_square(@matrix, expected)
|
219
|
-
end
|
220
|
-
# Chi-square to test model==independence
|
221
301
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
302
|
+
# Compute Polychoric correlation with joint estimate.
|
303
|
+
# Rho and thresholds are estimated at same time.
|
304
|
+
# Code based on R package "polycor", by J.Fox.
|
305
|
+
#
|
306
|
+
|
307
|
+
def compute_one_step_mle
|
308
|
+
# Get initial values with two-step aproach
|
309
|
+
compute_two_step_mle_drasgow
|
310
|
+
# Start iteration with past values
|
311
|
+
rho=@r
|
312
|
+
cut_alpha=@alpha
|
313
|
+
cut_beta=@beta
|
314
|
+
parameters=[rho]+cut_alpha+cut_beta
|
315
|
+
minimization = Proc.new { |v, params|
|
316
|
+
rho=v[0]
|
317
|
+
alpha=v[1,@nr-1]
|
318
|
+
beta=v[@nr,@nc-1]
|
319
|
+
loglike(alpha,beta,rho)
|
320
|
+
}
|
321
|
+
np=@nc-1+@nr
|
322
|
+
my_func = GSL::MultiMin::Function.alloc(minimization, np)
|
323
|
+
my_func.set_params(parameters) # parameters
|
324
|
+
|
325
|
+
x = GSL::Vector.alloc(parameters.dup)
|
326
|
+
|
327
|
+
ss = GSL::Vector.alloc(np)
|
328
|
+
ss.set_all(1.0)
|
329
|
+
|
330
|
+
minimizer = GSL::MultiMin::FMinimizer.alloc(minimizer_type_joint,np)
|
331
|
+
minimizer.set(my_func, x, ss)
|
332
|
+
|
333
|
+
iter = 0
|
334
|
+
message=""
|
335
|
+
begin
|
336
|
+
iter += 1
|
337
|
+
status = minimizer.iterate()
|
338
|
+
status = minimizer.test_size(@epsilon)
|
339
|
+
if status == GSL::SUCCESS
|
340
|
+
message="Joint MLE converged to minimum at\n"
|
341
|
+
end
|
342
|
+
x = minimizer.x
|
343
|
+
message+= sprintf("%5d iterations", iter)+"\n";
|
344
|
+
for i in 0...np do
|
345
|
+
message+=sprintf("%10.3e ", x[i])
|
346
|
+
end
|
347
|
+
message+=sprintf("f() = %7.3f size = %.3f\n", minimizer.fval, minimizer.size)+"\n";
|
348
|
+
end while status == GSL::CONTINUE and iter < @max_iterations
|
349
|
+
@iteration=@iter
|
350
|
+
@log+=message
|
351
|
+
puts message if @debug
|
352
|
+
@r=minimizer.x[0]
|
353
|
+
@alpha=minimizer.x[1,@nr-1].to_a
|
354
|
+
@beta=minimizer.x[@nr,@nc-1].to_a
|
355
|
+
@loglike_model= -minimizer.minimum
|
233
356
|
end
|
234
|
-
|
357
|
+
|
358
|
+
def matrix_for_rho(rho) # :nodoc:
|
235
359
|
pd=@nr.times.collect{ [0]*@nc}
|
236
360
|
pc=@nr.times.collect{ [0]*@nc}
|
237
361
|
@nr.times { |i|
|
@@ -246,37 +370,8 @@ module Statsample
|
|
246
370
|
}
|
247
371
|
Matrix.rows(pc)
|
248
372
|
end
|
249
|
-
|
250
|
-
|
251
|
-
e=expected
|
252
|
-
no_r_likehood=0
|
253
|
-
@nr.times {|i|
|
254
|
-
@nc.times {|j|
|
255
|
-
#p @matrix[i,j]
|
256
|
-
if @matrix[i,j]!=0
|
257
|
-
no_r_likehood+= @matrix[i,j]*Math::log(e[i,j])
|
258
|
-
end
|
259
|
-
}
|
260
|
-
}
|
261
|
-
p no_r_likehood
|
262
|
-
model=Matrix.rows(@pd).collect {|c| c*@total}
|
263
|
-
|
264
|
-
model_likehood=0
|
265
|
-
@nr.times {|i|
|
266
|
-
@nc.times {|j|
|
267
|
-
#p @matrix[i,j]
|
268
|
-
if @matrix[i,j]!=0
|
269
|
-
model_likehood+= @matrix[i,j] * Math::log(model[i,j])
|
270
|
-
end
|
271
|
-
}
|
272
|
-
}
|
273
|
-
|
274
|
-
p model_likehood
|
275
|
-
|
276
|
-
-2*(no_r_likehood-model_likehood)
|
277
|
-
|
278
|
-
end
|
279
|
-
def expected
|
373
|
+
|
374
|
+
def expected # :nodoc:
|
280
375
|
rt=[]
|
281
376
|
ct=[]
|
282
377
|
t=0
|
@@ -300,10 +395,14 @@ module Statsample
|
|
300
395
|
|
301
396
|
Matrix.rows(m)
|
302
397
|
end
|
303
|
-
# Compute polychoric using AS87.
|
304
|
-
# Doesn't work for now! I can't find the error :(
|
305
398
|
|
306
|
-
|
399
|
+
# Compute polychoric correlation using polychoric series.
|
400
|
+
# Algorithm: AS87, by Martinson and Hamdam(1975).
|
401
|
+
#
|
402
|
+
# <b>Warning</b>: According to Drasgow(2006), this
|
403
|
+
# computation diverges greatly of joint and two-step methods.
|
404
|
+
#
|
405
|
+
def compute_polychoric_series
|
307
406
|
@nn=@n-1
|
308
407
|
@mm=@m-1
|
309
408
|
@nn7=7*@nn
|
@@ -390,10 +489,10 @@ module Statsample
|
|
390
489
|
(1..@nn).each do |i| #do 22
|
391
490
|
beta[i]=Distribution::Normal.p_value(sumc[i] / sum.to_f)
|
392
491
|
end # 21
|
393
|
-
@alpha=alpha[1,alpha.size]
|
394
|
-
@beta=beta[1,beta.size]
|
395
|
-
@sumr=
|
396
|
-
@sumc=
|
492
|
+
@alpha=alpha[1,alpha.size]
|
493
|
+
@beta=beta[1,beta.size]
|
494
|
+
@sumr=row[1,row.size]
|
495
|
+
@sumc=colmn[1,colmn.size]
|
397
496
|
@total=sum
|
398
497
|
|
399
498
|
# Compute Fourier coefficients a and b. Verified
|
@@ -522,9 +621,12 @@ module Statsample
|
|
522
621
|
end # 43
|
523
622
|
raise "Error" if norts==0
|
524
623
|
@r=pcorl
|
624
|
+
|
625
|
+
@loglike_model=-loglike(@alpha, @beta, @r)
|
626
|
+
|
525
627
|
end
|
526
628
|
#Computes vector h(mm7) of orthogonal hermite...
|
527
|
-
def hermit(s,k)
|
629
|
+
def hermit(s,k) # :nodoc:
|
528
630
|
h=[]
|
529
631
|
(1..k).each do |i| # do 14
|
530
632
|
l=i
|
@@ -544,7 +646,7 @@ module Statsample
|
|
544
646
|
end
|
545
647
|
h
|
546
648
|
end
|
547
|
-
def xnorm(t)
|
649
|
+
def xnorm(t) # :nodoc:
|
548
650
|
Math::exp(-0.5 * t **2) * (1.0/Math::sqrt(2*Math::PI))
|
549
651
|
end
|
550
652
|
|
@@ -554,7 +656,7 @@ module Statsample
|
|
554
656
|
rp.to_text
|
555
657
|
end
|
556
658
|
|
557
|
-
def to_reportbuilder(generator)
|
659
|
+
def to_reportbuilder(generator) # :nodoc:
|
558
660
|
compute if @r.nil?
|
559
661
|
section=ReportBuilder::Section.new(:name=>@name)
|
560
662
|
t=ReportBuilder::Table.new(:name=>_("Contingence Table"),:header=>[""]+(@n.times.collect {|i| "Y=#{i}"})+["Total"])
|
@@ -574,6 +676,7 @@ module Statsample
|
|
574
676
|
t.add_row(["Threshold Y #{i}", sprintf("%0.4f", val)])
|
575
677
|
}
|
576
678
|
section.add(t)
|
679
|
+
section.add(_("Test of bivariate normality: X2 = %0.3f, df = %d, p= %0.5f" % [ chi_square, chi_square_df, 1-Distribution::ChiSquare.cdf(chi_square, chi_square_df)]))
|
577
680
|
generator.parse_element(section)
|
578
681
|
end
|
579
682
|
end
|