Packages

Little tool for converting JSON array or CSV to ARFF file.

Current section

Files

Jump to
arffy lib converter.ex
Raw

lib/converter.ex

defmodule Arffy.Converter do
@doc """
convert list to arrf @data, each in new line, similar to csv
"""
def convert_to_arff_data(list) do
list
|> Enum.map(fn x -> Map.values(x) |> Enum.map(fn nil -> ""; x -> x end) |> Enum.join(",") end)
|> Enum.join("\n") # convert list of maps to one large @datas tring
end
@doc """
get arff attributes based on value type from the map
"""
def convert_to_arff_attributes(elem, list) do
elem
|> Enum.map(fn {k, v} -> get_value(v, k, list) end) # get attributes string with name and type
|> Enum.join("\n")
end
defp get_value(value, key, list) do
{classes, count} = get_classes(list)
cleaned_value = String.trim(to_string(value)) # if value is numeric, convert it to string first, so parse doesn't throw an error
case Float.parse(cleaned_value) do # check if it can be a number # "@attribute attr-#{key} string"
:error ->
case check_nominal(classes, count) do # check if class is nominal
{:nominal, final} -> if value in classes, do: "@attribute attr-#{key} #{final}", else: "@attribute attr-#{key} string"
{:notnominal} -> "@attribute attr-#{key} string"
end
{_v, _c} -> case check_nominal(classes, count) do # check if class is nominal
{:nominal, final} -> if to_string(cleaned_value) in classes, do: "@attribute attr-#{key} #{final}", else: "@attribute attr-#{key} numeric"
{:notnominal} -> "@attribute attr-#{key} numeric"
end
end
end
@doc """
get list of all classes, last column values
"""
def get_classes(list) do
list
|> Enum.map(fn x -> Map.values(x) end)
|> Enum.map(fn x -> hd(Enum.reverse(x)) end)
|> Enum.filter(fn x -> x != "" end)
|> refactor_class()
end
@doc """
check if there are more than 3 unique values in classes list
"""
def check_nominal(values, count) do
if count > 3 do
{:notnominal}
else
final = Enum.join(values, ",")
{:nominal, "{#{final}}"}
end
end
defp refactor_class(list) do # return all classes and totla count
values = Enum.uniq(list)
count = Enum.count(values)
{values, count}
end
end