Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: node_js
node_js:
- 0.6
- "0.10"

branches:
only:
- master
- master
14 changes: 10 additions & 4 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# SentiMental - Putting the Mental in Sentimental

Sentiment analysis tool for node.js based on the [AFINN-111 wordlist](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6010).

Version 1.0 introduces performance improvements making it both the first, and now fastest, AFINN backed Sentiment Analysis tool for node.

## Install
$ npm install Sentimental
Expand All @@ -18,13 +20,17 @@

## Example
```js
var analyze = require('sentimental').analyze,
positivity = require('sentimental').positivity,
negativity = require('sentimental').negativity;
var analyze = require('Sentimental').analyze,
positivity = require('Sentimental').positivity,
negativity = require('Sentimental').negativity;

analyze("Hey you worthless scumbag"); //Score: -6, Comparative:-1.5
positivity("This is so cool"); //Score: 1, Comparative:.25
negativity("Hey you worthless scumbag"); //Score: 6, Comparative:1.5
analyze("I am happy"); //Score: 3, Comparative: 1
analyze("I am so happy"); //Score: 6, Comparative: 1.5
analyze("I am extremely happy"); //Score: 12, Comparative: 3
analyze("I am really sad"); //Score: -4, Comparative: -1
```


Expand Down Expand Up @@ -66,4 +72,4 @@ 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.
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ module.exports = {
analyze : analyze,
negativity : negativity,
positivity : positivity
};
};
39 changes: 39 additions & 0 deletions lib/migrate_wordList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Transforms old word list format to the new one
// -------------------------------------------------- //

var fs = require('fs');

var neg5 = require('../wordLists/neglist.js').neg5,
neg4 = require('../wordLists/neglist.js').neg4,
neg3 = require('../wordLists/neglist.js').neg3,
neg2 = require('../wordLists/neglist.js').neg2,
neg1 = require('../wordLists/neglist.js').neg1,
pos5 = require('../wordLists/poslist.js').pos5,
pos4 = require('../wordLists/poslist.js').pos4,
pos3 = require('../wordLists/poslist.js').pos3,
pos2 = require('../wordLists/poslist.js').pos2,
pos1 = require('../wordLists/poslist.js').pos1;

var afinn = require('../wordLists/afinn.json');

var result = {};
neg5.forEach(function(t) { if (!(t in afinn)) { result[t] = -5; } else { console.log('Already exist: ', t, afinn[t], -5); } });
neg4.forEach(function(t) { if (!(t in afinn)) { result[t] = -4; } else { console.log('Already exist: ', t, afinn[t], -4); } });
neg3.forEach(function(t) { if (!(t in afinn)) { result[t] = -3; } else { console.log('Already exist: ', t, afinn[t], -3); } });
neg2.forEach(function(t) { if (!(t in afinn)) { result[t] = -2; } else { console.log('Already exist: ', t, afinn[t], -2); } });
neg1.forEach(function(t) { if (!(t in afinn)) { result[t] = -1; } else { console.log('Already exist: ', t, afinn[t], -1); } });
pos1.forEach(function(t) { if (!(t in afinn)) { result[t] = 1; } else { console.log('Already exist: ', t, afinn[t], 1); } });
pos2.forEach(function(t) { if (!(t in afinn)) { result[t] = 2; } else { console.log('Already exist: ', t, afinn[t], 2); } });
pos3.forEach(function(t) { if (!(t in afinn)) { result[t] = 3; } else { console.log('Already exist: ', t, afinn[t], 3); } });
pos4.forEach(function(t) { if (!(t in afinn)) { result[t] = 4; } else { console.log('Already exist: ', t, afinn[t], 4); } });
pos5.forEach(function(t) { if (!(t in afinn)) { result[t] = 5; } else { console.log('Already exist: ', t, afinn[t], 5); } });

console.log(JSON.stringify(result));

Object.assign(afinn, result);

fs.writeFile('wordLists/afinn.json', JSON.stringify(afinn), function (err) {
if (err) {
console.log('Error: ', err);
}
});
56 changes: 18 additions & 38 deletions lib/sentimental.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,28 @@
var neg5 = require('../wordLists/neglist.js').neg5,
neg4 = require('../wordLists/neglist.js').neg4,
neg3 = require('../wordLists/neglist.js').neg3,
neg2 = require('../wordLists/neglist.js').neg2,
neg1 = require('../wordLists/neglist.js').neg1,
pos5 = require('../wordLists/poslist.js').pos5,
pos4 = require('../wordLists/poslist.js').pos4,
pos3 = require('../wordLists/poslist.js').pos3,
pos2 = require('../wordLists/poslist.js').pos2,
pos1 = require('../wordLists/poslist.js').pos1;

var afinn = require('../wordLists/afinn.json');

var tokenizeWithNoPunctuation = function (phrase) {
var noPunctuation = phrase.replace(/[^a-zA-Zа-яА-Я ]+/g, ' ').replace('/ {2,}/',' ');
return noPunctuation.toLowerCase().split(" ");
};

// Calculates the negative sentiment of a sentence
// -------------------------------------------------- //

function negativity (phrase) {
var addPush = function(t, score){
hits += score;
hits -= score;
words.push(t);
};

var noPunctuation = phrase.replace(/[^a-zA-Z ]+/g, '').replace('/ {2,}/',' '),
tokens = noPunctuation.toLowerCase().split(" "),
var tokens = tokenizeWithNoPunctuation(phrase),
hits = 0,
words = [];

tokens.forEach(function(t) {
if (neg5.indexOf(t) > -1) {
addPush(t,5);
} else if (neg4.indexOf(t) > -1) {
addPush(t,4);
} else if (neg3.indexOf(t) > -1) {
addPush(t,3);
} else if (neg2.indexOf(t) > -1) {
addPush(t,2);
} else if (neg1.indexOf(t) > -1) {
addPush(t,1);
if (afinn.hasOwnProperty(t)) {
if (afinn[t] < 0){
addPush(t, afinn[t]);
}
}
});

Expand All @@ -55,23 +42,16 @@ function positivity (phrase) {
hits += score;
words.push(t);
};

var noPunctuation = phrase.replace(/[^a-zA-Z ]+/g, '').replace('/ {2,}/',' '),
tokens = noPunctuation.toLowerCase().split(" "),

var tokens = tokenizeWithNoPunctuation(phrase),
hits = 0,
words = [];

tokens.forEach(function(t) {
if (pos5.indexOf(t) > -1) {
addPush(t,5);
} else if (pos4.indexOf(t) > -1) {
addPush(t,4);
} else if (pos3.indexOf(t) > -1) {
addPush(t,3);
} else if (pos2.indexOf(t) > -1) {
addPush(t,2);
} else if (pos1.indexOf(t) > -1) {
addPush(t,1);
if (afinn.hasOwnProperty(t)) {
if (afinn[t] > 0){
addPush(t, afinn[t]);
}
}
});

Expand Down Expand Up @@ -104,4 +84,4 @@ module.exports = {
analyze : analyze,
negativity : negativity,
positivity : positivity
};
};
11 changes: 5 additions & 6 deletions package.json
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
"name": "Sentimental",
"description": "Sentiment Analysis module",
"repository": "git://github.com/thinkroth/Sentimental",
"version": "0.0.2",
"version": "1.0.1",
"author": "Kevin M Roth",
"dependencies": {
},
"dependencies": {},
"scripts": {
"test": "make test"
},
"devDependencies": {
"mocha": "0.10.0",
"should": "0.6.0"
"mocha": "1.18.2",
"should": "3.3.0"
}
}
}
15 changes: 0 additions & 15 deletions test.js

This file was deleted.

21 changes: 20 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ describe('Negativity', function () {
done();
});
});
describe('#negativeComparative', function () {
it('should properly handle punctuation', function (done) {
negativity("I'll be here till 5").score.should.equal(0);
done();
});
});
});


Expand Down Expand Up @@ -77,6 +83,12 @@ describe('Positivity', function () {
done();
});
});
describe('#positiveComparative', function () {
it('should properly handle punctuation', function (done) {
positivity("I'll be here till 5").score.should.equal(0);
done();
});
});
});

describe('Analyze', function () {
Expand Down Expand Up @@ -110,4 +122,11 @@ describe('Analyze', function () {
done();
});
});
});
describe('Russian', function () {
it('RU1', function(done) {
analyze("Система автоопределения тональности явно недооценена").score.should.equal(-1);
analyze("Система автоопределения тональности явно недооценена").comparative.should.equal(-0.2);
done();
});
});
});
1 change: 1 addition & 0 deletions wordLists/afinn.json

Large diffs are not rendered by default.

Loading