~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/core/Instance.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *    This program is free software; you can redistribute it and/or modify
 
3
 *    it under the terms of the GNU General Public License as published by
 
4
 *    the Free Software Foundation; either version 2 of the License, or
 
5
 *    (at your option) any later version.
 
6
 *
 
7
 *    This program is distributed in the hope that it will be useful,
 
8
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
 *    GNU General Public License for more details.
 
11
 *
 
12
 *    You should have received a copy of the GNU General Public License
 
13
 *    along with this program; if not, write to the Free Software
 
14
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
15
 */
 
16
 
 
17
/*
 
18
 *    Instance.java
 
19
 *    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
package weka.core;
 
24
 
 
25
import java.io.Serializable;
 
26
import java.util.Enumeration;
 
27
 
 
28
/**
 
29
 * Class for handling an instance. All values (numeric, date, nominal, string
 
30
 * or relational) are internally stored as floating-point numbers. If an
 
31
 * attribute is nominal (or a string or relational), the stored value is the
 
32
 * index of the corresponding nominal (or string or relational) value in the
 
33
 * attribute's definition. We have chosen this approach in favor of a more
 
34
 * elegant object-oriented approach because it is much faster. <p>
 
35
 *
 
36
 * Typical usage (code from the main() method of this class): <p>
 
37
 *
 
38
 * <code>
 
39
 * ... <br>
 
40
 *      
 
41
 * // Create empty instance with three attribute values <br>
 
42
 * Instance inst = new Instance(3); <br><br>
 
43
 *     
 
44
 * // Set instance's values for the attributes "length", "weight", and "position"<br>
 
45
 * inst.setValue(length, 5.3); <br>
 
46
 * inst.setValue(weight, 300); <br>
 
47
 * inst.setValue(position, "first"); <br><br>
 
48
 *   
 
49
 * // Set instance's dataset to be the dataset "race" <br>
 
50
 * inst.setDataset(race); <br><br>
 
51
 *   
 
52
 * // Print the instance <br>
 
53
 * System.out.println("The instance: " + inst); <br>
 
54
 *
 
55
 * ... <br>
 
56
 * </code><p>
 
57
 *
 
58
 * All methods that change an instance are safe, ie. a change of an
 
59
 * instance does not affect any other instances. All methods that
 
60
 * change an instance's attribute values clone the attribute value
 
61
 * vector before it is changed. If your application heavily modifies
 
62
 * instance values, it may be faster to create a new instance from scratch.
 
63
 *
 
64
 * @author Eibe Frank (eibe@cs.waikato.ac.nz)
 
65
 * @version $Revision: 1.25 $ 
 
66
 */
 
67
public class Instance
 
68
  implements Copyable, Serializable {
 
69
  
 
70
  /** for serialization */
 
71
  static final long serialVersionUID = 1482635194499365122L;
 
72
  
 
73
  /** Constant representing a missing value. */
 
74
  protected static final double MISSING_VALUE = Double.NaN;
 
75
 
 
76
  /** 
 
77
   * The dataset the instance has access to.  Null if the instance
 
78
   * doesn't have access to any dataset.  Only if an instance has
 
79
   * access to a dataset, it knows about the actual attribute types.  
 
80
   */
 
81
  protected /*@spec_public@*/ Instances m_Dataset;
 
82
 
 
83
  /** The instance's attribute values. */
 
84
  protected /*@spec_public non_null@*/ double[] m_AttValues;
 
85
 
 
86
  /** The instance's weight. */
 
87
  protected double m_Weight;
 
88
 
 
89
  /**
 
90
   * Constructor that copies the attribute values and the weight from
 
91
   * the given instance. Reference to the dataset is set to null.
 
92
   * (ie. the instance doesn't have access to information about the
 
93
   * attribute types)
 
94
   *
 
95
   * @param instance the instance from which the attribute
 
96
   * values and the weight are to be copied 
 
97
   */
 
98
  //@ ensures m_Dataset == null;
 
99
  public Instance(/*@non_null@*/ Instance instance) {
 
100
    
 
101
    m_AttValues = instance.m_AttValues;
 
102
    m_Weight = instance.m_Weight;
 
103
    m_Dataset = null;
 
104
  }
 
105
 
 
106
  /**
 
107
   * Constructor that inititalizes instance variable with given
 
108
   * values. Reference to the dataset is set to null. (ie. the instance
 
109
   * doesn't have access to information about the attribute types)
 
110
   *
 
111
   * @param weight the instance's weight
 
112
   * @param attValues a vector of attribute values 
 
113
   */
 
114
  //@ ensures m_Dataset == null;
 
115
  public Instance(double weight,  /*@non_null@*/ double[]attValues){
 
116
    
 
117
    m_AttValues = attValues;
 
118
    m_Weight = weight;
 
119
    m_Dataset = null;
 
120
  }
 
121
 
 
122
  /**
 
123
   * Constructor of an instance that sets weight to one, all values to
 
124
   * be missing, and the reference to the dataset to null. (ie. the instance
 
125
   * doesn't have access to information about the attribute types)
 
126
   *
 
127
   * @param numAttributes the size of the instance 
 
128
   */
 
129
  //@ requires numAttributes > 0;    // Or maybe == 0 is okay too?
 
130
  //@ ensures m_Dataset == null;
 
131
  public Instance(int numAttributes) {
 
132
    
 
133
    m_AttValues = new double[numAttributes];
 
134
    for (int i = 0; i < m_AttValues.length; i++) {
 
135
      m_AttValues[i] = MISSING_VALUE;
 
136
    }
 
137
    m_Weight = 1;
 
138
    m_Dataset = null;
 
139
  }
 
140
 
 
141
  /**
 
142
   * Returns the attribute with the given index.
 
143
   *
 
144
   * @param index the attribute's index
 
145
   * @return the attribute at the given position
 
146
   * @throws UnassignedDatasetException if instance doesn't have access to a
 
147
   * dataset
 
148
   */ 
 
149
  //@ requires m_Dataset != null;
 
150
  public /*@pure@*/ Attribute attribute(int index) {
 
151
   
 
152
    if (m_Dataset == null) {
 
153
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
154
    }
 
155
    return m_Dataset.attribute(index);
 
156
  }
 
157
 
 
158
  /**
 
159
   * Returns the attribute with the given index. Does the same
 
160
   * thing as attribute().
 
161
   *
 
162
   * @param indexOfIndex the index of the attribute's index 
 
163
   * @return the attribute at the given position
 
164
   * @throws UnassignedDatasetException if instance doesn't have access to a
 
165
   * dataset
 
166
   */ 
 
167
  //@ requires m_Dataset != null;
 
168
  public /*@pure@*/ Attribute attributeSparse(int indexOfIndex) {
 
169
   
 
170
    if (m_Dataset == null) {
 
171
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
172
    }
 
173
    return m_Dataset.attribute(indexOfIndex);
 
174
  }
 
175
 
 
176
  /**
 
177
   * Returns class attribute.
 
178
   *
 
179
   * @return the class attribute
 
180
   * @throws UnassignedDatasetException if the class is not set or the
 
181
   * instance doesn't have access to a dataset
 
182
   */
 
183
  //@ requires m_Dataset != null;
 
184
  public /*@pure@*/ Attribute classAttribute() {
 
185
 
 
186
    if (m_Dataset == null) {
 
187
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
188
    }
 
189
    return m_Dataset.classAttribute();
 
190
  }
 
191
 
 
192
  /**
 
193
   * Returns the class attribute's index.
 
194
   *
 
195
   * @return the class index as an integer 
 
196
   * @throws UnassignedDatasetException if instance doesn't have access to a dataset 
 
197
   */
 
198
  //@ requires m_Dataset != null;
 
199
  //@ ensures  \result == m_Dataset.classIndex();
 
200
  public /*@pure@*/ int classIndex() {
 
201
    
 
202
    if (m_Dataset == null) {
 
203
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
204
    }
 
205
    return m_Dataset.classIndex();
 
206
  }
 
207
 
 
208
  /**
 
209
   * Tests if an instance's class is missing.
 
210
   *
 
211
   * @return true if the instance's class is missing
 
212
   * @throws UnassignedClassException if the class is not set or the instance doesn't
 
213
   * have access to a dataset
 
214
   */
 
215
  //@ requires classIndex() >= 0;
 
216
  public /*@pure@*/ boolean classIsMissing() {
 
217
 
 
218
    if (classIndex() < 0) {
 
219
      throw new UnassignedClassException("Class is not set!");
 
220
    }
 
221
    return isMissing(classIndex());
 
222
  }
 
223
 
 
224
  /**
 
225
   * Returns an instance's class value in internal format. (ie. as a
 
226
   * floating-point number)
 
227
   *
 
228
   * @return the corresponding value as a double (If the 
 
229
   * corresponding attribute is nominal (or a string) then it returns the 
 
230
   * value's index as a double).
 
231
   * @throws UnassignedClassException if the class is not set or the instance doesn't
 
232
   * have access to a dataset 
 
233
   */
 
234
  //@ requires classIndex() >= 0;
 
235
  public /*@pure@*/ double classValue() {
 
236
    
 
237
    if (classIndex() < 0) {
 
238
      throw new UnassignedClassException("Class is not set!");
 
239
    }
 
240
    return value(classIndex());
 
241
  }
 
242
 
 
243
  /**
 
244
   * Produces a shallow copy of this instance. The copy has
 
245
   * access to the same dataset. (if you want to make a copy
 
246
   * that doesn't have access to the dataset, use 
 
247
   * <code>new Instance(instance)</code>
 
248
   *
 
249
   * @return the shallow copy
 
250
   */
 
251
  //@ also ensures \result != null;
 
252
  //@ also ensures \result instanceof Instance;
 
253
  //@ also ensures ((Instance)\result).m_Dataset == m_Dataset;
 
254
  public /*@pure@*/ Object copy() {
 
255
 
 
256
    Instance result = new Instance(this);
 
257
    result.m_Dataset = m_Dataset;
 
258
    return result;
 
259
  }
 
260
 
 
261
  /**
 
262
   * Returns the dataset this instance has access to. (ie. obtains
 
263
   * information about attribute types from) Null if the instance
 
264
   * doesn't have access to a dataset.
 
265
   *
 
266
   * @return the dataset the instance has accesss to
 
267
   */
 
268
  //@ ensures \result == m_Dataset;
 
269
  public /*@pure@*/ Instances dataset() {
 
270
 
 
271
    return m_Dataset;
 
272
  }
 
273
 
 
274
  /**
 
275
   * Deletes an attribute at the given position (0 to 
 
276
   * numAttributes() - 1). Only succeeds if the instance does not
 
277
   * have access to any dataset because otherwise inconsistencies
 
278
   * could be introduced.
 
279
   *
 
280
   * @param position the attribute's position
 
281
   * @throws RuntimeException if the instance has access to a
 
282
   * dataset 
 
283
   */
 
284
  //@ requires m_Dataset != null;
 
285
  public void deleteAttributeAt(int position) {
 
286
 
 
287
    if (m_Dataset != null) {
 
288
      throw new RuntimeException("Instance has access to a dataset!");
 
289
    }
 
290
    forceDeleteAttributeAt(position);
 
291
  }
 
292
 
 
293
  /**
 
294
   * Returns an enumeration of all the attributes.
 
295
   *
 
296
   * @return enumeration of all the attributes
 
297
   * @throws UnassignedDatasetException if the instance doesn't
 
298
   * have access to a dataset 
 
299
   */
 
300
  //@ requires m_Dataset != null;
 
301
  public /*@pure@*/ Enumeration enumerateAttributes() {
 
302
 
 
303
    if (m_Dataset == null) {
 
304
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
305
    }
 
306
    return m_Dataset.enumerateAttributes();
 
307
  }
 
308
 
 
309
  /**
 
310
   * Tests if the headers of two instances are equivalent.
 
311
   *
 
312
   * @param inst another instance
 
313
   * @return true if the header of the given instance is 
 
314
   * equivalent to this instance's header
 
315
   * @throws UnassignedDatasetException if instance doesn't have access to any
 
316
   * dataset
 
317
   */
 
318
  //@ requires m_Dataset != null;
 
319
  public /*@pure@*/ boolean equalHeaders(Instance inst) {
 
320
 
 
321
    if (m_Dataset == null) {
 
322
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
323
    }
 
324
    return m_Dataset.equalHeaders(inst.m_Dataset);
 
325
  }
 
326
 
 
327
  /**
 
328
   * Tests whether an instance has a missing value. Skips the class attribute if set.
 
329
   * @return true if instance has a missing value.
 
330
   * @throws UnassignedDatasetException if instance doesn't have access to any
 
331
   * dataset
 
332
   */
 
333
  //@ requires m_Dataset != null;
 
334
  public /*@pure@*/ boolean hasMissingValue() {
 
335
    
 
336
    if (m_Dataset == null) {
 
337
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
338
    }
 
339
    for (int i = 0; i < numAttributes(); i++) {
 
340
      if (i != classIndex()) {
 
341
        if (isMissing(i)) {
 
342
          return true;
 
343
        }
 
344
      }
 
345
    }
 
346
    return false;
 
347
  }
 
348
 
 
349
  /**
 
350
   * Returns the index of the attribute stored at the given position.
 
351
   * Just returns the given value.
 
352
   *
 
353
   * @param position the position 
 
354
   * @return the index of the attribute stored at the given position
 
355
   */
 
356
  public /*@pure@*/ int index(int position) {
 
357
 
 
358
    return position;
 
359
  }
 
360
 
 
361
  /**
 
362
   * Inserts an attribute at the given position (0 to 
 
363
   * numAttributes()). Only succeeds if the instance does not
 
364
   * have access to any dataset because otherwise inconsistencies
 
365
   * could be introduced.
 
366
   *
 
367
   * @param position the attribute's position
 
368
   * @throws RuntimeException if the instance has accesss to a
 
369
   * dataset
 
370
   * @throws IllegalArgumentException if the position is out of range
 
371
   */
 
372
  //@ requires m_Dataset == null;
 
373
  //@ requires 0 <= position && position <= numAttributes();
 
374
  public void insertAttributeAt(int position) {
 
375
 
 
376
    if (m_Dataset != null) {
 
377
      throw new RuntimeException("Instance has accesss to a dataset!");
 
378
    }
 
379
    if ((position < 0) ||
 
380
        (position > numAttributes())) {
 
381
      throw new IllegalArgumentException("Can't insert attribute: index out "+
 
382
                                         "of range");
 
383
    }
 
384
    forceInsertAttributeAt(position);
 
385
  }
 
386
 
 
387
  /**
 
388
   * Tests if a specific value is "missing".
 
389
   *
 
390
   * @param attIndex the attribute's index
 
391
   * @return true if the value is "missing"
 
392
   */
 
393
  public /*@pure@*/ boolean isMissing(int attIndex) {
 
394
 
 
395
    if (Double.isNaN(m_AttValues[attIndex])) {
 
396
      return true;
 
397
    }
 
398
    return false;
 
399
  }
 
400
 
 
401
  /**
 
402
   * Tests if a specific value is "missing". Does
 
403
   * the same thing as isMissing() if applied to an Instance.
 
404
   *
 
405
   * @param indexOfIndex the index of the attribute's index 
 
406
   * @return true if the value is "missing"
 
407
   */
 
408
  public /*@pure@*/ boolean isMissingSparse(int indexOfIndex) {
 
409
 
 
410
    if (Double.isNaN(m_AttValues[indexOfIndex])) {
 
411
      return true;
 
412
    }
 
413
    return false;
 
414
  }
 
415
 
 
416
  /**
 
417
   * Tests if a specific value is "missing".
 
418
   * The given attribute has to belong to a dataset.
 
419
   *
 
420
   * @param att the attribute
 
421
   * @return true if the value is "missing"
 
422
   */
 
423
  public /*@pure@*/ boolean isMissing(Attribute att) {
 
424
 
 
425
    return isMissing(att.index());
 
426
  }
 
427
 
 
428
  /**
 
429
   * Tests if the given value codes "missing".
 
430
   *
 
431
   * @param val the value to be tested
 
432
   * @return true if val codes "missing"
 
433
   */
 
434
  public static /*@pure@*/ boolean isMissingValue(double val) {
 
435
 
 
436
    return Double.isNaN(val);
 
437
  }
 
438
 
 
439
  /**
 
440
   * Merges this instance with the given instance and returns
 
441
   * the result. Dataset is set to null.
 
442
   *
 
443
   * @param inst the instance to be merged with this one
 
444
   * @return the merged instances
 
445
   */
 
446
  public Instance mergeInstance(Instance inst) {
 
447
 
 
448
    int m = 0;
 
449
    double [] newVals = new double[numAttributes() + inst.numAttributes()];
 
450
    for (int j = 0; j < numAttributes(); j++, m++) {
 
451
      newVals[m] = value(j);
 
452
    }
 
453
    for (int j = 0; j < inst.numAttributes(); j++, m++) {
 
454
      newVals[m] = inst.value(j);
 
455
    }
 
456
    return new Instance(1.0, newVals);
 
457
  }
 
458
 
 
459
  /**
 
460
   * Returns the double that codes "missing".
 
461
   *
 
462
   * @return the double that codes "missing"
 
463
   */
 
464
  public /*@pure@*/ static double missingValue() {
 
465
 
 
466
    return MISSING_VALUE;
 
467
  }
 
468
 
 
469
  /**
 
470
   * Returns the number of attributes.
 
471
   *
 
472
   * @return the number of attributes as an integer
 
473
   */
 
474
  //@ ensures \result == m_AttValues.length;
 
475
  public /*@pure@*/ int numAttributes() {
 
476
 
 
477
    return m_AttValues.length;
 
478
  }
 
479
 
 
480
  /**
 
481
   * Returns the number of class labels.
 
482
   *
 
483
   * @return the number of class labels as an integer if the 
 
484
   * class attribute is nominal, 1 otherwise.
 
485
   * @throws UnassignedDatasetException if instance doesn't have access to any
 
486
   * dataset
 
487
   */
 
488
  //@ requires m_Dataset != null;
 
489
  public /*@pure@*/ int numClasses() {
 
490
    
 
491
    if (m_Dataset == null) {
 
492
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
493
    }
 
494
    return m_Dataset.numClasses();
 
495
  }
 
496
 
 
497
  /**
 
498
   * Returns the number of values present. Always the same as numAttributes().
 
499
   *
 
500
   * @return the number of values
 
501
   */
 
502
  //@ ensures \result == m_AttValues.length;
 
503
  public /*@pure@*/ int numValues() {
 
504
 
 
505
    return m_AttValues.length;
 
506
  }
 
507
 
 
508
  /** 
 
509
   * Replaces all missing values in the instance with the
 
510
   * values contained in the given array. A deep copy of
 
511
   * the vector of attribute values is performed before the
 
512
   * values are replaced.
 
513
   *
 
514
   * @param array containing the means and modes
 
515
   * @throws IllegalArgumentException if numbers of attributes are unequal
 
516
   */
 
517
  public void replaceMissingValues(double[] array) {
 
518
         
 
519
    if ((array == null) || 
 
520
        (array.length != m_AttValues.length)) {
 
521
      throw new IllegalArgumentException("Unequal number of attributes!");
 
522
    }
 
523
    freshAttributeVector();
 
524
    for (int i = 0; i < m_AttValues.length; i++) {
 
525
      if (isMissing(i)) {
 
526
        m_AttValues[i] = array[i];
 
527
      }
 
528
    }
 
529
  }
 
530
 
 
531
  /**
 
532
   * Sets the class value of an instance to be "missing". A deep copy of
 
533
   * the vector of attribute values is performed before the
 
534
   * value is set to be missing.
 
535
   *
 
536
   * @throws UnassignedClassException if the class is not set
 
537
   * @throws UnassignedDatasetException if the instance doesn't
 
538
   * have access to a dataset
 
539
   */
 
540
  //@ requires classIndex() >= 0;
 
541
  public void setClassMissing() {
 
542
 
 
543
    if (classIndex() < 0) {
 
544
      throw new UnassignedClassException("Class is not set!");
 
545
    }
 
546
    setMissing(classIndex());
 
547
  }
 
548
 
 
549
  /**
 
550
   * Sets the class value of an instance to the given value (internal
 
551
   * floating-point format).  A deep copy of the vector of attribute
 
552
   * values is performed before the value is set.
 
553
   *
 
554
   * @param value the new attribute value (If the corresponding
 
555
   * attribute is nominal (or a string) then this is the new value's
 
556
   * index as a double).  
 
557
   * @throws UnassignedClassException if the class is not set
 
558
   * @throws UnaddignedDatasetException if the instance doesn't
 
559
   * have access to a dataset 
 
560
   */
 
561
  //@ requires classIndex() >= 0;
 
562
  public void setClassValue(double value) {
 
563
 
 
564
    if (classIndex() < 0) {
 
565
      throw new UnassignedClassException("Class is not set!");
 
566
    }
 
567
    setValue(classIndex(), value);
 
568
  }
 
569
 
 
570
  /**
 
571
   * Sets the class value of an instance to the given value. A deep
 
572
   * copy of the vector of attribute values is performed before the
 
573
   * value is set.
 
574
   *
 
575
   * @param value the new class value (If the class
 
576
   * is a string attribute and the value can't be found,
 
577
   * the value is added to the attribute).
 
578
   * @throws UnassignedClassException if the class is not set
 
579
   * @throws UnassignedDatasetException if the dataset is not set
 
580
   * @throws IllegalArgumentException if the attribute is not
 
581
   * nominal or a string, or the value couldn't be found for a nominal
 
582
   * attribute 
 
583
   */
 
584
  //@ requires classIndex() >= 0;
 
585
  public final void setClassValue(String value) {
 
586
 
 
587
    if (classIndex() < 0) {
 
588
      throw new UnassignedClassException("Class is not set!");
 
589
    }
 
590
    setValue(classIndex(), value);
 
591
  }
 
592
 
 
593
  /**
 
594
   * Sets the reference to the dataset. Does not check if the instance
 
595
   * is compatible with the dataset. Note: the dataset does not know
 
596
   * about this instance. If the structure of the dataset's header
 
597
   * gets changed, this instance will not be adjusted automatically.
 
598
   *
 
599
   * @param instances the reference to the dataset 
 
600
   */
 
601
  public final void setDataset(Instances instances) {
 
602
    
 
603
    m_Dataset = instances;
 
604
  }
 
605
 
 
606
  /**
 
607
   * Sets a specific value to be "missing". Performs a deep copy
 
608
   * of the vector of attribute values before the value is set to
 
609
   * be missing.
 
610
   *
 
611
   * @param attIndex the attribute's index
 
612
   */
 
613
  public final void setMissing(int attIndex) {
 
614
 
 
615
    setValue(attIndex, MISSING_VALUE);
 
616
  }
 
617
 
 
618
  /**
 
619
   * Sets a specific value to be "missing". Performs a deep copy
 
620
   * of the vector of attribute values before the value is set to
 
621
   * be missing. The given attribute has to belong to a dataset.
 
622
   *
 
623
   * @param att the attribute
 
624
   */
 
625
  public final void setMissing(Attribute att) {
 
626
 
 
627
    setMissing(att.index());
 
628
  }
 
629
 
 
630
  /**
 
631
   * Sets a specific value in the instance to the given value 
 
632
   * (internal floating-point format). Performs a deep copy
 
633
   * of the vector of attribute values before the value is set.
 
634
   *
 
635
   * @param attIndex the attribute's index 
 
636
   * @param value the new attribute value (If the corresponding
 
637
   * attribute is nominal (or a string) then this is the new value's
 
638
   * index as a double).  
 
639
   */
 
640
  public void setValue(int attIndex, double value) {
 
641
    
 
642
    freshAttributeVector();
 
643
    m_AttValues[attIndex] = value;
 
644
  }
 
645
 
 
646
  /**
 
647
   * Sets a specific value in the instance to the given value 
 
648
   * (internal floating-point format). Performs a deep copy
 
649
   * of the vector of attribute values before the value is set.
 
650
   * Does exactly the same thing as setValue().
 
651
   *
 
652
   * @param indexOfIndex the index of the attribute's index 
 
653
   * @param value the new attribute value (If the corresponding
 
654
   * attribute is nominal (or a string) then this is the new value's
 
655
   * index as a double).  
 
656
   */
 
657
  public void setValueSparse(int indexOfIndex, double value) {
 
658
    
 
659
    freshAttributeVector();
 
660
    m_AttValues[indexOfIndex] = value;
 
661
  }
 
662
 
 
663
  /**
 
664
   * Sets a value of a nominal or string attribute to the given
 
665
   * value. Performs a deep copy of the vector of attribute values
 
666
   * before the value is set.
 
667
   *
 
668
   * @param attIndex the attribute's index
 
669
   * @param value the new attribute value (If the attribute
 
670
   * is a string attribute and the value can't be found,
 
671
   * the value is added to the attribute).
 
672
   * @throws UnassignedDatasetException if the dataset is not set
 
673
   * @throws IllegalArgumentException if the selected
 
674
   * attribute is not nominal or a string, or the supplied value couldn't 
 
675
   * be found for a nominal attribute 
 
676
   */
 
677
  //@ requires m_Dataset != null;
 
678
  public final void setValue(int attIndex, String value) {
 
679
    
 
680
    int valIndex;
 
681
 
 
682
    if (m_Dataset == null) {
 
683
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
684
    }
 
685
    if (!attribute(attIndex).isNominal() &&
 
686
        !attribute(attIndex).isString()) {
 
687
      throw new IllegalArgumentException("Attribute neither nominal nor string!");
 
688
    }
 
689
    valIndex = attribute(attIndex).indexOfValue(value);
 
690
    if (valIndex == -1) {
 
691
      if (attribute(attIndex).isNominal()) {
 
692
        throw new IllegalArgumentException("Value not defined for given nominal attribute!");
 
693
      } else {
 
694
        attribute(attIndex).forceAddValue(value);
 
695
        valIndex = attribute(attIndex).indexOfValue(value);
 
696
      }
 
697
    }
 
698
    setValue(attIndex, (double)valIndex); 
 
699
  }
 
700
 
 
701
  /**
 
702
   * Sets a specific value in the instance to the given value
 
703
   * (internal floating-point format). Performs a deep copy of the
 
704
   * vector of attribute values before the value is set, so if you are
 
705
   * planning on calling setValue many times it may be faster to
 
706
   * create a new instance using toDoubleArray.  The given attribute
 
707
   * has to belong to a dataset.
 
708
   *
 
709
   * @param att the attribute 
 
710
   * @param value the new attribute value (If the corresponding
 
711
   * attribute is nominal (or a string) then this is the new value's
 
712
   * index as a double).  
 
713
   */
 
714
  public final void setValue(Attribute att, double value) {
 
715
 
 
716
    setValue(att.index(), value);
 
717
  }
 
718
 
 
719
  /**
 
720
   * Sets a value of an nominal or string attribute to the given
 
721
   * value. Performs a deep copy of the vector of attribute values
 
722
   * before the value is set, so if you are planning on calling setValue many
 
723
   * times it may be faster to create a new instance using toDoubleArray.
 
724
   * The given attribute has to belong to a dataset.
 
725
   *
 
726
   * @param att the attribute
 
727
   * @param value the new attribute value (If the attribute
 
728
   * is a string attribute and the value can't be found,
 
729
   * the value is added to the attribute).
 
730
   * @throws IllegalArgumentException if the the attribute is not
 
731
   * nominal or a string, or the value couldn't be found for a nominal
 
732
   * attribute 
 
733
   */
 
734
  public final void setValue(Attribute att, String value) {
 
735
 
 
736
    if (!att.isNominal() &&
 
737
        !att.isString()) {
 
738
      throw new IllegalArgumentException("Attribute neither nominal nor string!");
 
739
    }
 
740
    int valIndex = att.indexOfValue(value);
 
741
    if (valIndex == -1) {
 
742
      if (att.isNominal()) {
 
743
        throw new IllegalArgumentException("Value not defined for given nominal attribute!");
 
744
      } else {
 
745
        att.forceAddValue(value);
 
746
        valIndex = att.indexOfValue(value);
 
747
      }
 
748
    }
 
749
    setValue(att.index(), (double)valIndex);
 
750
  }
 
751
 
 
752
  /**
 
753
   * Sets the weight of an instance.
 
754
   *
 
755
   * @param weight the weight
 
756
   */
 
757
  public final void setWeight(double weight) {
 
758
 
 
759
    m_Weight = weight;
 
760
  }
 
761
 
 
762
  /** 
 
763
   * Returns the relational value of a relational attribute.
 
764
   *
 
765
   * @param attIndex the attribute's index
 
766
   * @return the corresponding relation as an Instances object
 
767
   * @throws IllegalArgumentException if the attribute is not a
 
768
   * relation-valued attribute
 
769
   * @throws UnassignedDatasetException if the instance doesn't belong
 
770
   * to a dataset.
 
771
   */
 
772
  //@ requires m_Dataset != null;
 
773
  public final /*@pure@*/ Instances relationalValue(int attIndex) {
 
774
 
 
775
    if (m_Dataset == null) {
 
776
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
777
    } 
 
778
    return relationalValue(m_Dataset.attribute(attIndex));
 
779
  }
 
780
 
 
781
 
 
782
  /** 
 
783
   * Returns the relational value of a relational attribute.
 
784
   *
 
785
   * @param att the attribute
 
786
   * @return the corresponding relation as an Instances object
 
787
   * @throws IllegalArgumentException if the attribute is not a
 
788
   * relation-valued attribute
 
789
   * @throws UnassignedDatasetException if the instance doesn't belong
 
790
   * to a dataset.
 
791
   */
 
792
  public final /*@pure@*/ Instances relationalValue(Attribute att) {
 
793
 
 
794
    int attIndex = att.index();
 
795
    if (att.isRelationValued()) {
 
796
      return att.relation((int) value(attIndex));
 
797
    } else {
 
798
      throw new IllegalArgumentException("Attribute isn't relation-valued!");
 
799
    }
 
800
  }
 
801
 
 
802
  /** 
 
803
   * Returns the value of a nominal, string, date, or relational attribute
 
804
   * for the instance as a string.
 
805
   *
 
806
   * @param attIndex the attribute's index
 
807
   * @return the value as a string
 
808
   * @throws IllegalArgumentException if the attribute is not a nominal,
 
809
   * string, date, or relation-valued attribute.
 
810
   * @throws UnassignedDatasetException if the instance doesn't belong
 
811
   * to a dataset.
 
812
   */
 
813
  //@ requires m_Dataset != null;
 
814
  public final /*@pure@*/ String stringValue(int attIndex) {
 
815
 
 
816
    if (m_Dataset == null) {
 
817
      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
 
818
    } 
 
819
    return stringValue(m_Dataset.attribute(attIndex));
 
820
  }
 
821
 
 
822
 
 
823
  /** 
 
824
   * Returns the value of a nominal, string, date, or relational attribute
 
825
   * for the instance as a string.
 
826
   *
 
827
   * @param att the attribute
 
828
   * @return the value as a string
 
829
   * @throws IllegalArgumentException if the attribute is not a nominal,
 
830
   * string, date, or relation-valued attribute.
 
831
   * @throws UnassignedDatasetException if the instance doesn't belong
 
832
   * to a dataset.
 
833
   */
 
834
  public final /*@pure@*/ String stringValue(Attribute att) {
 
835
 
 
836
    int attIndex = att.index();
 
837
    switch (att.type()) {
 
838
    case Attribute.NOMINAL:
 
839
    case Attribute.STRING:
 
840
      return att.value((int) value(attIndex));
 
841
    case Attribute.DATE:
 
842
      return att.formatDate(value(attIndex));
 
843
    case Attribute.RELATIONAL:
 
844
      return att.relation((int) value(attIndex)).stringWithoutHeader();
 
845
    default:
 
846
      throw new IllegalArgumentException("Attribute isn't nominal, string or date!");
 
847
    }
 
848
  }
 
849
 
 
850
  /**
 
851
   * Returns the values of each attribute as an array of doubles.
 
852
   *
 
853
   * @return an array containing all the instance attribute values
 
854
   */
 
855
  public double[] toDoubleArray() {
 
856
 
 
857
    double[] newValues = new double[m_AttValues.length];
 
858
    System.arraycopy(m_AttValues, 0, newValues, 0, 
 
859
                     m_AttValues.length);
 
860
    return newValues;
 
861
  }
 
862
 
 
863
  /**
 
864
   * Returns the description of one instance. If the instance
 
865
   * doesn't have access to a dataset, it returns the internal
 
866
   * floating-point values. Quotes string
 
867
   * values that contain whitespace characters.
 
868
   *
 
869
   * @return the instance's description as a string
 
870
   */
 
871
  public String toString() {
 
872
 
 
873
    StringBuffer text = new StringBuffer();
 
874
    
 
875
    for (int i = 0; i < m_AttValues.length; i++) {
 
876
      if (i > 0) text.append(",");
 
877
      text.append(toString(i));
 
878
    }
 
879
 
 
880
    return text.toString();
 
881
  }
 
882
 
 
883
  /**
 
884
   * Returns the description of one value of the instance as a 
 
885
   * string. If the instance doesn't have access to a dataset, it 
 
886
   * returns the internal floating-point value. Quotes string
 
887
   * values that contain whitespace characters, or if they
 
888
   * are a question mark.
 
889
   *
 
890
   * @param attIndex the attribute's index
 
891
   * @return the value's description as a string
 
892
   */
 
893
  public final /*@pure@*/ String toString(int attIndex) {
 
894
 
 
895
   StringBuffer text = new StringBuffer();
 
896
   
 
897
   if (isMissing(attIndex)) {
 
898
     text.append("?");
 
899
   } else {
 
900
     if (m_Dataset == null) {
 
901
       text.append(Utils.doubleToString(m_AttValues[attIndex],6));
 
902
     } else {
 
903
       switch (m_Dataset.attribute(attIndex).type()) {
 
904
       case Attribute.NOMINAL:
 
905
       case Attribute.STRING:
 
906
       case Attribute.DATE:
 
907
       case Attribute.RELATIONAL:
 
908
         text.append(Utils.quote(stringValue(attIndex)));
 
909
         break;
 
910
       case Attribute.NUMERIC:
 
911
         text.append(Utils.doubleToString(value(attIndex),6));
 
912
         break;
 
913
       default:
 
914
         throw new IllegalStateException("Unknown attribute type");
 
915
       }
 
916
     }
 
917
   }
 
918
   return text.toString();
 
919
  }
 
920
 
 
921
  /**
 
922
   * Returns the description of one value of the instance as a 
 
923
   * string. If the instance doesn't have access to a dataset it 
 
924
   * returns the internal floating-point value. Quotes string
 
925
   * values that contain whitespace characters, or if they
 
926
   * are a question mark.
 
927
   * The given attribute has to belong to a dataset.
 
928
   *
 
929
   * @param att the attribute
 
930
   * @return the value's description as a string
 
931
   */
 
932
  public final String toString(Attribute att) {
 
933
   
 
934
   return toString(att.index());
 
935
  }
 
936
 
 
937
  /**
 
938
   * Returns an instance's attribute value in internal format.
 
939
   *
 
940
   * @param attIndex the attribute's index
 
941
   * @return the specified value as a double (If the corresponding
 
942
   * attribute is nominal (or a string) then it returns the value's index as a 
 
943
   * double).
 
944
   */
 
945
  public /*@pure@*/ double value(int attIndex) {
 
946
 
 
947
    return m_AttValues[attIndex];
 
948
  }
 
949
 
 
950
  /**
 
951
   * Returns an instance's attribute value in internal format.
 
952
   * Does exactly the same thing as value() if applied to an Instance.
 
953
   *
 
954
   * @param indexOfIndex the index of the attribute's index
 
955
   * @return the specified value as a double (If the corresponding
 
956
   * attribute is nominal (or a string) then it returns the value's index as a 
 
957
   * double).
 
958
   */
 
959
  public /*@pure@*/ double valueSparse(int indexOfIndex) {
 
960
 
 
961
    return m_AttValues[indexOfIndex];
 
962
  }  
 
963
 
 
964
  /**
 
965
   * Returns an instance's attribute value in internal format.
 
966
   * The given attribute has to belong to a dataset.
 
967
   *
 
968
   * @param att the attribute
 
969
   * @return the specified value as a double (If the corresponding
 
970
   * attribute is nominal (or a string) then it returns the value's index as a
 
971
   * double).
 
972
   */
 
973
  public /*@pure@*/ double value(Attribute att) {
 
974
 
 
975
    return value(att.index());
 
976
  }
 
977
 
 
978
  /**
 
979
   * Returns the instance's weight.
 
980
   *
 
981
   * @return the instance's weight as a double
 
982
   */
 
983
  public final /*@pure@*/ double weight() {
 
984
 
 
985
    return m_Weight;
 
986
  }
 
987
 
 
988
  /**
 
989
   * Deletes an attribute at the given position (0 to 
 
990
   * numAttributes() - 1).
 
991
   *
 
992
   * @param position the attribute's position
 
993
   */
 
994
  void forceDeleteAttributeAt(int position) {
 
995
 
 
996
    double[] newValues = new double[m_AttValues.length - 1];
 
997
 
 
998
    System.arraycopy(m_AttValues, 0, newValues, 0, position);
 
999
    if (position < m_AttValues.length - 1) {
 
1000
      System.arraycopy(m_AttValues, position + 1, 
 
1001
                       newValues, position, 
 
1002
                       m_AttValues.length - (position + 1));
 
1003
    }
 
1004
    m_AttValues = newValues;
 
1005
  }
 
1006
 
 
1007
  /**
 
1008
   * Inserts an attribute at the given position
 
1009
   * (0 to numAttributes()) and sets its value to be missing. 
 
1010
   *
 
1011
   * @param position the attribute's position
 
1012
   */
 
1013
  void forceInsertAttributeAt(int position)  {
 
1014
 
 
1015
    double[] newValues = new double[m_AttValues.length + 1];
 
1016
 
 
1017
    System.arraycopy(m_AttValues, 0, newValues, 0, position);
 
1018
    newValues[position] = MISSING_VALUE;
 
1019
    System.arraycopy(m_AttValues, position, newValues, 
 
1020
                     position + 1, m_AttValues.length - position);
 
1021
    m_AttValues = newValues;
 
1022
  }
 
1023
 
 
1024
  /**
 
1025
   * Private constructor for subclasses. Does nothing.
 
1026
   */
 
1027
  protected Instance() {
 
1028
  }
 
1029
 
 
1030
  /**
 
1031
   * Clones the attribute vector of the instance and
 
1032
   * overwrites it with the clone.
 
1033
   */
 
1034
  private void freshAttributeVector() {
 
1035
 
 
1036
    m_AttValues = toDoubleArray();
 
1037
  }
 
1038
 
 
1039
  /**
 
1040
   * Main method for testing this class.
 
1041
   * 
 
1042
   * @param options the commandline options - ignored
 
1043
   */
 
1044
  //@ requires options != null;
 
1045
  public static void main(String[] options) {
 
1046
 
 
1047
    try {
 
1048
 
 
1049
      // Create numeric attributes "length" and "weight"
 
1050
      Attribute length = new Attribute("length");
 
1051
      Attribute weight = new Attribute("weight");
 
1052
      
 
1053
      // Create vector to hold nominal values "first", "second", "third" 
 
1054
      FastVector my_nominal_values = new FastVector(3); 
 
1055
      my_nominal_values.addElement("first"); 
 
1056
      my_nominal_values.addElement("second"); 
 
1057
      my_nominal_values.addElement("third"); 
 
1058
      
 
1059
      // Create nominal attribute "position" 
 
1060
      Attribute position = new Attribute("position", my_nominal_values);
 
1061
      
 
1062
      // Create vector of the above attributes 
 
1063
      FastVector attributes = new FastVector(3);
 
1064
      attributes.addElement(length);
 
1065
      attributes.addElement(weight);
 
1066
      attributes.addElement(position);
 
1067
      
 
1068
      // Create the empty dataset "race" with above attributes
 
1069
      Instances race = new Instances("race", attributes, 0);
 
1070
      
 
1071
      // Make position the class attribute
 
1072
      race.setClassIndex(position.index());
 
1073
      
 
1074
      // Create empty instance with three attribute values
 
1075
      Instance inst = new Instance(3);
 
1076
      
 
1077
      // Set instance's values for the attributes "length", "weight", and "position"
 
1078
      inst.setValue(length, 5.3);
 
1079
      inst.setValue(weight, 300);
 
1080
      inst.setValue(position, "first");
 
1081
      
 
1082
      // Set instance's dataset to be the dataset "race"
 
1083
      inst.setDataset(race);
 
1084
      
 
1085
      // Print the instance
 
1086
      System.out.println("The instance: " + inst);
 
1087
      
 
1088
      // Print the first attribute
 
1089
      System.out.println("First attribute: " + inst.attribute(0));
 
1090
      
 
1091
      // Print the class attribute
 
1092
      System.out.println("Class attribute: " + inst.classAttribute());
 
1093
      
 
1094
      // Print the class index
 
1095
      System.out.println("Class index: " + inst.classIndex());
 
1096
      
 
1097
      // Say if class is missing
 
1098
      System.out.println("Class is missing: " + inst.classIsMissing());
 
1099
      
 
1100
      // Print the instance's class value in internal format
 
1101
      System.out.println("Class value (internal format): " + inst.classValue());
 
1102
      
 
1103
      // Print a shallow copy of this instance
 
1104
      Instance copy = (Instance) inst.copy();
 
1105
      System.out.println("Shallow copy: " + copy);
 
1106
      
 
1107
      // Set dataset for shallow copy
 
1108
      copy.setDataset(inst.dataset());
 
1109
      System.out.println("Shallow copy with dataset set: " + copy);
 
1110
      
 
1111
      // Unset dataset for copy, delete first attribute, and insert it again
 
1112
      copy.setDataset(null);
 
1113
      copy.deleteAttributeAt(0);
 
1114
      copy.insertAttributeAt(0);
 
1115
      copy.setDataset(inst.dataset());
 
1116
      System.out.println("Copy with first attribute deleted and inserted: " + copy); 
 
1117
      
 
1118
      // Enumerate attributes (leaving out the class attribute)
 
1119
      System.out.println("Enumerating attributes (leaving out class):");
 
1120
      Enumeration enu = inst.enumerateAttributes();
 
1121
      while (enu.hasMoreElements()) {
 
1122
        Attribute att = (Attribute) enu.nextElement();
 
1123
        System.out.println(att);
 
1124
      }
 
1125
      
 
1126
      // Headers are equivalent?
 
1127
      System.out.println("Header of original and copy equivalent: " +
 
1128
                         inst.equalHeaders(copy));
 
1129
 
 
1130
      // Test for missing values
 
1131
      System.out.println("Length of copy missing: " + copy.isMissing(length));
 
1132
      System.out.println("Weight of copy missing: " + copy.isMissing(weight.index()));
 
1133
      System.out.println("Length of copy missing: " + 
 
1134
                         Instance.isMissingValue(copy.value(length)));
 
1135
      System.out.println("Missing value coded as: " + Instance.missingValue());
 
1136
 
 
1137
      // Prints number of attributes and classes
 
1138
      System.out.println("Number of attributes: " + copy.numAttributes());
 
1139
      System.out.println("Number of classes: " + copy.numClasses());
 
1140
 
 
1141
      // Replace missing values
 
1142
      double[] meansAndModes = {2, 3, 0};
 
1143
      copy.replaceMissingValues(meansAndModes);
 
1144
      System.out.println("Copy with missing value replaced: " + copy);
 
1145
 
 
1146
      // Setting and getting values and weights
 
1147
      copy.setClassMissing();
 
1148
      System.out.println("Copy with missing class: " + copy);
 
1149
      copy.setClassValue(0);
 
1150
      System.out.println("Copy with class value set to first value: " + copy);
 
1151
      copy.setClassValue("third");
 
1152
      System.out.println("Copy with class value set to \"third\": " + copy);
 
1153
      copy.setMissing(1);
 
1154
      System.out.println("Copy with second attribute set to be missing: " + copy);
 
1155
      copy.setMissing(length);
 
1156
      System.out.println("Copy with length set to be missing: " + copy);
 
1157
      copy.setValue(0, 0);
 
1158
      System.out.println("Copy with first attribute set to 0: " + copy);
 
1159
      copy.setValue(weight, 1);
 
1160
      System.out.println("Copy with weight attribute set to 1: " + copy);
 
1161
      copy.setValue(position, "second");
 
1162
      System.out.println("Copy with position set to \"second\": " + copy);
 
1163
      copy.setValue(2, "first");
 
1164
      System.out.println("Copy with last attribute set to \"first\": " + copy);
 
1165
      System.out.println("Current weight of instance copy: " + copy.weight());
 
1166
      copy.setWeight(2);
 
1167
      System.out.println("Current weight of instance copy (set to 2): " + copy.weight());
 
1168
      System.out.println("Last value of copy: " + copy.toString(2));
 
1169
      System.out.println("Value of position for copy: " + copy.toString(position));
 
1170
      System.out.println("Last value of copy (internal format): " + copy.value(2));
 
1171
      System.out.println("Value of position for copy (internal format): " + 
 
1172
                         copy.value(position));
 
1173
    } catch (Exception e) {
 
1174
      e.printStackTrace();
 
1175
    }
 
1176
  }
 
1177
}