1 package org.rosuda.REngine;
4 // Copyright (C) 2007 Simon Urbanek
5 // --- for licensing information see LICENSE file in the original distribution ---
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
16 public class RFactor {
21 /** create a new, empty factor var */
22 public RFactor() { ids=new int[0]; levels=new String[0]; }
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)
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];
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);
39 this.index_base = index_base;
42 /** create a new factor variable by factorizing a given string array. The levels will be created in the orer of appearance.
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];
51 while (i < c.length) {
52 int ix = (c[i]==null)?-1:lv.indexOf(c[i]);
53 if (ix<0 && c[i]!=null) {
57 ids[i] = (ix<0)?REXPInteger.NA:(ix+index_base);
60 levels = new String[lv.size()];
62 while (i < levels.length) {
63 levels[i] = (String) lv.elementAt(i);
68 /** same as <code>RFactor(c, 1)</code> */
69 public RFactor(String c[]) {
73 /** same as <code>RFactor(i,v, true, 1)</code> */
74 public RFactor(int[] i, String[] v) {
78 /** returns the level of a given case
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];
86 /** returns <code>true</code> if the data contain the given level index */
87 public boolean contains(int li) {
89 while (i < ids.length) {
90 if (ids[i] == li) return true;
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;
101 while (i < ids.length) {
102 if (ids[i] == li) return true;
108 /** count the number of occurences of a given level index */
109 public int count(int levelIndex) {
112 while (i < ids.length) {
113 if (ids[i] == levelIndex) ct++;
119 /** count the number of occurences of a given level name */
120 public int count(String name) {
121 return count(levelIndex(name));
124 /** return an array with level counts. */
125 public int[] counts() {
126 int[] c = new int[levels.length];
128 while (i < ids.length) {
129 final int li = ids[i] - index_base;
130 if (li>=0 && li<levels.length)
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;
141 while (i < levels.length) {
142 if (levels[i]!=null && levels[i].equals(name)) return i + index_base;
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() {
153 /** return the contents as integer indices (with the index base of this factor) */
154 public int[] asIntegers() {
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++; }
166 /** return the level name for a given level index */
167 public String levelAtIndex(int li) {
169 return (li<0||li>levels.length)?null:levels[li];
172 /** return the level index for a given case */
173 public int indexAt(int i) {
177 /** return the factor as an array of strings */
178 public String[] asStrings() {
179 String[] s = new String[ids.length];
181 while (i < ids.length) {
188 /** return the base of the levels index */
189 public int indexBase() {
193 /** returns the number of cases */
194 public int size() { return ids.length; }
196 public String toString() {
197 return super.toString()+"["+ids.length+","+levels.length+",#"+index_base+"]";
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=(");
207 for (int i=0;i<val.size();i++) {
208 sb.append((i>0)?",\"":"\"");
209 sb.append((String)val.elementAt(i));
212 sb.append("),ids=(");
216 for (int i=0;i<id.size();i++) {
217 if (i>0) sb.append(",");
218 sb.append((Integer)id.elementAt(i));
221 return sb.toString();