Reputation: 431
I am trying to group lists in a 2dlist based on the last element in each list in Haskell. Like this:
[[0,1],[2,2],[0,2],[1,1]]
would either become a 3d list like this:
[[[0,1],[1,1]],[[0,2],[2,2]]]
or would separate the data into n number of categories using any data structures.
Specifically, I'm trying to implement the seperateByClass Method in this tutorial http://machinelearningmastery.com/naive-bayes-classifier-scratch-python/
Upvotes: 0
Views: 164
Reputation: 67507
import Data.List(groupBy, sortBy)
import Data.Ord(compare)
groupBy (\x y -> x!!1==y!!1) $ sortBy (\x y -> compare (x!!1) (y!!1)) [[0,1],[2,2],[0,2],[1,1]]
[[[0,1],[1,1]],[[2,2],[0,2]]]
or, change the indexed access to last
groupBy (\x y -> last x==last y) $ sortBy (\x y -> compare (last x) (last y)) [[0,1],[2,2],[0,2],[1,1]]
[[[0,1],[1,1]],[[2,2],[0,2]]]
perhaps easier with some helper functions
compareLast x y = compare (last x) (last y)
equalLast x y = EQ == compareLast x y
groupBy equalLast $ sortBy compareLast [[0,1],[2,2],[0,2],[1,1]]
[[[0,1],[1,1]],[[2,2],[0,2]]]
Or, going one step further
compareBy f x y = compare (f x) (f y)
equalBy f = ((EQ ==) .) . compareBy f
partitionBy f = groupBy (equalBy f) . sortBy (compareBy f)
partitionBy last [[0,1],[2,2],[0,2],[1,1]]
[[[0,1],[1,1]],[[2,2],[0,2]]]
Upvotes: 1
Reputation: 10238
The goal is to convert
def separateByClass(dataset):
separated = {}
for i in range(len(dataset)):
vector = dataset[i]
if (vector[-1] not in separated):
separated[vector[-1]] = []
separated[vector[-1]].append(vector)
return separated
dataset = [[1,20,1], [2,21,0], [3,22,1]]
separated = separateByClass(dataset)
print('Separated instances: {0}').format(separated)
which has output
Separated instances: {0: [[2, 21, 0]], 1: [[1, 20, 1], [3, 22, 1]]}
to Haskell. This is the perfect use-case for Data.Map
's fromListWith :: Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
, which takes a list of key-value pairs and a strategy for combining values when two pairs happen to share the same key.
λ> import Data.Maybe
λ> import Data.Map
λ> let last_ = listToMaybe . reverse
λ> let pairs = [(last_ x, [x]) | x <- dataset]
λ> fromListWith (\a b -> b) pairs
fromList [(Just 0,[[2,21,0]]),(Just 1,[[1,20,1]])]
λ> fromListWith (++) pairs
fromList [(Just 0,[2,21,0]),(Just 1,[3,22,1,1,20,1])]
λ> fromListWith (++) pairs
fromList [(Just 0,[[2,21,0]]),(Just 1,[[3,22,1],[1,20,1]])]
Great job, Haskell.
Upvotes: 1