statsample 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +20 -1
  3. data/Manifest.txt +8 -1
  4. data/README.txt +11 -7
  5. data/Rakefile +2 -2
  6. data/data/locale/es/LC_MESSAGES/statsample.mo +0 -0
  7. data/examples/dataset.rb +8 -0
  8. data/examples/multiple_regression.rb +1 -1
  9. data/examples/parallel_analysis.rb +29 -0
  10. data/examples/parallel_analysis_tetrachoric.rb +30 -0
  11. data/examples/vector.rb +6 -0
  12. data/lib/distribution.rb +16 -6
  13. data/lib/distribution/normal.rb +27 -20
  14. data/lib/distribution/normalbivariate.rb +1 -1
  15. data/lib/statsample.rb +19 -2
  16. data/lib/statsample/anova.rb +118 -16
  17. data/lib/statsample/bivariate.rb +27 -13
  18. data/lib/statsample/bivariate/polychoric.rb +18 -5
  19. data/lib/statsample/crosstab.rb +66 -74
  20. data/lib/statsample/dataset.rb +52 -45
  21. data/lib/statsample/dominanceanalysis.rb +2 -5
  22. data/lib/statsample/factor.rb +1 -1
  23. data/lib/statsample/factor/parallelanalysis.rb +122 -0
  24. data/lib/statsample/factor/pca.rb +23 -28
  25. data/lib/statsample/factor/principalaxis.rb +8 -3
  26. data/lib/statsample/matrix.rb +27 -24
  27. data/lib/statsample/mle.rb +11 -11
  28. data/lib/statsample/permutation.rb +2 -1
  29. data/lib/statsample/regression.rb +10 -8
  30. data/lib/statsample/regression/multiple/baseengine.rb +36 -25
  31. data/lib/statsample/regression/multiple/gslengine.rb +14 -0
  32. data/lib/statsample/regression/multiple/matrixengine.rb +4 -32
  33. data/lib/statsample/regression/multiple/rubyengine.rb +2 -6
  34. data/lib/statsample/regression/simple.rb +1 -1
  35. data/lib/statsample/reliability.rb +42 -54
  36. data/lib/statsample/test.rb +10 -6
  37. data/lib/statsample/test/f.rb +16 -26
  38. data/lib/statsample/test/levene.rb +4 -8
  39. data/lib/statsample/test/t.rb +30 -24
  40. data/lib/statsample/test/umannwhitney.rb +13 -6
  41. data/lib/statsample/vector.rb +86 -76
  42. data/po/es/statsample.mo +0 -0
  43. data/po/es/statsample.po +127 -94
  44. data/po/statsample.pot +114 -79
  45. data/test/test_anovaoneway.rb +27 -0
  46. data/test/test_anovawithvectors.rb +97 -0
  47. data/test/test_bivariate.rb +6 -57
  48. data/test/test_bivariate_polychoric.rb +65 -0
  49. data/test/test_crosstab.rb +6 -0
  50. data/test/test_dataset.rb +29 -1
  51. data/test/test_distribution.rb +6 -13
  52. data/test/test_dominance_analysis.rb +1 -1
  53. data/test/test_factor.rb +3 -3
  54. data/test/test_helpers.rb +18 -18
  55. data/test/test_matrix.rb +33 -20
  56. data/test/test_permutation.rb +36 -30
  57. data/test/test_regression.rb +26 -8
  58. data/test/test_reliability.rb +104 -14
  59. data/test/test_test_f.rb +11 -14
  60. data/test/test_test_t.rb +42 -35
  61. data/test/test_umannwhitney.rb +22 -10
  62. data/test/test_vector.rb +204 -102
  63. metadata +57 -81
  64. metadata.gz.sig +0 -0
  65. data/test/test_anova.rb +0 -24
@@ -3,17 +3,22 @@ module Statsample
3
3
  module Multiple
4
4
  # Base class for Multiple Regression Engines
5
5
  class BaseEngine
6
-
7
- include GetText
8
- bindtextdomain("statsample")
6
+ include Statsample::Summarizable
9
7
  # Name of analysis
10
8
  attr_accessor :name
11
-
9
+ # Minimum number of valid case for pairs of correlation
10
+ attr_reader :cases
11
+ # Number of valid cases (listwise)
12
+ attr_reader :valid_cases
13
+ # Number of total cases (dataset.cases)
14
+ attr_reader :total_cases
12
15
  def self.univariate?
13
16
  true
14
17
  end
15
18
  def initialize(ds, y_var, opts = Hash.new)
16
19
  @ds=ds
20
+ @predictors_n=@ds.fields.size-1
21
+ @total_cases=@ds.cases
17
22
  @cases=@ds.cases
18
23
  @y_var=y_var
19
24
  @r2=nil
@@ -23,12 +28,16 @@ module Statsample
23
28
  }
24
29
  end
25
30
  # Calculate F Test
26
- def f_test
27
- @f_test||=Statsample::Test::F.new(ssr, sse, df_r, df_e, :name_numerator=>_("Regression"), :name_denominator=>_("Error"), :name=>"ANOVA")
31
+ def anova
32
+ @anova||=Statsample::Anova::OneWay.new(:ss_num=>ssr, :ss_den=>sse, :df_num=>df_r, :df_den=>df_e, :name_numerator=>_("Regression"), :name_denominator=>_("Error"), :name=>"ANOVA")
33
+ end
34
+ # Standard error of estimate
35
+ def se_estimate
36
+ Math::sqrt(sse.quo(df_e))
28
37
  end
29
38
  # Retrieves a vector with predicted values for y
30
39
  def predicted
31
- (0...@ds.cases).collect { |i|
40
+ @total_cases.times.collect { |i|
32
41
  invalid=false
33
42
  vect=@dep_columns.collect {|v| invalid=true if v[i].nil?; v[i]}
34
43
  if invalid
@@ -44,7 +53,7 @@ module Statsample
44
53
  end
45
54
  # Retrieves a vector with residuals values for y
46
55
  def residuals
47
- (0...@ds.cases).collect{|i|
56
+ (0...@total_cases).collect{|i|
48
57
  invalid=false
49
58
  vect=@dep_columns.collect{|v| invalid=true if v[i].nil?; v[i]}
50
59
  if invalid or @ds[@y_var][i].nil?
@@ -62,6 +71,9 @@ module Statsample
62
71
  def sst
63
72
  raise "You should implement this"
64
73
  end
74
+ def r2_adjusted
75
+ r2-((1-r2)*@predictors_n).quo(df_e)
76
+ end
65
77
  # Sum of squares (regression)
66
78
  def ssr
67
79
  r2*sst
@@ -89,19 +101,19 @@ module Statsample
89
101
  end
90
102
  # Degrees of freedom for regression
91
103
  def df_r
92
- @dep_columns.size
104
+ @predictors_n
93
105
  end
94
106
  # Degrees of freedom for error
95
107
  def df_e
96
- @ds_valid.cases-@dep_columns.size-1
108
+ @valid_cases-@predictors_n-1
97
109
  end
98
110
  # Fisher for Anova
99
111
  def f
100
- f_test.f
112
+ anova.f
101
113
  end
102
114
  # p-value of Fisher
103
115
  def probability
104
- f_test.probability
116
+ anova.probability
105
117
  end
106
118
  # Tolerance for a given variable
107
119
  # http://talkstats.com/showthread.php?t=5056
@@ -130,6 +142,7 @@ module Statsample
130
142
  out
131
143
  end
132
144
  # Estandar error of R^2
145
+ # ????
133
146
  def se_r2
134
147
  Math::sqrt((4*r2*(1-r2)**2*(df_e)**2).quo((@cases**2-1)*(@cases+3)))
135
148
  end
@@ -139,10 +152,11 @@ module Statsample
139
152
  def estimated_variance_covariance_matrix
140
153
  mse_p=mse
141
154
  columns=[]
142
- @ds_valid.each_vector{|k,v|
155
+ @ds_valid.fields.each{|k|
156
+ v=@ds_valid[k]
143
157
  columns.push(v.data) unless k==@y_var
144
158
  }
145
- columns.unshift([1.0]*@ds_valid.cases)
159
+ columns.unshift([1.0]*@valid_cases)
146
160
  x=Matrix.columns(columns)
147
161
  matrix=((x.t*x)).inverse * mse
148
162
  matrix.collect {|i| Math::sqrt(i) if i>0 }
@@ -155,25 +169,22 @@ module Statsample
155
169
  def constant_se
156
170
  estimated_variance_covariance_matrix[0,0]
157
171
  end
158
- def summary
159
- rp=ReportBuilder.new()
160
- rp.add(self)
161
- rp.to_text
162
- end
163
172
  def report_building(b)
164
173
  b.section(:name=>@name) do |g|
165
174
  c=coeffs
166
- g.text(_("Engine: %s") % self.class)
167
- g.text(_("Cases(listwise)=%d(%d)") % [@ds.cases, @ds_valid.cases])
168
- g.text("R=#{sprintf('%0.3f',r)}")
169
- g.text("R^2=#{sprintf('%0.3f',r2)}")
175
+ g.text _("Engine: %s") % self.class
176
+ g.text(_("Cases(listwise)=%d(%d)") % [@total_cases, @valid_cases])
177
+ g.text _("R=%0.3f") % r
178
+ g.text _("R^2=%0.3f") % r2
179
+ g.text _"R^2 Adj=%0.3f" % r2_adjusted
180
+ g.text _("Std.Error R=%0.3f") % se_estimate
170
181
 
171
182
  g.text(_("Equation")+"="+ sprintf('%0.3f',constant) +" + "+ @fields.collect {|k| sprintf('%0.3f%s',c[k],k)}.join(' + ') )
172
183
 
173
- g.parse_element(f_test)
184
+ g.parse_element(anova)
174
185
  sc=standarized_coeffs
175
186
  cse=coeffs_se
176
- g.table(:name=>"Beta coefficients", :header=>%w{coeff b beta se t}.collect{|field| _(field)} ) do |t|
187
+ g.table(:name=>_("Beta coefficients"), :header=>%w{coeff b beta se t}.collect{|field| _(field)} ) do |t|
177
188
  t.row([_("Constant"), sprintf("%0.3f", constant), "-", sprintf("%0.3f", constant_se), sprintf("%0.3f", constant_t)])
178
189
  @fields.each do |f|
179
190
  t.row([f, sprintf("%0.3f", c[f]), sprintf("%0.3f", sc[f]), sprintf("%0.3f", cse[f]), sprintf("%0.3f", c[f].quo(cse[f]))])
@@ -21,6 +21,7 @@ class GslEngine < BaseEngine
21
21
  super
22
22
  @ds=ds.dup_only_valid
23
23
  @ds_valid=@ds
24
+ @valid_cases=@ds_valid.cases
24
25
  @dy=@ds[@y_var]
25
26
  @ds_indep=ds.dup(ds.fields-[y_var])
26
27
  # Create a custom matrix
@@ -111,6 +112,19 @@ class GslEngine < BaseEngine
111
112
  v.quo(red_sd)
112
113
  }.to_vector(:scale)
113
114
  end
115
+
116
+ # Standard error for coeffs
117
+ def coeffs_se
118
+ out={}
119
+ evcm=estimated_variance_covariance_matrix
120
+ @ds_valid.fields.each_with_index do |f,i|
121
+ mi=i+1
122
+ next if f==@y_var
123
+ out[f]=evcm[mi,mi]
124
+ end
125
+ out
126
+ end
127
+
114
128
  end
115
129
  end
116
130
  end
@@ -50,7 +50,7 @@ class MatrixEngine < BaseEngine
50
50
  @fields=matrix.fields-[y_var]
51
51
 
52
52
  @n_predictors=@fields.size
53
-
53
+ @predictors_n=@n_predictors
54
54
  @matrix_x= @matrix_cor.submatrix(@fields)
55
55
  @matrix_x_cov= @matrix_cov.submatrix(@fields)
56
56
 
@@ -88,11 +88,11 @@ class MatrixEngine < BaseEngine
88
88
  }
89
89
  else
90
90
  @coeffs_stan=result_matrix.column(0).to_a
91
-
92
91
  @coeffs=standarized_coeffs.collect {|k,v|
93
92
  standarized_coeffs[k]*@y_sd.quo(@x_sd[k])
94
93
  }
95
94
  end
95
+ @total_cases=@valid_cases=@cases
96
96
  end
97
97
  def cases
98
98
  raise "You should define the number of valid cases first" if @cases.nil?
@@ -144,6 +144,7 @@ class MatrixEngine < BaseEngine
144
144
  # Reference:
145
145
  # * http://talkstats.com/showthread.php?t=5056
146
146
  def tolerance(var)
147
+ return 1 if @matrix_x.column_size==1
147
148
  lr=Statsample::Regression::Multiple::MatrixEngine.new(@matrix_x, var)
148
149
  1-lr.r2
149
150
  end
@@ -165,7 +166,7 @@ class MatrixEngine < BaseEngine
165
166
  # t value for constant
166
167
  def constant_t
167
168
  return nil if constant_se.nil?
168
- constant.to_f/constant_se
169
+ constant.to_f / constant_se
169
170
  end
170
171
  # Standard error for constant.
171
172
  # This method recreates the estimaded variance-covariance matrix
@@ -197,35 +198,6 @@ class MatrixEngine < BaseEngine
197
198
  matrix.collect {|i| Math::sqrt(i) if i>0 }[0,0]
198
199
  end
199
200
 
200
- def report_building(builder) # :nodoc:
201
- builder.section(:name=>_("Multiple Regression: ")+@name) do |g|
202
- c=coeffs
203
- g.text(_("Engine: %s") % self.class)
204
- g.text(_("Cases=%d") % [@cases])
205
- g.text("R=#{sprintf('%0.3f',r)}")
206
- g.text("R^2=#{sprintf('%0.3f',r2)}")
207
-
208
- g.text(_("Equation")+"="+ sprintf('%0.3f',constant) +" + "+ @fields.collect {|k| sprintf('%0.3f%s',c[k],k)}.join(' + ') )
209
-
210
- g.parse_element(f_test)
211
-
212
-
213
-
214
- sc=standarized_coeffs
215
- cse=coeffs_se
216
- g.table(:name=>"Beta coefficients", :header=>%w{coeff b beta se t}.collect{|field| _(field)} ) do |t|
217
- if (constant_se.nil?)
218
- t.row([_("Constant"), sprintf("%0.3f", constant),"--","?","?"])
219
- else
220
- t.row([_("Constant"), sprintf("%0.3f", constant), "-", sprintf("%0.3f", constant_se), sprintf("%0.3f", constant_t)])
221
- end
222
-
223
- @fields.each do |f|
224
- t.row([f, sprintf("%0.3f", c[f]), sprintf("%0.3f", sc[f]), sprintf("%0.3f", cse[f]), sprintf("%0.3f", c[f].quo(cse[f]))])
225
- end
226
- end
227
- end
228
- end
229
201
  end
230
202
  end
231
203
  end
@@ -31,11 +31,9 @@ class RubyEngine < MatrixEngine
31
31
  @ds=ds
32
32
  @dy=ds[@y_var]
33
33
  @ds_valid=ds.dup_only_valid
34
+ @total_cases=@ds.cases
35
+ @valid_cases=@ds_valid.cases
34
36
  @ds_indep = ds.dup(ds.fields-[y_var])
35
-
36
- # p obtain_predictor_matrix
37
- # p @matrix_x.correlation
38
-
39
37
  set_dep_columns
40
38
  end
41
39
 
@@ -82,8 +80,6 @@ class RubyEngine < MatrixEngine
82
80
  @ds_indep.update_valid_data
83
81
  set_dep_columns
84
82
  end
85
-
86
-
87
83
  # Standard error for constant
88
84
  def constant_se
89
85
  estimated_variance_covariance_matrix[0,0]
@@ -70,7 +70,7 @@ module Statsample
70
70
  end
71
71
  end
72
72
  def init_vectors(vx,vy)
73
- @vx,@vy=Statsample.only_valid(vx,vy)
73
+ @vx,@vy=Statsample.only_valid_clone(vx,vy)
74
74
  x_m=@vx.mean
75
75
  y_m=@vy.mean
76
76
  num=den=0
@@ -7,9 +7,9 @@ module Statsample
7
7
  ds=ods.dup_only_valid
8
8
  n_items=ds.fields.size
9
9
  sum_var_items=ds.vectors.inject(0) {|ac,v|
10
- ac+v[1].variance_sample }
10
+ ac+v[1].variance }
11
11
  total=ds.vector_sum
12
- (n_items / (n_items-1).to_f) * (1-(sum_var_items/ total.variance_sample))
12
+ (n_items.quo(n_items-1)) * (1-(sum_var_items.quo(total.variance)))
13
13
  end
14
14
  # Calculate Chonbach's alpha for a given dataset
15
15
  # using standarized values for every vector.
@@ -17,16 +17,16 @@ module Statsample
17
17
 
18
18
  def cronbach_alpha_standarized(ods)
19
19
  ds=ods.dup_only_valid.fields.inject({}){|a,f|
20
- a[f]=ods[f].vector_standarized; a
20
+ a[f]=ods[f].standarized; a
21
21
  }.to_dataset
22
22
  cronbach_alpha(ds)
23
23
  end
24
24
  end
25
25
  class ItemCharacteristicCurve
26
- attr_reader :totals, :counts,:vector_total
26
+ attr_reader :totals, :counts, :vector_total
27
27
  def initialize (ds, vector_total=nil)
28
28
  vector_total||=ds.vector_sum
29
- raise "Total size != Dataset size" if vector_total.size!=ds.cases
29
+ raise ArgumentError, "Total size != Dataset size" if vector_total.size!=ds.cases
30
30
  @vector_total=vector_total
31
31
  @ds=ds
32
32
  @totals={}
@@ -48,19 +48,21 @@ module Statsample
48
48
  i+=1
49
49
  end
50
50
  end
51
+ # Return a hash with p for each different value on a vector
51
52
  def curve_field(field, item)
52
53
  out={}
53
54
  item=item.to_s
54
- @totals.each{|value,n|
55
+ @totals.each do |value,n|
55
56
  count_value= @counts[field][value][item].nil? ? 0 : @counts[field][value][item]
56
- out[value]=count_value.to_f/n.to_f
57
- }
57
+ out[value]=count_value.quo(n)
58
+ end
58
59
  out
59
60
  end
60
61
  end
61
62
  class ItemAnalysis
62
63
  attr_reader :mean, :sd,:valid_n, :alpha , :alpha_standarized
63
- def initialize(ds)
64
+ attr_accessor :name
65
+ def initialize(ds,opts=Hash.new)
64
66
  @ds=ds.dup_only_valid
65
67
  @total=@ds.vector_sum
66
68
  @item_mean=@ds.vector_mean.mean
@@ -70,11 +72,15 @@ module Statsample
70
72
  @kurtosis=@total.kurtosis
71
73
  @sd = @total.sd
72
74
  @valid_n = @total.size
75
+ opts_default={:name=>"Reliability Analisis"}
76
+ @opts=opts_default.merge(opts)
77
+ @name=@opts[:name]
78
+
73
79
  begin
74
80
  @alpha = Statsample::Reliability.cronbach_alpha(ds)
75
81
  @alpha_standarized = Statsample::Reliability.cronbach_alpha_standarized(ds)
76
82
  rescue => e
77
- raise DatasetException.new(@ds,e), "Problem on calculate alpha"
83
+ raise DatasetException.new(@ds,e), "Error calculating alpha"
78
84
  end
79
85
  end
80
86
  # Returns a hash with structure
@@ -201,51 +207,33 @@ module Statsample
201
207
  a
202
208
  end
203
209
  end
204
- def html_summary
205
- html = <<EOF
206
- <p><strong>Summary for scale:</strong></p>
207
- <ul>
208
- <li>Items=#{@ds.fields.size}</li>
209
- <li>Total Mean=#{@mean}</li>
210
- <li>Item Mean=#{@item_mean}</li>
211
- <li>Std.Dv.=#{@sd}</li>
212
- <li>Median=#{@median}</li>
213
- <li>Skewness=#{sprintf("%0.3f",@skew)}</li>
214
- <li>Kurtosis=#{sprintf("%0.3f",@kurtosis)}</li>
215
-
216
- <li>Valid n:#{@valid_n}</li>
217
- <li>Cronbach alpha: #{@alpha}</li>
218
- </ul>
219
- <table><thead><th>Variable</th>
220
-
221
- <th>Mean</th>
222
- <th>StDv.</th>
223
- <th>Mean if deleted</th><th>Var. if
224
- deleted</th><th> StDv. if
225
- deleted</th><th> Itm-Totl
226
- Correl.</th><th>Alpha if
227
- deleted</th></thead>
228
- EOF
210
+ def summary
211
+ ReportBuilder.new(:no_title=>true).add(self).to_text
212
+ end
213
+ def report_building(builder)
214
+ builder.section(:name=>@name) do |s|
215
+ s.table(:name=>"Summary") do |t|
216
+ t.row ["Items", @ds.fields.size]
217
+ t.row ["Total Mean", @mean]
218
+ t.row ["Item Mean", @item_mean]
219
+ t.row ["S.D.", @sd]
220
+ t.row ["Median", @median]
221
+ t.row ["Skewness", "%0.4f" % @skew]
222
+ t.row ["Kurtosis", "%0.4f" % @kurtosis]
223
+ t.row ["Valid n", @valid_n]
224
+ t.row ["Cronbach's alpha", "%0.4f" % @alpha]
225
+ t.row ["Standarized Cronbach's alpha", "%0.4f" % @alpha_standarized]
226
+ end
227
+ itc=item_total_correlation
228
+ sid=stats_if_deleted
229
+ is=item_statistics
229
230
 
230
- itc=item_total_correlation
231
- sid=stats_if_deleted
232
- is=item_statistics
233
- @ds.fields.each {|f|
234
- html << <<EOF
235
- <tr>
236
- <td>#{f}</td>
237
- <td>#{sprintf("%0.5f",is[f][:mean])}</td>
238
- <td>#{sprintf("%0.5f",is[f][:sds])}</td>
239
- <td>#{sprintf("%0.5f",sid[f][:mean])}</td>
240
- <td>#{sprintf("%0.5f",sid[f][:variance_sample])}</td>
241
- <td>#{sprintf("%0.5f",sid[f][:sds])}</td>
242
- <td>#{sprintf("%0.5f",itc[f])}</td>
243
- <td>#{sprintf("%0.5f",sid[f][:alpha])}</td>
244
- </tr>
245
- EOF
246
- }
247
- html << "</table><hr />"
248
- html
231
+ s.table(:name=>"Items report", :header=>["item","mean","sd", "mean if deleted", "var if deleted", "sd if deleted"," item-total correl.", "alpha if deleted"]) do |t|
232
+ @ds.fields.each do |f|
233
+ t.row(["#{@ds[f].name}(#{f})", sprintf("%0.5f",is[f][:mean]), sprintf("%0.5f",is[f][:sds]), sprintf("%0.5f",sid[f][:mean]), sprintf("%0.5f",sid[f][:variance_sample]), sprintf("%0.5f",sid[f][:sds]), sprintf("%0.5f",itc[f]), sprintf("%0.5f",sid[f][:alpha])])
234
+ end
235
+ end
236
+ end
249
237
  end
250
238
  end
251
239
  end
@@ -8,11 +8,12 @@ module Statsample
8
8
  autoload(:F, 'statsample/test/f')
9
9
  # Returns probability of getting a value lower or higher
10
10
  # than sample, using cdf and number of tails.
11
- # * For one tail left, return the cdf
12
- # * For one tail right, return 1-cdf
13
- # * For two tails, returns 2*right_tail(cdf.abs)
11
+ #
12
+ # * <tt>:left</tt> : For one tail left, return the cdf
13
+ # * <tt>:right</tt> : For one tail right, return 1-cdf
14
+ # * <tt>:both</tt> : For both tails, returns 2*right_tail(cdf.abs)
14
15
  def p_using_cdf(cdf, tails=:both)
15
- tails=:both if tails==2
16
+ tails=:both if tails==2 or tails==:two
16
17
  tails=:right if tails==1 or tails==:positive
17
18
  tails=:left if tails==:negative
18
19
  case tails
@@ -40,8 +41,11 @@ module Statsample
40
41
  }
41
42
  sum
42
43
  end
43
- def u_mannwhitney(v1p,v2p)
44
- Statsample::Test::UMannWhitney.new(v1p,v2p)
44
+ # Shorthand for Statsample::Test::UMannWhitney.new
45
+ #
46
+ # * <tt>v1</tt> and <tt>v2</tt> should be Statsample::Vector.
47
+ def u_mannwhitney(v1, v2)
48
+ Statsample::Test::UMannWhitney.new(v1,v2)
45
49
  end
46
50
  # Shorthand for Statsample::Test::T::OneSample.new
47
51
  def t_one_sample(vector, opts=Hash.new)