# -*- coding: utf-8 -*-
"""
Attribute value frequency outlier detection using Spark
"""
from pyspark import SparkContext
from operator import add
sc = SparkContext(appName="Attribute Value Frequency")
def parseDevelopmentDatasetLine(line):
"""
Parses development dataset line to attributes.
:param line: .
:returns: list of key value pairs.
"""
retval = []
# Development dataset uses \', \' to separate
# the attributes.
parts = line.split(",")
for item in parts:
# Keys are separated from the values by \':\'
key, value = item.split(\':\')
# Lets trim the extra whitespace from the key and the value
key = key.strip()
value = value.strip()
retval.append((key, value))
return retval
def attributeValueFrequencyScorer(line):
"""
Connects each line to attribute value frequency score (up to constant factor)
:param line: line turned to list of (label, value) tuples
:returns: original line and attribute value frequency score.
"""
# Let\'s score each line and create a tuple (line, score)
score = 0
for item in line:
# item[0] is attribute id
# item[1] is value of the attribute
# Note: May fail due to overflow but not likely.
score += counts[str(item[0])][str(item[1])]
return (line, score)
if __name__ == \'__main__\':
data = sc.textFile("s3a://<your aws account key>:<your aws account secret key>@free-style-sciencey-spark-demo/development_dataset.txt")
parsed_data = data.map(parseDevelopmentDatasetLine)
# Let\'s count the number of times different attribute values
# are present in the dataset.
grouped_by_attribute_value_labels = parsed_data.flatMap(lambda x: x).reduceByKey(lambda x,y: x + \' \' + y )
keys = grouped_by_attribute_value_labels.keys().collect()
# Count for all possible values for each attribute value
counts = {}
for key in keys:
# Let\'s turn tuples to dict
values = grouped_by_attribute_value_labels.filter(lambda x: x[0] == key).flatMap(lambda x: x[1].split()).map(lambda x: (x, 1)).reduceByKey(add).collect()
counts[str(key)] = dict(values)
# Let\'s go through the dataset and score each item
avf_scored_data = parsed_data.map(attributeValueFrequencyScorer).sortBy(lambda x: x[1])
outliers = avf_scored_data.take(10) # Let\'s print 10 most likely outliers
for item in outliers:
print item
# Let\'s also put results to s3
sc.parallelize(outliers).saveAsTextFile("s3a://<your aws account key>:<your aws account secret key>@free-style-sciencey-spark-demo/avf_tuloksia.txt")