Permalink
Browse files

Implemented the factor part.

  • Loading branch information...
0 parents commit db769e45bcf509b0e06cec234293a0e13089eadc @sethyuan committed Mar 14, 2013
Showing with 237 additions and 0 deletions.
  1. +18 −0 .gitignore
  2. +2 −0 .npmignore
  3. +19 −0 LICENSE
  4. +37 −0 README.md
  5. +50 −0 lib/xtabs.js
  6. +37 −0 package.json
  7. +2 −0 test/mocha.opts
  8. +72 −0 test/xtabs.js
@@ -0,0 +1,18 @@
+.DS_Store
+*.swp
+node_modules
+
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+
+npm-debug.log
@@ -0,0 +1,2 @@
+test/
+src/
19 LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2013 Seth Yuan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
@@ -0,0 +1,37 @@
+# xtabs
+
+A cross tabulation library for Node.js
+
+## Installation
+
+```bash
+$ npm install xtabs
+```
+
+## Example
+
+## API
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2013 Seth Yuan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
@@ -0,0 +1,50 @@
+var unique, match;
+
+unique = function(x) {
+ var set = {}, i, hasNull = false;
+ for (i = 0; i < x.length; i++) {
+ if (x[i] === null) hasNull = true;
+ else if (set[x[i]] == null) set[x[i]] = true;
+ }
+ return hasNull ? Object.keys(set).concat(null) : Object.keys(set);
+};
+
+match = function(x, table, useNull) {
+ var map = {}, res = new Array(x.length),
+ nullValue = (useNull ? table.length - 1 : null), i;
+ // Construct map.
+ for (i = 0; i < table.length; i++) {
+ if (table[i] !== null) map[table[i]] = i;
+ }
+ // Construct results.
+ for (i = 0; i < x.length; i++) {
+ res[i] = (x[i] !== null ? map[x[i]] : nullValue);
+ }
+ return res;
+};
+
+exports.factor = function(x, useNull) {
+ var f, levels;
+ levels = unique(x);
+ if (!useNull && levels[levels.length - 1] === null) levels.length--;
+ f = match(x, levels, useNull);
+ f.levels = levels;
+ return f;
+};
+
+exports.isFactor = function(o) {
+ return (Array.isArray(o) && o.levels != null);
+};
+
+exports.asString = function(f) {
+ var map = {}, i, res = new Array(f.length);
+ // Construct map.
+ for (i = 0; i < f.levels.length; i++) {
+ map[i] = f.levels[i];
+ }
+ // Construct results.
+ for (i = 0; i < f.length; i++) {
+ res[i] = (f[i] !== null ? map[f[i]] : null);
+ }
+ return res;
+};
@@ -0,0 +1,37 @@
+{
+ "name": "xtabs",
+ "version": "0.1.0",
+ "description": "A cross tabulation library for Node.js",
+ "main": "./lib/xtabs.js",
+ "scripts": {
+ "test": "mocha"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/sethyuan/xtabs.git"
+ },
+ "bugs": {
+ "url": "https://github.com/sethyuan/xtabs/issues",
+ "email": "cavingdeep@gmail.com"
+ },
+ "keywords": [
+ "cross",
+ "tabulation",
+ "statistics",
+ "xtabs",
+ "R",
+ "tab"
+ ],
+ "author": {
+ "name": "sethyuan",
+ "email": "cavingdeep@gmail.com"
+ },
+ "engines": {
+ "node": ">=0.8"
+ },
+ "license": "MIT",
+ "readmeFilename": "README.md",
+ "devDependencies": {
+ "should": "latest"
+ }
+}
@@ -0,0 +1,2 @@
+--reporter spec
+--ui bdd
@@ -0,0 +1,72 @@
+var xtabs = require("../"),
+ should = require("should");
+
+describe("xtabs", function() {
+ describe("factor", function() {
+ it("a vector (array)", function() {
+ var x = ["Male", "Female", "Female", "Female", "Male", "Female"],
+ factoredX = xtabs.factor(x);
+ factoredX.length.should.equal(x.length);
+ factoredX.slice(0, x.length).should.eql([0, 1, 1, 1, 0, 1]);
+ factoredX.levels.should.eql(["Male", "Female"]);
+ });
+
+ it("isFactor", function() {
+ var x = ["Male", "Female", "Female", "Female", "Male", "Female"],
+ factoredX = xtabs.factor(x);
+ xtabs.isFactor(factoredX).should.be.true;
+ });
+
+ it("pushing", function() {
+ var x = ["Male", "Female", "Female", "Female", "Male", "Female"],
+ factoredX = xtabs.factor(x);
+ factoredX.push(1);
+ factoredX.length.should.equal(x.length + 1);
+ factoredX[factoredX.length - 1].should.equal(1);
+ });
+
+ it("convert back to string", function() {
+ var x = ["Male", "Female", "Female", "Female", "Male", "Female"],
+ factoredX = xtabs.factor(x);
+ xtabs.asString(factoredX).should.be.eql(x);
+ });
+
+ it("with NA (aka null)", function() {
+ var x = ["Male", "Female", null, "Female", null, "Female"],
+ factoredX = xtabs.factor(x, true);
+ factoredX.levels.should.eql(["Male", "Female", null]);
+ factoredX.slice(0, x.length).should.eql([0, 1, 2, 1, 2, 1]);
+ });
+
+ it("without NA (aka null)", function() {
+ var x = ["Male", "Female", null, "Female", null, "Female"],
+ factoredX = xtabs.factor(x);
+ factoredX.levels.should.eql(["Male", "Female"]);
+ factoredX.slice(0, x.length).should.eql([0, 1, null, 1, null, 1]);
+ });
+
+ it("convert back to string with null used", function() {
+ var x = ["Male", "Female", null, "Female", null, "Female"],
+ factoredX = xtabs.factor(x, true);
+ xtabs.asString(factoredX).should.be.eql(x);
+ });
+
+ it("convert back to string with null not used", function() {
+ var x = ["Male", "Female", null, "Female", null, "Female"],
+ factoredX = xtabs.factor(x);
+ xtabs.asString(factoredX).should.be.eql(x);
+ });
+ });
+
+ it("a single factor");
+
+ it("a single vector (array)");
+
+ it("a single factor counting NA (aka null)");
+
+ it("a data frame (an object with array members)");
+
+ it("a data frame of factor members");
+
+ it("a data frame of factor members counting NA (aka null)");
+});

0 comments on commit db769e4

Please sign in to comment.