Class: Statsample::SEM::SemJFoxEngine

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

Overview

SEM using J.Fox ‘sem’ R library. Documentation for methods extracted from [davidakenny.net/cm/fit.htm]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, opts = Hash.new) ⇒ SemJFoxEngine

Returns a new instance of SemJFoxEngine.



14
15
16
17
18
19
20
21
# File 'lib/statsample/sem/semjfoxengine.rb', line 14

def initialize(model,opts=Hash.new)
  @model=model
  defaults = {
    :name=>_("SEM analysis using J.Fox sem package")
  }
  @opts=defaults.merge defaults
  @name=@opts[:name]
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



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

def name
  @name
end

#r_summaryObject (readonly)

Returns the value of attribute r_summary.



13
14
15
# File 'lib/statsample/sem/semjfoxengine.rb', line 13

def r_summary
  @r_summary
end

#summarizableObject

Returns the value of attribute summarizable.



11
12
13
# File 'lib/statsample/sem/semjfoxengine.rb', line 11

def summarizable
  @summarizable
end

Instance Method Details

#adjusted_goodness_of_fitObject

Lisrel measure. Don’t trust!



104
105
106
# File 'lib/statsample/sem/semjfoxengine.rb', line 104

def adjusted_goodness_of_fit
  @r_summary["AGFI"]
end

#bicObject

Bayesian Information Criterion (BIC) and Adjusted BIC

the AIC pays a penalty of 2 for each parameter estimated. The BIC and adjusted BIC increases the penalty as sample size increases χ2 + [k(k - 1)/2 - df]ln(N)

where ln(N) is the natural logarithm of the number of cases in the sample. The adjusted BIC replaces ln(N) with ln[(N + 2)/24]. The BIC places a high value on parsimony (perhaps too high). The adjusted BIC, while placing a penalty for adding parameters based on sample, does not place as high a penalty as the BIC. Like the AIC, these measures are not absolute measues and are used to compare the fit of two or more models estimated from the same data set.



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

def bic
  @r_summary["BIC"]
  
end

#cfiObject

Comparative Fit Index (CFI).

This measure is directly based on the non-centrality measure. Let d = χ2 - df where df are the degrees of freedom of the model. The Comparative Fit Index equals

[d(Null Model) - d(Proposed Model)]/d(Null Model)

If the index is greater than one, it is set at one and if less than zero, it is set to zero. It is interpreted as the previous indexes. If the CFI is less than one, then the CFI is always greater than the TLI. CFI pays a penalty of one for every parameter estimated. Note that the CFI depends on the average size of the correlations in the data. If the average correlation between variables is not high, then the CFI will not be very high.



156
157
158
159
# File 'lib/statsample/sem/semjfoxengine.rb', line 156

def cfi
  @r_summary["CFI"]
  
end

#chi_squareObject

Chi-Square.

For models with about 75 to 200 cases, this is a reasonable measure of fit. But for models with more cases, the chi square is almost always statistically significant. Chi square is also affected by the size of the correlations in the model: the larger the correlations, the poorer the fit.



84
85
86
# File 'lib/statsample/sem/semjfoxengine.rb', line 84

def chi_square
  @r_summary["chisq"]
end

#chi_square_nullObject

Chi-Square for null model



92
93
94
# File 'lib/statsample/sem/semjfoxengine.rb', line 92

def chi_square_null
  @r_summary["chisqNull"]
end

#coefficientsObject



181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/statsample/sem/semjfoxengine.rb', line 181

def coefficients
  est=Hash.new
  coeffs=@r_summary['coeff']
  coeffs[4].each_with_index do |v,i|
    v=~/(.+) (<---|<-->) (.+)/
    f1=$1
    f2=$3
    key=[f1,f2].sort
    est[key]={:estimate=>coeffs[0][i], :se=>coeffs[1][i], :z=>coeffs[2][i], :p=>coeffs[3][i], :label=>@model.get_label(key)}
  end
  est
end

#computeObject



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/statsample/sem/semjfoxengine.rb', line 55

def compute
  raise "Insuficient information" unless @model.complete?
  r.assign 'manifests', @model.manifests
  r.assign 'data', @model.data_type==:raw ? @model.ds : @model.matrix
  if @model.matrix
    r.assign 'vn', @model.variables
    # We should assing names to fields on matrix
    r.void_eval('dimnames(data)<-list(vn,vn)')
  end
  r.void_eval r_query
  @r_summary=@r.eval('sem.summary').to_ruby
end

#dfObject

Degrees of freedom for Chi-Square



88
89
90
# File 'lib/statsample/sem/semjfoxengine.rb', line 88

def df
  @r_summary["df"]
end

#df_nullObject



95
96
97
# File 'lib/statsample/sem/semjfoxengine.rb', line 95

def df_null
  @r_summary["dfNull"]
end

#goodness_of_fitObject

Lisrel measure. Don’t trust!



99
100
101
# File 'lib/statsample/sem/semjfoxengine.rb', line 99

def goodness_of_fit
  @r_summary["GFI"]
end

#graphvizObject



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

def graphviz
  require 'tmpdir'
  out=""
  compute if @r_summary.nil?
  Dir.mktmpdir {|dir| 
    filename=dir+="/model_#{Time.new.to_s}"
    r.void_eval("path.diagram(sem.object,output.type='dot',file='#{filename}')")
    
    file=File.open(filename+".dot","r") do |fp|
      out=fp.read
    end
  }
  out
end

#iterationsObject



178
179
180
# File 'lib/statsample/sem/semjfoxengine.rb', line 178

def iterations
  @r_summary['iterations']
end

#nfiObject

Bentler-Bonett Index or Normed Fit Index (NFI).

Define the null model as a model in which all of the correlations or covariances are zero. The null model is referred to as the “Independence Model” in AMOS. Its formula is:

[χ2(Null Model) - χ2(Proposed Model)]/ [χ2(Null Model)]

A value between .90 and .95 is acceptable, and above .95 is good. A disadvantage of this measure is that it cannot be smaller if more parameters are added to the model. Thus, the more parameters added to the model, the larger the index. It is for this reason that this measure is not recommended, but rather NNFI and CFI is used.



132
133
134
# File 'lib/statsample/sem/semjfoxengine.rb', line 132

def nfi
  @r_summary["NFI"]
end

#nnfiObject

Tucker Lewis Index or Non-normed Fit Index (NNFI).

A problem with the Bentler-Bonett NFI index is that there is no penalty for adding parameters. The Tucker-Lewis index does have such a penalty. Let χ2/df be the ratio of chi square to its degrees of freedom

[χ2/df(Null Model) - χ2/df(Proposed Model)]/[χ2/df(Null Model) - 1]

If the index is greater than one, it is set at one. It is interpreted as the Bentler-Bonett index. Note than for a given model, a lower chi square to df ratio (as long as it is not less than one) implies a better fitting model.



143
144
145
146
# File 'lib/statsample/sem/semjfoxengine.rb', line 143

def nnfi
  @r_summary["NNFI"]
  
end

#normalized_residualObject



175
176
177
# File 'lib/statsample/sem/semjfoxengine.rb', line 175

def normalized_residual
  @r_summary["norm.res"]
end

#rObject



22
23
24
# File 'lib/statsample/sem/semjfoxengine.rb', line 22

def r
  @r||=Rserve::Connection.new
end

#r_queryObject



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/statsample/sem/semjfoxengine.rb', line 44

def r_query
  <<-EOF
library(sem);
sem.model<-matrix(c(
#{r_sempaths}
),
ncol=3,byrow=TRUE)
sem.object<-sem(sem.model,data, obs.variables=manifests, N=#{@model.cases});
sem.summary<-summary(sem.object)
  EOF
end

#r_semdataObject



34
35
36
37
38
39
40
41
42
43
# File 'lib/statsample/sem/semjfoxengine.rb', line 34

def r_semdata
  type=case @model.data_type
    when :raw
      raise "Not implemented"
    when :covariance
      'cov'
    when :correlation
      raise "not implemented"
  end
end

#r_sempathsObject



25
26
27
28
29
30
31
32
33
# File 'lib/statsample/sem/semjfoxengine.rb', line 25

def r_sempaths
  @model.paths.values.map {|path|
    sign=(path[:arrow]==1) ? " ->" : "<->"
    label= path[:label] ? path[:label]  : "NA"  

    label_and_value=(path[:free]) ? "'#{label}', NA" : "NA, #{path[:value]}"
    "'#{path[:from]} #{sign} #{path[:to]}', #{label_and_value}"
  }.join(",\n")
end

#rmseaObject

Root Mean Square Error of Approximation (RMSEA)

This measure is based on the non-centrality parameter. Its formula can be shown to equal:

[([χ2/df] - 1)/(N - 1)]

where N the sample size and df the degrees of freedom of the model. (If χ2 is less than df, then RMSEA is set to zero.) Good models have an RMSEA of .05 or less. Models whose RMSEA is .10 or more have poor fit.



116
117
118
# File 'lib/statsample/sem/semjfoxengine.rb', line 116

def rmsea
  @r_summary["RMSEA"][0]
end

#rmsea_alphaObject



122
123
124
# File 'lib/statsample/sem/semjfoxengine.rb', line 122

def rmsea_alpha
  @r_summary["RMSEA"][3]
end

#rmsea_confidence_intervalObject



119
120
121
# File 'lib/statsample/sem/semjfoxengine.rb', line 119

def rmsea_confidence_interval
  @r_summary["RMSEA"][1..2]
end

#srmrObject



160
161
162
163
# File 'lib/statsample/sem/semjfoxengine.rb', line 160

def srmr
  @r_summary["SRMR"]
  
end