1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package ubic.basecode.util.r;
21
22 import org.apache.commons.lang3.StringUtils;
23 import org.rosuda.REngine.REXP;
24 import org.rosuda.REngine.REXPMismatchException;
25 import ubic.basecode.math.linearmodels.AnovaEffect;
26 import ubic.basecode.math.linearmodels.GenericAnovaResult;
27 import ubic.basecode.math.linearmodels.LinearModelSummary;
28
29 import javax.annotation.Nullable;
30 import java.util.*;
31 import java.util.stream.Collectors;
32
33
34
35
36
37
38 class GenericAnovaResultImpl extends AbstractAnovaResult implements GenericAnovaResult {
39
40 private static final long serialVersionUID = 1L;
41
42 private final Map<TreeSet<String>, AnovaEffect> interactionEffects = new LinkedHashMap<>();
43 private final Map<String, AnovaEffect> mainEffects = new LinkedHashMap<>();
44 @Nullable
45 private final AnovaEffect residual;
46
47
48
49
50 public GenericAnovaResultImpl( String key, REXP rAnovaTable ) throws REXPMismatchException {
51 super( key );
52 String[] names = rAnovaTable.getAttribute( "row.names" ).asStrings();
53 double[] pvs = rAnovaTable.asList().at( "Pr(>F)" ).asDoubles();
54 double[] dfs = rAnovaTable.asList().at( "Df" ).asDoubles();
55 double[] fs = rAnovaTable.asList().at( "F value" ).asDoubles();
56 double[] ssq = rAnovaTable.asList().at( "Sum Sq" ).asDoubles();
57 AnovaEffect residual = null;
58 for ( int i = 0; i < pvs.length; i++ ) {
59 String termLabel = names[i];
60 boolean isInteraction = termLabel.contains( ":" );
61 boolean isResidual = termLabel.equals( "Residuals" );
62 AnovaEffectls/AnovaEffect.html#AnovaEffect">AnovaEffect ae = new AnovaEffect( termLabel, pvs[i], fs[i], dfs[i], ssq[i], isInteraction, isResidual );
63 if ( isInteraction ) {
64 interactionEffects.put( new TreeSet<>( Arrays.asList( StringUtils.split( termLabel, ":" ) ) ), ae );
65 } else if ( isResidual ) {
66 residual = ae;
67 } else {
68 mainEffects.put( termLabel, ae );
69 }
70 }
71 this.residual = residual;
72 }
73
74 @Override
75 public boolean hasResiduals() {
76 return residual != null;
77 }
78
79 @Override
80 public double getResidualsDof() {
81 return residual != null ? residual.getDof() : Double.NaN;
82 }
83
84 @Override
85 public double getResidualsFStat() {
86 return residual != null ? residual.getFStat() : Double.NaN;
87 }
88
89 @Override
90 public double getResidualsPValue() {
91 return residual != null ? residual.getPValue() : Double.NaN;
92 }
93
94 @Override
95 public double getInteractionEffectDof() {
96 if ( interactionEffects.size() > 1 ) {
97 throw new IllegalArgumentException( "Must specify which interaction" );
98 }
99 if ( interactionEffects.isEmpty() ) {
100 return Double.NaN;
101 }
102 return interactionEffects.values().iterator().next().getDof();
103 }
104
105 @Override
106 public double getInteractionEffectFStat() {
107 if ( interactionEffects.size() > 1 ) {
108 throw new IllegalArgumentException( "Must specify which interaction" );
109 }
110 if ( interactionEffects.isEmpty() ) {
111 return Double.NaN;
112 }
113 return interactionEffects.values().iterator().next().getFStat();
114 }
115
116 @Override
117 public double getInteractionEffectPValue() {
118 if ( interactionEffects.size() > 1 ) {
119 throw new IllegalArgumentException( "Must specify which interaction" );
120 }
121 if ( interactionEffects.isEmpty() ) {
122 return Double.NaN;
123 }
124 return interactionEffects.values().iterator().next().getPValue();
125 }
126
127 @Override
128 public double getInteractionEffectDof( String... factorNames ) {
129 if ( interactionEffects.isEmpty() ) {
130 return Double.NaN;
131 }
132 TreeSet<String> interactionFactor = new TreeSet<>( Arrays.asList( factorNames ) );
133 if ( !interactionEffects.containsKey( interactionFactor ) ) {
134 return Double.NaN;
135 }
136 return interactionEffects.get( interactionFactor ).getDof();
137 }
138
139 @Override
140 public double getInteractionEffectFStat( String... factorNames ) {
141 if ( interactionEffects.isEmpty() ) {
142 return Double.NaN;
143 }
144 TreeSet<String> interactionFactor = new TreeSet<>( Arrays.asList( factorNames ) );
145 if ( !interactionEffects.containsKey( interactionFactor ) ) {
146 return Double.NaN;
147 }
148 return interactionEffects.get( interactionFactor ).getFStat();
149 }
150
151
152
153
154 @Override
155 public double getInteractionEffectPValue( String... factorNames ) {
156 TreeSet<String> interactionFactor = new TreeSet<>( Arrays.asList( factorNames ) );
157 if ( interactionEffects.isEmpty() ) {
158 return Double.NaN;
159 }
160 if ( !interactionEffects.containsKey( interactionFactor ) ) {
161 return Double.NaN;
162 }
163 return interactionEffects.get( interactionFactor ).getPValue();
164 }
165
166 @Override
167 public double getMainEffectDof( String factorName ) {
168 if ( mainEffects.get( factorName ) == null ) {
169 return Double.NaN;
170 }
171 return mainEffects.get( factorName ).getDof();
172 }
173
174 @Override
175 public double getMainEffectFStat( String factorName ) {
176 if ( mainEffects.get( factorName ) == null ) {
177 return Double.NaN;
178 }
179 return mainEffects.get( factorName ).getFStat();
180 }
181
182
183
184
185 @Override
186 public Collection<String> getMainEffectFactorNames() {
187 return mainEffects.keySet();
188 }
189
190 @Override
191 public double getMainEffectPValue( String factorName ) {
192 if ( mainEffects.get( factorName ) == null ) {
193 return Double.NaN;
194 }
195 return mainEffects.get( factorName ).getPValue();
196 }
197
198 @Override
199 public Collection<String[]> getInteractionEffectFactorNames() {
200 return interactionEffects.keySet().stream()
201 .map( fn -> fn.toArray( new String[0] ) )
202 .collect( Collectors.toList() );
203 }
204
205 @Override
206 public boolean hasInteractions() {
207 return !interactionEffects.isEmpty();
208 }
209
210 @Override
211 public String toString() {
212 StringBuilder buf = new StringBuilder();
213
214 buf.append( "ANOVA table " ).append( this.getKey() ).append( " \n" );
215
216 buf.append( StringUtils.leftPad( "\t", 10 ) ).append( "Df\tSSq\tMSq\tF\tP\n" );
217
218 for ( String me : this.getMainEffectFactorNames() ) {
219 if ( me.equals( LinearModelSummary.INTERCEPT_COEFFICIENT_NAME ) ) {
220 continue;
221 }
222 AnovaEffect a = mainEffects.get( me );
223 buf.append( a ).append( "\n" );
224 }
225
226 if ( hasInteractions() ) {
227 for ( TreeSet<String> ifa : interactionEffects.keySet() ) {
228 AnovaEffect a = this.interactionEffects.get( ifa );
229 buf.append( a ).append( "\n" );
230 }
231 }
232
233 buf.append( residual ).append( "\n" );
234
235 return buf.toString();
236 }
237 }