Class: Statsample::SEM::Model

Inherits:
Object
  • Object
show all
Includes:
Summarizable
Defined in:
lib/statsample/sem/model.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = Hash.new, &block) ⇒ Model

Returns a new instance of Model.

Raises:

  • (ArgumentError)


19
20
21
22
23
24
25
26
27
28
29
# File 'lib/statsample/sem/model.rb', line 19

def initialize(opts=Hash.new, &block)
  raise ArgumentError,"opts should be a Hash" if !opts.is_a? Hash
  default_opts={:name=>_("SEM Model")}
  @opts=default_opts.merge opts
  @paths=Hash.new
  @manifests=nil
  @latents=nil
  if block
    block.arity<1 ? self.instance_eval(&block) : block.call(self)
  end
end

Instance Attribute Details

#casesObject

Number of cases



12
13
14
# File 'lib/statsample/sem/model.rb', line 12

def cases
  @cases
end

#data_typeObject (readonly)

Type of data used. Could be :covariance, :correlation or :raw



6
7
8
# File 'lib/statsample/sem/model.rb', line 6

def data_type
  @data_type
end

#dsObject (readonly)

Raw data on a dataset



10
11
12
# File 'lib/statsample/sem/model.rb', line 10

def ds
  @ds
end

#matrixObject (readonly)

Covariance/correlation matrix



8
9
10
# File 'lib/statsample/sem/model.rb', line 8

def matrix
  @matrix
end

#meansObject

Optional array of mean for use when data is matrix based



14
15
16
# File 'lib/statsample/sem/model.rb', line 14

def means
  @means
end

#pathsObject (readonly)

Returns the value of attribute paths.



18
19
20
# File 'lib/statsample/sem/model.rb', line 18

def paths
  @paths
end

#variablesObject

Name of variables



16
17
18
# File 'lib/statsample/sem/model.rb', line 16

def variables
  @variables
end

Instance Method Details

#add_path(f1, f2, arrows, free, values, labels, i) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/statsample/sem/model.rb', line 68

def add_path(f1,f2,arrows,free,values,labels,i)
  arrow_s = (arrows==1) ? "to":"cov"
  raise "Path repeated : #{f1},#{f2}" if @paths.has_key? [[f1,f2].sort]
  label= (labels.nil? or !labels.respond_to?:[] or labels[i].nil?) ? "#{f1} #{arrow_s} #{f2}" : labels[i]
  
  free_v = (free.is_a? Array) ? free[i] : free 
  if values.is_a? Array
    value= values[i].nil? ? nil : values[i]
  elsif values.is_a? Numeric
    value=values
  end
    
  value = nil if free_v
  
  @paths[[f1,f2].sort]={ :from=>f1, :to=>f2, :arrow=>arrows, :label=>label, :free=>free_v, :value=>value}
end

#add_raw_path(f1, f2, arrows, label, free, value) ⇒ Object



65
66
67
# File 'lib/statsample/sem/model.rb', line 65

def add_raw_path(f1,f2,arrows,label,free,value)
  @paths[[f1,f2].sort]={ :from=>f1, :to=>f2, :arrow=>arrows, :label=>label, :free=>free, :value=>value}
end

#complete?Boolean

True if model have enough information to process it

Returns:

  • (Boolean)


62
63
64
# File 'lib/statsample/sem/model.rb', line 62

def complete?
  !@data_type.nil? and !@manifests.nil? and !@latents.nil? and @paths.size>0
end

#data_from_dataset(ds) ⇒ Object



218
219
220
221
222
# File 'lib/statsample/sem/model.rb', line 218

def data_from_dataset(ds)
  @data_type=:raw
  @ds=ds
  @variables=@ds.fields
end

#data_from_matrix(matrix, opts = Hash.new) ⇒ Object



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/statsample/sem/model.rb', line 224

def data_from_matrix(matrix,opts=Hash.new)
  type = opts[:type]
  type||=(matrix.respond_to? :type) ? matrix.type : :covariance
  variable_names = opts[:variable_names]
  cases = opts[:cases]
  means = opts[:means]
  raise "You should set number of cases" if cases.nil?
  
  @data_type= (type==:covariance) ? :covariance : :correlation
  @matrix=matrix
  @cases=cases
  @means=means
  if variable_names.nil? 
    @variables=@matrix.fields if @matrix.respond_to? :fields
  else
    @variables=variable_names
  end
end

#dupObject



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/statsample/sem/model.rb', line 30

def dup
  mod=Model.new(@opts)
  if @data_type==:raw
    mod.data_from_dataset(@ds)
  else
    mod.data_from_matrix(@matrix,:type=>@data_type,:cases=>@cases, :means=>@means) 
  end
  mod.latents=latents
  mod.manifests=manifests
  if @paths
    @paths.each_pair do |k,v|
      mod.add_raw_path(k[0],k[1],v[:arrow],v[:label],v[:free], v[:value])
    end
  end
  mod
end

#get_label(key) ⇒ Object



184
185
186
# File 'lib/statsample/sem/model.rb', line 184

def get_label(key)
  @paths[key][:label]
end

#infer_latentsObject

Latents will be any variable set on a path not present on @variables



177
178
179
# File 'lib/statsample/sem/model.rb', line 177

def infer_latents
  variables_on_paths-@variables
end

#infer_manifestsObject

Latens will be any variable set on path present on @variables



181
182
183
# File 'lib/statsample/sem/model.rb', line 181

def infer_manifests
  variables_on_paths & @variables
end

#kObject

Number of variables on model



172
173
174
# File 'lib/statsample/sem/model.rb', line 172

def k
  variables_on_paths.size
end

#latents(*argv) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/statsample/sem/model.rb', line 187

def latents(*argv)
  if argv.size==0
    if @latents.nil? and @paths.size>0 and !@data_type.nil? 
      @latents=infer_latents
    end
    @latents
  elsif argv[0].is_a? Array 
    @latents=argv[0]
  else
    @latents=[argv]
  end
end

#latents=(argv) ⇒ Object



199
200
201
# File 'lib/statsample/sem/model.rb', line 199

def latents=(argv)
  @latents=argv
end

#make_nullObject



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/statsample/sem/model.rb', line 46

def make_null
  # Get current variables
  vars=variables_on_paths
  @paths.clear
  vars.each do |v|
    if @variables.include? v
      free=true
      value=nil
    else
      free=false
      value=1.0
    end
    add_raw_path(v,v,2,"var #{v}",free,value)
  end
end

#manifests(*argv) ⇒ Object



203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/statsample/sem/model.rb', line 203

def manifests(*argv)
  if argv.size==0
    if @manifests.nil? and @paths.size>0 and !@data_type.nil? 
      @manifests=infer_manifests
    end
    @manifests
  elsif argv[0].is_a? Array 
    @manifests=argv[0]
  else
    @manifests=[argv]
  end
end

#manifests=(argv) ⇒ Object



215
216
217
# File 'lib/statsample/sem/model.rb', line 215

def manifests=(argv)
  @manifests=argv
end

#path(opts) ⇒ Object

Set one or more paths. Based on OpenMx mxPath method.

Options:

  • :from : String or Array. sources of new paths

  • :to : String or Array. sinks of new paths

  • :all : bool. If you, connect all sources to all sinks. If false,

connect one-on-one sources to sinks if both are arrays, one source to many sinks if :from is a String and :to is an Array

  • :arrows : 1 for regression, 2 for variance-covariance. See rules

for specific automatic setting

  • :free : Indicates whether paths are free or fixed. By default, true

  • :values : The starting values of the parameters

  • :labels : The names of paths

Rules

  • from : variance-> from and to equal, label equal to “s^2 NAME_OF_FIELD”, arrows=2, free=>true

  • from and to: regression -> label equal to “FROM->TO”, arrows=1, free=>true

  • from, to, arrows -> label equal to “FROM->TO” if arrows=1,

“FROM<->TO” if arrows=2, free=>true

  • free=false -> requires values for each from - to value



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/statsample/sem/model.rb', line 104

def path(opts)
  raise "Requires at least :from option" unless opts.has_key? :from
  
  free=true
  all=false
  
  from=opts[:from]
  to=opts[:to]
  
  all=opts[:all] if opts.has_key? :all
  free=opts[:free] if opts.has_key? :free

  labels=opts[:labels]
  arrows=opts[:arrows]
  
  values=opts[:values]
  from=[from] if from.is_a? String
  to||=from
  to=[to] if to.is_a? String
  
  if from==to # variances
    arrows||=2
    labels_2=Array.new(from.size)
    
    from.each_with_index do |f,i|
      labels_2[i]=(labels.nil? or !labels.respond_to?:[] or labels[i].nil?) ? "var #{f}" : labels[i]
    end
    
    from.each_with_index do |f,i|
      add_path(f,f,arrows,free,values, labels_2,i)
    end
  else # regression and covariances
    arrows||=1
    i=0
    all=true if from.size==1 or to.size==1
    if all
      from.each do |f1|
        to.each do |f2|
          add_path(f1,f2,arrows,free,values,labels,i)
          i+=1 
        end
      end
    else
      raise ":from and :to should be the same size" if from.size!=to.size
      from.size.times.each do |i|
        add_path(from[i],to[i],arrows,free,values,labels,i)
      end
      
    end
    
  end
  
  
end

#variables_on_pathsObject

Total number of variables



163
164
165
166
167
168
169
170
# File 'lib/statsample/sem/model.rb', line 163

def variables_on_paths
  out=Array.new
  @paths.keys.each {|k|
    out << k[0] unless out.include? k[0]
    out << k[1] unless out.include? k[1]
  }
  out
end