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 RFactor(c, 1)
*/
public RFactor(String c[]) {
this(c, 1);
}
/** same as RFactor(i,v, true, 1)
*/
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 true
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 true
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 && lilevels.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)?";":("levels="+val.size()+";"))+((id==null)?"":("cases="+id.size()))+"}";
StringBuffer sb=new StringBuffer("{levels=(");
if (val==null)
sb.append("null");
else
for (int i=0;i0)?",\"":"\"");
sb.append((String)val.elementAt(i));
sb.append("\"");
};
sb.append("),ids=(");
if (id==null)
sb.append("null");
else
for (int i=0;i0) sb.append(",");
sb.append((Integer)id.elementAt(i));
};
sb.append(")}");
return sb.toString();
} */
}