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