Packages

Sentiment analysis based on afinn-165, emojis and some enhancements.

Current section

Files

Jump to
veritaserum lib veritaserum.ex
Raw

lib/veritaserum.ex

defmodule Veritaserum do
@moduledoc """
Sentiment analisis based on AFINN-165, emojis and some enhancements.
Also supports:
- emojis (❤️, 😱...)
- boosters (*very*, *really*...)
- negators (*don't*, *not*...).
"""
@afinn_values File.read!("#{__DIR__}/../config/afinn.json")
|> Poison.Parser.parse!
@emojis File.read!("#{__DIR__}/../config/emoji.json")
|> Poison.Parser.parse!
@values Map.merge(@afinn_values, @emojis)
@negators File.read!("#{__DIR__}/../config/negators.json")
|> Poison.Parser.parse!
@boosters File.read!("#{__DIR__}/../config/boosters.json")
|> Poison.Parser.parse!
@spec analyze(List.t) :: Integer.t
def analyze(input) when is_list(input) do
input
|> Stream.map(&analyze/1)
|> Enum.to_list
end
@doc """
Returns a sentiment value for the given text
iex> Veritaserum.analyze(["I ❤️ Veritaserum", "Veritaserum is really awesome"])
[3, 5]
iex> Veritaserum.analyze("I love Veritaserum")
3
"""
@spec analyze(String.t) :: Integer.t
def analyze(input) do
input
|> clean
|> String.split
|> analyze_list()
|> Enum.reduce(0, &(&1 + &2))
end
defp analyze_list([head | tail]) do
analyze_list(tail, head, [analyze_word(head)])
end
defp analyze_list([head | tail], previous, result) do
analyze_list(tail, head, [analyze_word(head, previous) | result])
end
defp analyze_list([], _, result), do: result
defp analyze_word(word) do
case @values[word] do
nil -> 0
val -> val
end
end
defp analyze_word(word, previous) do
case @negators[previous] do
1 -> - analyze_word(word)
_ -> analyze_word_for_boosters(word, previous)
end
end
defp analyze_word_for_boosters(word, previous) do
case @boosters[previous] do
nil -> analyze_word(word)
val -> word |> analyze_word |> apply_booster(val)
end
end
defp apply_booster(word_value, booster) when word_value > 0, do: word_value + booster
defp apply_booster(word_value, booster) when word_value < 0, do: word_value - booster
defp apply_booster(word_value, _booster), do: word_value
defp clean(text) do
text
|> String.strip
|> String.replace(~r/\n/, "")
|> String.downcase
|> String.replace(~r/[.,\/#!$%\^&\*;:{}=_`\"~()]/, "")
|> String.replace(~r/ {2,}/, " ")
end
end