Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[initial] Gosentiwordnet v2 release #1

Merged
merged 5 commits into from
Oct 12, 2020
Merged
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
coverage.txt
coverage.out
coverage.html
10 changes: 10 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
language: go
go:
- 1.14.x

script:
- go test -v -coverprofile=coverage.txt -covermode=count

after_success:
- bash <(curl -s https://codecov.io/bash)
- rm -rf coverage.txt
7 changes: 7 additions & 0 deletions FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# These are supported funding model platforms

github: [dinopuguh] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
61 changes: 60 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,60 @@
go-sentiwordnet
# 💬 GoSentiwordnet

Sentiment analyzer using [sentiwordnet](https://github.com/aesuli/SentiWordNet) lexicon in Go. This library produce sentiment score for each word, including positive, negative, and objective score.

## ⚙ Installation

First of all, [download](https://golang.org/dl/) and install Go `1.14` or higher is required.

Install this library using the [`go get`](https://golang.org/cmd/go/#hdr-Add_dependencies_to_current_module_and_install_them) command:

```bash
$ go get github.com/dinopuguh/gosentiwordnet
```



## ⚡ Quickstart

```go
package main

import (
"fmt"

goswn "github.com/dinopuguh/gosentiwordnet"
)

func main() {
sa := goswn.New()

scores, exist := sa.GetSentimentScore("love", "v", "2")
if exist {
fmt.Println("💬 Sentiment score:", scores) // => 💬 Sentiment score: {1 0 0}
}
}
```

The `GetSentimentScore` required 3 parameters(word, pos-tag, and word usage):

1. **Word**: the word want to process
2. **POS tag**: part-of-speech tag of the word
3. **Word usage**: 1 for most common usage and a higher number would indicate lesser common usages



## 👍 Contributing

If you want to say **thank you** and/or support the active development of `Gosentiwordnet`:

1. Add a [GitHub Star](https://github.com/dinopuguh/gosentiwordnet/stargazers) to the project.
2. Write a review or tutorial on [Medium](https://medium.com/), [Dev.to](https://dev.to/) or personal blog.
3. Be a part of our [sponsors](https://github.com/sponsors/dinopuguh) to support this project.



## 💻 Contributors

- Dino Puguh (initial works)

Open for any pull requests to develop this project.
32 changes: 32 additions & 0 deletions example/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"fmt"

goswn "github.com/dinopuguh/gosentiwordnet"
)

// Token represent the required parameter for using gosentiwordnet
type Token struct {
Word string // the word want to process
PosTag string // part-of-speech tag of word
Usage string // word usage (1 for most common usage and a higher number would indicate lesser common usages)
}

func main() {
sa := goswn.New()

tokens := []Token{
Token{Word: "love", PosTag: "v", Usage: "2"},
Token{Word: "neat", PosTag: "a", Usage: "4"},
Token{Word: "overacting", PosTag: "n", Usage: "1"},
}

for _, token := range tokens {
scores, exist := sa.GetSentimentScore(token.Word, token.PosTag, token.Usage)
if exist {
fmt.Printf("💬 Sentiment score of %s: %v\n", token.Word, scores)
// 💬 Sentiment score: {positive_score negative_score objective_score}
}
}
}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/dinopuguh/gosentiwordnet

go 1.14

require github.com/stretchr/testify v1.6.1
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
17 changes: 10 additions & 7 deletions gosentiwordnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ import (

const sentiWordnetAssetName = "rawdata/SentiWordNet_3.0.0.txt"

// SentimentAnalyzer represent the sentiment analyzer with sentiwordnet lexicon
type SentimentAnalyzer struct {
Lexicon map[string]Sentiment
}

// Sentiment reprensent sentiment score for each word
// containing positive, negative and objective
type Sentiment struct {
Positive float64
Negative float64
Expand Down Expand Up @@ -56,13 +59,12 @@ func (sa *SentimentAnalyzer) generateLexicon() {

line++
}

if err := scanner.Err(); err != nil {
log.Fatal(err.Error())
}
}

func (sa *SentimentAnalyzer) GetSentimentScore(word string, posTag string, usage string) (bool, Sentiment) {
// GetSentimentScore count the sentiment score of word based on POS tag and the word usage.
// POS tag: part-of-speech tag of word
// Word usage: 1 for most common usage and a higher number would indicate lesser common usages
func (sa *SentimentAnalyzer) GetSentimentScore(word string, posTag string, usage string) (Sentiment, bool) {
var result Sentiment

posTag = "(" + posTag + ")"
Expand All @@ -78,10 +80,11 @@ func (sa *SentimentAnalyzer) GetSentimentScore(word string, posTag string, usage
}
}

return match, result
return result, match
}

func NewGoSentiwordnet() *SentimentAnalyzer {
// New generate the sentiment analyzer with sentiwordnet lexicon
func New() *SentimentAnalyzer {
var sa SentimentAnalyzer

sa.generateLexicon()
Expand Down
34 changes: 34 additions & 0 deletions gosentiwordnet_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package gosentiwordnet_test

import (
"testing"

"github.com/dinopuguh/gosentiwordnet"
"github.com/stretchr/testify/assert"
)

type SentimentTestCase struct {
Word string
PosTag string
Usage string
Scores gosentiwordnet.Sentiment
}

func generateTestCases() []SentimentTestCase {
return []SentimentTestCase{
SentimentTestCase{Word: "love", PosTag: "v", Usage: "2", Scores: gosentiwordnet.Sentiment{Positive: 1, Negative: 0, Objective: 0}},
SentimentTestCase{Word: "neat", PosTag: "a", Usage: "4", Scores: gosentiwordnet.Sentiment{Positive: 0.625, Negative: 0, Objective: 0.375}},
SentimentTestCase{Word: "overacting", PosTag: "n", Usage: "1", Scores: gosentiwordnet.Sentiment{Positive: 0, Negative: 0.875, Objective: 0.125}},
SentimentTestCase{Word: "finely", PosTag: "r", Usage: "2", Scores: gosentiwordnet.Sentiment{Positive: 0.625, Negative: 0, Objective: 0.375}},
}
}

func TestSentimentAnalysis(t *testing.T) {
sa := gosentiwordnet.New()
for _, testCase := range generateTestCases() {
scores, match := sa.GetSentimentScore(testCase.Word, testCase.PosTag, testCase.Usage)
if match {
assert.Equalf(t, testCase.Scores, scores, testCase.Word)
}
}
}