]> gerrit.simantics Code Review - simantics/r.git/blob - org.simantics.r.scl/src/org/rosuda/REngine/RFactor.java
(refs #6833) Test RExp inheritance in SCL
[simantics/r.git] / org.simantics.r.scl / src / org / rosuda / REngine / RFactor.java
1 package org.rosuda.REngine;
2
3 // REngine
4 // Copyright (C) 2007 Simon Urbanek
5 // --- for licensing information see LICENSE file in the original distribution ---
6
7 import java.util.*;
8
9 /** representation of a factor variable. In R there is no actual object
10     type called "factor", instead it is coded as an int vector with a list
11     attribute. The parser code of REXP converts such constructs directly into
12     the RFactor objects and defines an own XT_FACTOR type 
13     
14     @version $Id$
15 */    
16 public class RFactor {
17     int ids[];
18     String levels[];
19         int index_base;
20
21     /** create a new, empty factor var */
22     public RFactor() { ids=new int[0]; levels=new String[0]; }
23     
24     /** create a new factor variable, based on the supplied arrays.
25                 @param i array of IDs (inde_base..v.length+index_base-1)
26                 @param v values - cotegory names
27                 @param copy copy above vaules or just retain them
28                 @param index_base index of the first level element (1 for R factors, cannot be negtive)
29                 */
30     public RFactor(int[] i, String[] v, boolean copy, int index_base) {
31                 if (i==null) i = new int[0];
32                 if (v==null) v = new String[0];
33                 if (copy) {
34                         ids=new int[i.length]; System.arraycopy(i,0,ids,0,i.length);
35                         levels=new String[v.length]; System.arraycopy(v,0,levels,0,v.length);
36                 } else {
37                         ids=i; levels=v;
38                 }
39                 this.index_base = index_base;
40     }
41
42         /** create a new factor variable by factorizing a given string array. The levels will be created in the orer of appearance.
43                 @param c contents
44                 @param index_base base of the level index */
45         public RFactor(String c[], int index_base) {
46                 this.index_base = index_base;
47                 if (c == null) c = new String[0];
48                 Vector lv = new Vector();
49                 ids = new int[c.length];
50                 int i = 0;
51                 while (i < c.length) {
52                         int ix = (c[i]==null)?-1:lv.indexOf(c[i]);
53                         if (ix<0 && c[i]!=null) {
54                                 ix = lv.size();
55                                 lv.add(c[i]);
56                         }
57                         ids[i] = (ix<0)?REXPInteger.NA:(ix+index_base);
58                         i++;
59                 }
60                 levels = new String[lv.size()];
61                 i = 0;
62                 while (i < levels.length) {
63                         levels[i] = (String) lv.elementAt(i);
64                         i++;
65                 }
66         }
67         
68         /** same as <code>RFactor(c, 1)</code> */
69         public RFactor(String c[]) {
70                 this(c, 1);
71         }
72         
73         /** same as <code>RFactor(i,v, true, 1)</code> */
74         public RFactor(int[] i, String[] v) {
75                 this(i, v, true, 1);
76         }
77         
78     /** returns the level of a given case
79                 @param i case number
80                 @return name. may throw exception if out of range */
81     public String at(int i) {
82                 int li = ids[i] - index_base;
83                 return (li<0||li>levels.length)?null:levels[li];
84     }
85
86         /** returns <code>true</code> if the data contain the given level index */
87         public boolean contains(int li) {
88                 int i = 0;
89                 while (i < ids.length) {
90                         if (ids[i] == li) return true;
91                         i++;
92                 }
93                 return false;
94         }
95         
96         /** return <code>true</code> if the factor contains the given level (it is NOT the same as levelIndex==-1!) */
97         public boolean contains(String name) {
98                 int li = levelIndex(name);
99                 if (li<0) return false;
100                 int i = 0;
101                 while (i < ids.length) {
102                         if (ids[i] == li) return true;
103                         i++;
104                 }
105                 return false;
106         }
107         
108         /** count the number of occurences of a given level index */
109         public int count(int levelIndex) {
110                 int i = 0;
111                 int ct = 0;
112                 while (i < ids.length) {
113                         if (ids[i] == levelIndex) ct++;
114                         i++;
115                 }
116                 return ct;
117         }
118         
119         /** count the number of occurences of a given level name */
120         public int count(String name) {
121                 return count(levelIndex(name));
122         }
123         
124         /** return an array with level counts. */
125         public int[] counts() {
126                 int[] c = new int[levels.length];
127                 int i = 0;
128                 while (i < ids.length) {
129                         final int li = ids[i] - index_base;
130                         if (li>=0 && li<levels.length)
131                                 c[li]++;
132                         i++;
133                 }
134                 return c;
135         }
136         
137         /** return the index of a given level name or -1 if it doesn't exist */
138         public int levelIndex(String name) {
139                 if (name==null) return -1;
140                 int i = 0;
141                 while (i < levels.length) {
142                         if (levels[i]!=null && levels[i].equals(name)) return i + index_base;
143                         i++;
144                 }
145                 return -1;
146         }
147         
148         /** return the list of levels (0-based, use {@link #indexBase} correction if you want to access it by level index) */
149         public String[] levels() {
150                 return levels;
151         }
152         
153         /** return the contents as integer indices (with the index base of this factor) */
154         public int[] asIntegers() {
155                 return ids;
156         }
157         
158         /** return the contents as integer indices with a given index base */
159         public int[] asIntegers(int desired_index_base) {
160                 if (desired_index_base == index_base) return ids;
161                 int[] ix = new int[ids.length];
162                 int j = 0; while (j < ids.length) { ix[j] = ids[j] - index_base + desired_index_base; j++; }
163                 return ix;
164         }
165         
166         /** return the level name for a given level index */
167         public String levelAtIndex(int li) {
168                 li -= index_base;
169                 return (li<0||li>levels.length)?null:levels[li];
170         }
171         
172         /** return the level index for a given case */
173         public int indexAt(int i) {
174                 return ids[i];
175         }
176         
177         /** return the factor as an array of strings */
178         public String[] asStrings() {
179                 String[] s = new String[ids.length];
180                 int i = 0;
181                 while (i < ids.length) {
182                         s[i] = at(i);
183                         i++;
184                 }
185                 return s;       
186         }
187         
188         /** return the base of the levels index */
189         public int indexBase() {
190                 return index_base;
191         }
192         
193     /** returns the number of cases */
194     public int size() { return ids.length; }
195
196         public String toString() {
197                 return super.toString()+"["+ids.length+","+levels.length+",#"+index_base+"]";
198         }
199         
200     /** displayable representation of the factor variable
201     public String toString() {
202         //return "{"+((val==null)?"<null>;":("levels="+val.size()+";"))+((id==null)?"<null>":("cases="+id.size()))+"}";
203         StringBuffer sb=new StringBuffer("{levels=(");
204         if (val==null)
205             sb.append("null");
206         else
207             for (int i=0;i<val.size();i++) {
208                 sb.append((i>0)?",\"":"\"");
209                 sb.append((String)val.elementAt(i));
210                 sb.append("\"");
211             };
212         sb.append("),ids=(");
213         if (id==null)
214             sb.append("null");
215         else
216             for (int i=0;i<id.size();i++) {
217                 if (i>0) sb.append(",");
218                 sb.append((Integer)id.elementAt(i));
219             };
220         sb.append(")}");
221         return sb.toString();
222     } */
223 }
224