Feature Selection Toolbox FST4
UTIA · Czech Academy of Sciences
Loading...
Searching...
No Matches
data_file_ARFF.hpp
Go to the documentation of this file.
1#ifndef FSTDATAFILEARFF_H
2#define FSTDATAFILEARFF_H
3 /*
30=========================================================================
31Copyright and license:
32 * FST4 software (with the exception of any bundled or externally linked
33 third-party components) is Copyright (C) 2000-present Institute of
34 Information Theory and Automation of the Czech Academy of Sciences (UTIA).
35 * FST4 is free software: you can redistribute it and/or modify it under
36 the terms of the GNU Affero General Public License as published by the
37 Free Software Foundation, version 3. The full text of the license is in
38 the file LICENSE in the distribution root and at
39 https://www.gnu.org/licenses/agpl-3.0.html.
40 * FST4 is distributed in the hope that it will be useful, but WITHOUT ANY
41 WARRANTY; without even the implied warranty of MERCHANTABILITY or
42 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
43 License for more details.
44 * Closed-source use without the AGPL's copyleft obligations requires a
45 commercial license from UTIA; in case of interest write to
46 utia@utia.cas.cz. LICENSING.md in the distribution root explains both
47 options, the contributor license agreement that every contribution
48 requires, and the contacts (technical questions and pull requests:
49 somol@utia.cas.cz, with "FST" in the subject line).
50========================================================================== */
51
52#include <cstdio>
53#include <cstring>
54#include <cctype>
55#include <cstdlib>
56#include <vector>
57#include <iostream>
58#include "error.hpp"
59#include "global.hpp"
60
61namespace FST {
62
64
65
68 public:
69 static const int TYPE_NUMERIC = 1;
70 static const int TYPE_NOMINAL = 2;
71 static const int TYPE_STRING = 3;
72 static const int TYPE_UNSUPPORTED = 4;
73
74 std::string name;
75 std::string typeName;
76 int type;
77 int offset;
78 int size;
79 bool isClass;
80 std::vector<std::string> values;
81 };
82
85 void *data;
86 int classId;
87
88 public:
89 Data_File_ARFF_Record(int recordSize) {this->data = malloc(recordSize); classId = -1;}
91
92 void *getData() { return this->data;}
93 int getClassId() { return this->classId;}
94 void setClassId(int pId) {this->classId = pId;}
95 };
96
97 inline Data_File_ARFF_Record::~Data_File_ARFF_Record() {
98 if (this->data != nullptr) free(this->data);
99 this->data = nullptr;
100 }
101
102
103
105
136 private:
137 std::string _fileName;
138 std::vector<Data_File_ARFF_Record*> data;
139 std::vector<Data_File_ARFF_Feature*> attributes;
140 std::vector<Data_File_ARFF_Feature*> features;
141 // graceful degradation over unsupported column types: columnMap has one entry per
142 // @ATTRIBUTE line in file order — the index into `attributes` for loaded columns,
143 // -1 for skipped ones. Row parsers walk file columns through this map, so a
144 // STRING/DATE/unknown-typed column does not abort the load; each skip is reported
145 // loudly and the load summary states that feature indices follow the REMAINING
146 // columns in file order.
149 std::string name;
150 std::string typeName;
152 };
153 std::vector<SkippedColumn> skippedColumns;
154 std::vector<int> columnMap;
156
157 std::string relationName;
161
163 bool loaded;
164 public:
165 Data_File_ARFF(std::string fileName);
167
173 bool prepareFile(); // prepares the file contents
174
177 void sortRecordsByClass();
178
182 unsigned int getNoOfClasses(); // resturn number of classes
183 unsigned int getNoOfFeatures() {return features.size();}
184 unsigned int getNoOfAttributes() {return attributes.size();}
187 unsigned int getTotalSize(); // returns the total number of records
191 unsigned int getClassSize(int clsId); // returns number of records for given class
195 std::string getClassName(int clsId); // returns the nam of given class
196
197 Data_File_ARFF_Record* getRecordAt(long i) {if (i<0 || i>= (long)data.size()) return nullptr; else return data[i];}
198 // returns the value of given feature of given record
203 float getFeatureValue(long record, int feature) {
204 char *v = ((char *)(data[record]->getData()))+features[feature]->offset;
205 if (features[feature]->type == Data_File_ARFF_Feature::TYPE_NOMINAL) return (float)(*(short *)v); // nominal values are stored as short (see readAttrValue)
206 return *(float *)v;
207 };
208
209 void printInfo();
210 private:
214 bool readNextRow(char *row);
216 void prepareAttributes();
225 bool readAttrValue(Data_File_ARFF_Feature *feature, Data_File_ARFF_Record *rec, char *value);
226
231 bool readLine( FILE *f, std::vector<char> &buff ) {
232 size_t len = 0; buff[0] = 0;
233 while (fgets(buff.data()+len, (int)(buff.size()-len), f) != nullptr) {
234 len += strlen(buff.data()+len);
235 if ((len > 0 && buff[len-1] == '\n') || feof(f)) return true;
236 if (len >= buff.size()-2) buff.resize(2*buff.size());
237 }
238 return len > 0;
239 };
240
242 char *trim( char *szSource ) {
243 char *pszEOS = szSource + strlen( szSource ) - 1;
244 while( pszEOS >= szSource && (*pszEOS == ' ' || *pszEOS == 9 || *pszEOS == 13 || *pszEOS == 10)) *pszEOS-- = '\0';
245 pszEOS = szSource;
246 while( *pszEOS == ' ' || *pszEOS == 9 || *pszEOS == 13 || *pszEOS == 10) pszEOS++;
247 return pszEOS;
248 };
249
251 char *mystrupr( char *szSource ) {
252 char *pszEOS = szSource;
253 while( *pszEOS != 0 ) {*pszEOS=toupper(*pszEOS); pszEOS++;}
254 return szSource;
255 };
256 };
257
258
259 inline Data_File_ARFF::Data_File_ARFF(std::string fileName) {
260 this->_fileName = fileName;
261 this->classSize = nullptr;
262 attributesCount = 0;
263 classAttribute = -1;
264 classCount = -1;
265 loaded = false;
266 };
267
268 inline Data_File_ARFF::~Data_File_ARFF() {
269 for (unsigned i=0;i<attributes.size(); i++) delete attributes[i];
270 this->attributes.clear();
271 this->features.clear();
272 for (unsigned i=0;i<data.size(); i++) delete data[i];
273 this->data.clear();
274 if (classSize != nullptr) delete[] classSize;
275 classSize = nullptr;
276 }
277
279 FILE *f =fopen(_fileName.c_str(),"rt");
280 if(f==nullptr) {throw FST::fst_error("Data_File_ARFF file read problem.",1);}
281 std::vector<char> buff(8192); // grown by readLine() as needed — no line-length cap
282
283 bool readingData = false;
284 bool isError = false;
285 int rowsReaded = 0;
286
287 while (!isError && readLine(f, buff)) {
288 // NOTE: trim() right-trims in place but LEFT-trims only through its return value,
289 // so the result must be used — reading buff.data() instead would leave an indented
290 // @DATA/@ATTRIBUTE line unrecognized
291 char *line = trim(buff.data());
292
293 if (!line[0]) continue; // empty row
294 if (line[0]=='%') continue; // comment
295 if (readingData) {
296 if (readNextRow(line)) rowsReaded++;
297 else isError = true;
298 } else if (line[0]=='@') {
299 // get the second part of string
300 char *val = line+2; while(*val!=' ' && *val!=0 && *val!=9) val++; val[0] = 0; val++;
301 trim(mystrupr(line));
302
303 if (strcmp(line, "@RELATION")==0) this->relationName = val;
304 else if (strcmp(line, "@DATA")==0) {
305 readingData = true;
307 } else if (strcmp(line, "@ATTRIBUTE")==0) {
308 Data_File_ARFF_Feature *feature = this->createAttribute(val);
309 if (feature == nullptr) { // malformed definition — a damaged header stays fatal
310 std::cout << "Attribute description not understood : " << line << " " << val << std::endl;
311 isError = true; break;
312 } else if (feature->type == Data_File_ARFF_Feature::TYPE_STRING ||
314 // unsupported type: skip the COLUMN, keep loading everything else
315 const int fileColumn = (int)columnMap.size();
316 std::cout << "Skipping attribute '" << feature->name.c_str() << "' (file column "
317 << fileColumn+1 << "): unsupported type " << feature->typeName.c_str()
318 << " - FST4 features are numeric/nominal" << std::endl;
319 skippedColumns.push_back(SkippedColumn{feature->name, feature->typeName, fileColumn});
320 columnMap.push_back(-1);
321 delete feature;
322 } else { // loadable feature
323 columnMap.push_back((int)attributes.size());
324 this->attributes.push_back(feature);
325 this->attributesCount ++;
326 }
327 }
328 } else {
329 // a line outside the header that is neither a comment nor data: reported,
330 // but tolerated — the load continues with the next line
331 if (line[0] != 0) {
332 std::cout << "Error reading file - unexpected row : " << line << std::endl;
333 }
334 }
335
336 }
337
338 fclose(f);
339
340 // graceful degradation ends where nothing usable remains
341 if (!isError && !skippedColumns.empty() && attributes.empty()) {
342 std::cout << "No loadable attribute columns remain (all " << columnMap.size()
343 << " have unsupported types)" << std::endl;
344 throw FST::fst_error("Data_File_ARFF: no loadable attributes (all column types unsupported).",1);
345 }
346
347 loaded = !isError;
348 if (!loaded) return false; // the offending definition/row was reported above; the summary
349 // below reads through getters that refuse an unloaded file
350 std::cout << "Relation: " << this->relationName.c_str() << std::endl;
351 std::cout << "Classes count: " << getNoOfClasses() << std::endl;
352 std::cout << "Records count: " << rowsReaded << std::endl;
353 if (!skippedColumns.empty()) {
354 std::cout << "Skipped " << skippedColumns.size() << " of " << columnMap.size()
355 << " attribute columns (unsupported types, reported above); loaded feature"
356 << " indices follow the remaining columns in file order" << std::endl;
357 }
358
359 return !isError;
360 }
361
363 if (!loaded) {std::cout << "File not loaded" << std::endl; return;};
365 for (unsigned d=0; d < data.size(); d++) {
366 char *dt = (char *)data[d]->getData();
367 std::cout << "Record: cls=" << data[d]->getClassId() << " " ;
368 for (unsigned i=0; i < attributes.size(); i++) {
369 char *v = dt + attributes[i]->offset;
371 std::cout << " " << *(short *)v;
373 std::cout << " " << *(float*)v;
374 }
375 std::cout << std::endl;
376 }
377
378 std::cout << "Relation: " << this->relationName.c_str() << std::endl;
379 std::cout << "Feature count: " << this->attributes.size() << std::endl;
380
381 for (unsigned i=0; i < attributes.size(); i++) {
382 std::cout << " " << attributes[i]->name.c_str() << " : " << attributes[i]->type << std::endl;
384 std::vector<std::string> vals = attributes[i]->values;
385 for (unsigned j=0; j < vals.size(); j++)
386 std::cout << " - " << vals[j].c_str() << std::endl;
387 }
388 }
389
390 std::cout << "Classes count: " << getNoOfClasses() << " sizes: ";
391 for (unsigned int i=0; i<getNoOfClasses() ; i++)
392 std::cout << getClassName(i).c_str() << ": " << getClassSize(i) << " ";
393 std::cout << std::endl;
394
395
396 std::cout << "Records count: " << data.size() << std::endl;
397
398 }
399
401 int size = 0;
402 this->classAttribute = -1;
403
404 for (unsigned fi = 0; fi < attributes.size(); fi ++ ) {
405 Data_File_ARFF_Feature *feature = attributes[fi];
406 feature->offset = size;
407 size += feature->size;
408
409 std::vector<char> tmp(feature->name.c_str(), feature->name.c_str()+feature->name.length()+1); // no VLA: MSVC hard error C2131
410 mystrupr(tmp.data());
411 if ((strcmp(tmp.data(), "CLASS")==0 || strcmp(tmp.data(), "'CLASS'")==0) && feature->type==Data_File_ARFF_Feature::TYPE_NOMINAL) {
412 this->classAttribute = fi;
413 feature->isClass = true;
414 } else {
415 feature->isClass = false;
416 features.push_back(feature);
417 }
418 }
419
420 if (classAttribute>=0) {
421 classCount = attributes[classAttribute]->values.size();
422 classSize = new int[classCount];
423 for (int i=0;i<classCount;i++) classSize[i] = 0;
424 std::cout << "Classes count : " << classCount << std::endl;
425 }
426 this->recordSize = size;
427 }
428
430 info = trim(info);
431 if (*info == 0) {std::cout << "empty definition!" << std::endl;return nullptr;}
432
433 // get the second part: the name ends at the first blank -- unless it is quoted ('my attr'
434 // or "my attr", which is how Weka writes names containing blanks), in which case it ends
435 // at the closing quote and the quotes are not part of the name
436 char *val;
437 if (*info == '\'' || *info == '"') {
438 const char qc = *info; info++;
439 val = info; while (*val != qc && *val != 0) val++;
440 if (*val == 0) {std::cout << "syntax error (unterminated quoted attribute name)! - " << info << std::endl; return nullptr;}
441 *val = 0; val++;
442 } else {
443 val = info+1; while(*val!=' ' && *val!=0 && *val!=9) val++;
444 if (*val) {*val = 0; val++;}
445 }
446 val = trim(val);
447 // info => name
448 // val => type
449
450 int type = 0;
451 int size = 0;
452
453 Data_File_ARFF_Feature *feature = nullptr;
454
455 if (val[0]==0) {std::cout << "empty datatype!" << std::endl;return nullptr;}
456 if (val[0]=='{') {
457 val++;
458 char *p = val;
459 std::vector<std::string> values;
460 while (*val != '}' && *val !=0) {
461 if (*val == ',') {
462 *val = 0;
463 std::vector<char> tmp(p, p+strlen(p)+1); // no VLA: MSVC hard error C2131
464 values.push_back((std::string)trim(tmp.data()));
465 p = ++val;
466 }
467 val++;
468 }
469 if (*val == 0) {std::cout << "syntax error! - " << info << std::endl;return nullptr;}
470 *val = 0;
471 std::vector<char> tmp(p, p+strlen(p)+1); // no VLA: MSVC hard error C2131
472 values.push_back((std::string)trim(tmp.data()));
473
474 feature = new Data_File_ARFF_Feature();
475 feature->name = info;
476 feature->size = sizeof(short); // short
478 feature->values = values;
479
480 } else {
481 val = mystrupr(val);
482 if (strcmp(val, "REAL")==0 || strcmp(val, "NUMERIC")==0 || strcmp(val, "INTEGER")==0) {
484 size = sizeof(float);
485 } else if (strcmp(val, "STRING")==0) {
486 // an unsupported-type MARKER, not a loadable feature: FST4 has no way to turn
487 // free text into a numeric feature, so the caller skips the whole column
489 size = 0;
490 } else {
491 // unknown/unsupported type (DATE, RELATIONAL, typos...) — marker, same contract
493 size = 0;
494 }
495 feature = new Data_File_ARFF_Feature();
496 feature->name = info;
497 feature->typeName = val;
498 feature->size = size;
499 feature->type = type;
500 }
501 return feature;
502 }
503
504 inline bool Data_File_ARFF::readNextRow(char *row) {
505 if (! *row) return false; // empty row;
506 row = trim(row);
507 Data_File_ARFF_Record *rec = nullptr;
508 if (*row == '{') {
509 rec = this->readSparseRow(row);
510 } else {
511 rec = this->readNormalRow(row);
512 }
513
514 if (rec == nullptr) return false;
515
516 if (classSize != nullptr && rec->getClassId()>=0) classSize[rec->getClassId()] ++;
517 this->data.push_back(rec);
518 return true;
519 }
520
522 // p points to single value for my feature
523 char *fdata = (char *)rec->getData()+feature->offset;
525 if (sscanf(value, "%f", (float *)fdata)!=1) {
526 std::cout << "Error reading feature data - feature " << feature->name << ":"<< value << std::endl;return false;
527 }
528 if (feature->isClass) rec->setClassId((int)*((float*)fdata)); // slot holds a float (see sscanf above)
529 } else if (feature->type == Data_File_ARFF_Feature::TYPE_NOMINAL) {
530 std::vector<std::string> vals = feature->values;
531 int val = -1;
532 for (unsigned j=0; j < vals.size(); j++)
533 if (vals[j].compare(value)==0) {val = j; break;};
534 if (val == -1) {
535 std::cout << "Nominal value not found - " << feature->name.c_str() << " " << value << std::endl; return false;
536 };
537 *(short *)(fdata) = (short)val;
538
539 if (feature->isClass) rec->setClassId(val);
540 } else {
541 std::cout << "Unknown attribute type - " << feature->name.c_str() << feature->type << std::endl; return false;
542 }
543 return true;
544 }
545
548 bool ok = true;
549
550 // iterate FILE columns; columnMap routes each token to its loaded
551 // attribute or discards it (skipped unsupported column)
552 for (unsigned ci = 0; ok && ci < columnMap.size(); ci ++ ) {
553 if (*row == 0) { // problem, row ended to soon
554 std::cout << "Error reading data record - column " << ci << std::endl; ok = false; break;
555 }
556 // quote-aware token scan: honor a leading ' or " so commas embedded in
557 // quoted values (typical for skipped STRING columns) don't split the token
558 char *p = row;
559 char *q = row; while (*q == ' ' || *q == 9) q++;
560 if (*q == '\'' || *q == '"') {const char qc = *q; q++; while (*q != 0 && *q != qc) q++; if (*q) q++; row = q;}
561 while (*row != 0 && *row != ',') row++;
562 char tmpch = *row; *row = 0;
563
564 const int ai = columnMap[ci];
565 if (ai >= 0) {
566 // tokens must be trimmed before nominal lookup — a space after a comma
567 // would otherwise fail the exact string compare against the declared values
568 char *tok = trim(p);
569 // a value may be single- or double-quoted (Weka quotes nominal values freely,
570 // and quoted numbers occur too): hand readAttrValue() the bare content
571 { const size_t L = strlen(tok); if (L >= 2 && (tok[0] == '\'' || tok[0] == '"') && tok[L-1] == tok[0]) {tok[L-1] = 0; tok = trim(tok+1);} }
572 ok = ok && this->readAttrValue(attributes[ai], rec, tok);
573 } // ai<0: unsupported column — token consumed and discarded
574
575 *row = tmpch;
576 if (*row == ',') row++;
577 }
578
579 if (! ok ) {delete rec; return nullptr;};
580 return rec;
581 }
582
584
586 void *data = rec->getData();
587
588 memset(data, 0, recordSize);
589 bool ok = true;
590
591 char *id;
592 char *val;
593 int attID = 0;
594
595 row++;
596 while (*row != 0 && *row != '}' && ok) {
597 // skip initial spaces
598 while (*row == 9 || *row == ' ') row++;
599 // start reading attrnum
600 id = row;
601 while (*row != 9 && *row != ' ' && *row!=0) row++;
602 if (*row == 0) {ok= false; break;}; // line can't end here
603 *row = 0; row++;
604 // => id contains attr id
605
606 // skip spaces
607 while (*row == 9 || *row == ' ') row++;
608 val = row;
609 if (*row == '"' || *row == '\'') { // value is in commas
610 row++;
611 while (*row != 0 && *row != *val) row++; // scan to the matching closing quote (*val is the opening one)
612 if (*row == 0) {ok= false; break;}; // line can't end here
613
614 *row = 0; val++; row++;
615 while (*row == 9 || *row == ' ' || *row == ',') row++;
616 } else {
617 while (*row != ',' && *row != '}' && *row != 0) row++;
618 if (*row == 0) {ok= false; break;}; // line can't end here
619 if (*row == '}') {*row=0; row++; *row = '}';}
620 else {*row = 0; row++;};
621 val = trim(val);
622 }
623 // => val contains attr value
624 // row contains either ',' or '}'
625
626 attID = atoi(id); // a FILE column index — remap through columnMap
627 if (attID<0 || attID >= (int)columnMap.size()) {
628 std::cout << "Invalid attribute index - " << attID << std::endl; ok = false; break;
629 }
630
631 const int ai = columnMap[attID];
632 if (ai >= 0) {
633 ok = ok && readAttrValue(attributes[ai], rec, val);
634 } // ai<0: unsupported column — value ignored (reported once at header time)
635
636 while (*row == 9 || *row == ' ') row++;
637 }
638
639 if (!ok) {delete rec; return nullptr;}
640
641 // in sparse format an omitted attribute means value 0; if the class attribute
642 // was omitted the record belongs to class 0 (its data slot is already zeroed
643 // by the memset above)
644 if (classAttribute >= 0 && rec->getClassId() == -1) rec->setClassId(0);
645
646 return rec;
647 }
648
649 inline unsigned int Data_File_ARFF::getNoOfClasses() {
650 if (!loaded) {throw fst_error("File not loaded");};
651
652 if (classAttribute == -1) {std::cout << "class attribute not found" << std::endl; return 0;};
654 // defensive only: prepareAttributes() never assigns classAttribute to a
655 // non-nominal attribute, so this state is unreachable through load();
656 // throw rather than return -1, which would wrap to a huge unsigned value
657 throw fst_error("Class attribute is not nominal");
658 }
659 return attributes[classAttribute]->values.size();
660 }
661
662 inline unsigned int Data_File_ARFF::getTotalSize() {
663 if (!loaded) {throw fst_error("File not loaded");};
664 return data.size();
665 }
666
667 inline unsigned int Data_File_ARFF::getClassSize(int clsId) {
668 if (!loaded) {throw fst_error("File not loaded");};
669 // throw rather than return -1, which would wrap to a huge unsigned value;
670 // all in-tree callers iterate over [0,getNoOfClasses()) so never trigger this
671 if (classSize == nullptr) {throw fst_error("getClassSize: no class attribute loaded");};
672 if (clsId < 0 || clsId >= classCount) {throw fst_error("getClassSize: class id out of range");};
673 return classSize[clsId];
674 }
675
676 inline std::string Data_File_ARFF::getClassName(int clsId) {
677 if (!loaded) {throw fst_error("File not loaded");};
678 if (classSize == nullptr || clsId < 0 || clsId >= classCount) { return "-n/a-";};
679 return attributes[classAttribute]->values[clsId];
680 }
681
682
684 if (!loaded) {throw fst_error("File not loaded");};
685 if (classCount < 1) {throw fst_error("Classes not identified");};
686 std::vector<Data_File_ARFF_Record*> **clsData = new std::vector<Data_File_ARFF_Record*>*[classCount];
687
688 for (int c=0;c<classCount;c++) {
689 clsData[c]= new std::vector<Data_File_ARFF_Record*>;
690 }
691
692 for (unsigned i=0;i<data.size();i++) {
693 Data_File_ARFF_Record *rec = data[i];
694 clsData[rec->getClassId()]->push_back(rec);
695 }
696
697 data.clear();
698 for (int c=0;c<classCount;c++) {
699 std::vector<Data_File_ARFF_Record*> *v =clsData[c];
700 for (unsigned d=0;d<v->size();d++) {
701 Data_File_ARFF_Record *rec = v->at(d);
702 data.push_back(rec);
703 }
704 v->clear();
705 delete v;
706 }
707
708 delete[] clsData;
709 }
710
711}
712
713#endif
ARFF data format filter - representation of an attribute (one @ATTRIBUTE column).
Definition data_file_ARFF.hpp:67
bool isClass
true if this is the designated CLASS attribute (excluded from Data_File_ARFF::features,...
Definition data_file_ARFF.hpp:79
std::string typeName
the type text as written in the file (skip reporting)
Definition data_file_ARFF.hpp:75
int type
one of TYPE_NUMERIC/TYPE_NOMINAL/TYPE_STRING/TYPE_UNSUPPORTED
Definition data_file_ARFF.hpp:76
std::vector< std::string > values
the enumeration's value names, for TYPE_NOMINAL (empty otherwise)
Definition data_file_ARFF.hpp:80
int offset
byte offset of this feature's value within a Data_File_ARFF_Record's raw data buffer
Definition data_file_ARFF.hpp:77
static const int TYPE_UNSUPPORTED
recognized but unloadable (DATE, RELATIONAL, typos...); the column is skipped, see Data_File_ARFF::sk...
Definition data_file_ARFF.hpp:72
static const int TYPE_NOMINAL
loadable: a {v1,v2,...} enumeration, stored as a short index into values
Definition data_file_ARFF.hpp:70
int size
size in bytes of this feature's value slot (sizeof(float) or sizeof(short))
Definition data_file_ARFF.hpp:78
static const int TYPE_STRING
recognized but unloadable (ARFF STRING); the column is skipped, see Data_File_ARFF::skippedColumns
Definition data_file_ARFF.hpp:71
std::string name
attribute name, as written after @ATTRIBUTE
Definition data_file_ARFF.hpp:74
static const int TYPE_NUMERIC
loadable: a single-precision float slot
Definition data_file_ARFF.hpp:69
ARFF data format filter - representation of a record (one @DATA row).
Definition data_file_ARFF.hpp:84
Data_File_ARFF_Record(int recordSize)
allocates (uninitialized) an recordSize-byte data buffer
Definition data_file_ARFF.hpp:89
int getClassId()
this record's class index, or -1 if unset
Definition data_file_ARFF.hpp:93
void * getData()
the raw feature-value buffer (see data)
Definition data_file_ARFF.hpp:92
void setClassId(int pId)
sets this record's class index
Definition data_file_ARFF.hpp:94
void * data
raw feature-value buffer, recordSize bytes, laid out per Data_File_ARFF_Feature::offset/size (owned; ...
Definition data_file_ARFF.hpp:85
int classId
index into the class attribute's values, or -1 if not yet set
Definition data_file_ARFF.hpp:86
void sortRecordsByClass()
Reorders data in place, grouping records by class id (bucket sort over classCount buckets,...
Definition data_file_ARFF.hpp:683
std::string _fileName
input .arff file name, as passed to the constructor
Definition data_file_ARFF.hpp:137
bool readAttrValue(Data_File_ARFF_Feature *feature, Data_File_ARFF_Record *rec, char *value)
Parses value into feature's slot of rec's data buffer (float for TYPE_NUMERIC, a Data_File_ARFF_Featu...
Definition data_file_ARFF.hpp:521
unsigned int getNoOfFeatures()
number of non-class loadable features (features, i.e. attributes minus the CLASS attribute)
Definition data_file_ARFF.hpp:183
int classCount
number of classes (the CLASS attribute's value count), or -1 if classAttribute is -1
Definition data_file_ARFF.hpp:160
bool readNextRow(char *row)
Reads and stores one data row (dense or sparse, dispatched on a leading '{'); increments the row's cl...
Definition data_file_ARFF.hpp:504
std::vector< int > columnMap
one entry per @ATTRIBUTE line in file order: the index into attributes for a loaded column,...
Definition data_file_ARFF.hpp:154
Data_File_ARFF_Record * getRecordAt(long i)
the loaded record at index i, or nullptr if i is out of range
Definition data_file_ARFF.hpp:197
Data_File_ARFF_Record * readNormalRow(char *row)
Parses one dense (comma-separated) data row into a new record, walking file columns through columnMap...
Definition data_file_ARFF.hpp:546
char * trim(char *szSource)
trims a string (removes spaces, tabs, and cr / lf
Definition data_file_ARFF.hpp:242
bool prepareFile()
Reads and parses the whole .arff file: the header (@RELATION/@ATTRIBUTE lines) then every @DATA row....
Definition data_file_ARFF.hpp:278
unsigned int getNoOfAttributes()
Definition data_file_ARFF.hpp:184
std::string getClassName(int clsId)
Name (nominal value text) of class clsId.
Definition data_file_ARFF.hpp:676
Data_File_ARFF_Feature * createAttribute(char *info)
Definition data_file_ARFF.hpp:429
float getFeatureValue(long record, int feature)
The value of features[feature] in record record, read out of that record's raw data buffer.
Definition data_file_ARFF.hpp:203
int classAttribute
index into attributes of the nominal attribute named CLASS/'CLASS', or -1 if none was found
Definition data_file_ARFF.hpp:159
unsigned int getClassSize(int clsId)
Number of records belonging to class clsId.
Definition data_file_ARFF.hpp:667
bool loaded
whether prepareFile() completed without error; getters that need loaded data throw fst_error while fa...
Definition data_file_ARFF.hpp:163
Data_File_ARFF_Record * readSparseRow(char *row)
Parses one sparse ({idx value, idx value, ...}) data row into a new record (unset attributes default ...
Definition data_file_ARFF.hpp:583
char * mystrupr(char *szSource)
replaces nonstandard strupr
Definition data_file_ARFF.hpp:251
int recordSize
size in bytes of one record's raw data buffer (sum of all loaded attributes' Data_File_ARFF_Feature::...
Definition data_file_ARFF.hpp:162
std::vector< Data_File_ARFF_Feature * > features
the subset of attributes that are actual features (i.e. excluding the CLASS attribute); populated by ...
Definition data_file_ARFF.hpp:140
int * classSize
per-class record counts, indexed by class id (size classCount); owned, allocated in prepareAttributes...
Definition data_file_ARFF.hpp:155
std::vector< Data_File_ARFF_Record * > data
loaded records, owned (deleted in the destructor); reordered in place by sortRecordsByClass()
Definition data_file_ARFF.hpp:138
void printInfo()
prints a full debug dump (every record's feature values, the attribute list with nominal value tables...
Definition data_file_ARFF.hpp:362
unsigned int getNoOfClasses()
Number of classes, i.e. the CLASS attribute's value count.
Definition data_file_ARFF.hpp:649
int attributesCount
number of loaded (non-skipped) attribute columns, i.e. attributes.size()
Definition data_file_ARFF.hpp:158
std::string relationName
the @RELATION name
Definition data_file_ARFF.hpp:157
std::vector< Data_File_ARFF_Feature * > attributes
LOADED attribute columns only (unsupported types are skipped), INCLUDING the CLASS attribute if prese...
Definition data_file_ARFF.hpp:139
Data_File_ARFF(std::string fileName)
constructs an (unloaded) reader for fileName; call prepareFile() to actually read it
Definition data_file_ARFF.hpp:259
bool readLine(FILE *f, std::vector< char > &buff)
Definition data_file_ARFF.hpp:231
void prepareAttributes()
Post-@DATA setup: assigns each loaded attribute's Data_File_ARFF_Feature::offset within a record buff...
Definition data_file_ARFF.hpp:400
std::vector< SkippedColumn > skippedColumns
every column skipped due to an unsupported type, in file order; see columnMap
Definition data_file_ARFF.hpp:153
unsigned int getTotalSize()
Number of loaded records (data's size).
Definition data_file_ARFF.hpp:662
FST4 specific error passing class.
Definition error.hpp:61
FST4 specific error passing class.
Global definitions.
The Feature Selection Toolbox 4 library: every library component – data access, criteria and classifi...
Definition data_accessor.hpp:80
One @ATTRIBUTE column that was recognized but could not be loaded (STRING/DATE/unknown type),...
Definition data_file_ARFF.hpp:148
std::string name
the attribute's name
Definition data_file_ARFF.hpp:149
std::string typeName
the type text as written in the file
Definition data_file_ARFF.hpp:150
int fileColumn
0-based column index among all @ATTRIBUTE lines (not just loaded ones)
Definition data_file_ARFF.hpp:151
Copyright © 2000–present ÚTIA, Institute of Information Theory and Automation of the Czech Academy of Sciences · Contacts · This site sets no cookies and uses no analytics.