Subscribe:

Pages

Simple Clustering with RSRuby

Clustering is a technique for grouping objects which are similar. For example, given the following data instances:




A:10,20,30,40
B:40,30,20,10
C:11,21,29,39
D:39,29,21,11

We can see that A and C are 'closer' than B and D, so A and C can be grouped together, and B and D form a separate group.

R supports a wide variety of clustering techniques, all of which require us to pass a data frame object to the R interpreter. This post describes a simple way of generating a data frame, passing it to a clustering algorithm, and reading back some of the results.

Creating a Data Frame

The data frame is an R-specific data structure for holding data and its interpretation. For clustering, we need to describe a number of instances (the rows within a standard table) based on their attributes (the columns). For example, the following shows the first two instances from a weather dataset:



instanceoutlooktemperaturehumiditywindy
1085850
2080901


To define this in RSRuby, we need to set up a conversion tool, to handle the conversion from a hashmap to R's data frame.

require 'rsruby'
require 'rsruby/dataframe'

r = RSRuby.instance

r.class_table['data.frame'] = lambda {|x| DataFrame.new(x)}
RSRuby.set_default_mode(RSRuby::CLASS_CONVERSION)

The weather dataset can be defined and set up as follows:

outlooks = [0,0,1,2,2,2,1,0,0,2,0,1,1,2]
temps = [85,80,83,70,68,65,64,72,69,75,75,72,81,71]
humidities = [85,90,86,96,80,70,65,95,70,80,70,90,75,91]
winds = [0,1,0,0,0,1,1,0,0,0,1,1,0,1]

weather_data = {}
weather_data['outlook'] = outlooks
weather_data['temperature'] = temps
weather_data['humidity'] = humidities
weather_data['windy'] = winds

example = r.as_data_frame(:x => weather_data)

Of course, the definition of the hashmap can be simplified, but I like this format as a template for constructing the data frames from other sources of data. Note that the hashmap must be provided as the value of the :x key when constructing the data frame.

Clustering

To use any of the cluster techniques, we must include the 'cluster' library:

r.library("cluster")

A simple form of clustering algorithm is called clara. This takes a data frame and a number of clusters, and then returns a set of results which describe the data in terms of those clusters; the result is returned as a hashmap for Ruby, and the cluster results can be retrieved using the "clustering" key:

clara_result = r.clara(example,2)

14.times do |i|
puts "Data: #{clara_result["data"][i].join(",")} Cluster: #{clara_result["clustering"][i]}"
end

A sample output is:

Data: 0,85,85,0 Cluster: 1
Data: 0,80,90,1 Cluster: 2
Data: 1,83,86,0 Cluster: 1
Data: 2,70,96,0 Cluster: 2
Data: 2,68,80,0 Cluster: 1
Data: 2,65,70,1 Cluster: 1
Data: 1,64,65,1 Cluster: 1
Data: 0,72,95,0 Cluster: 2
Data: 0,69,70,0 Cluster: 1
Data: 2,75,80,0 Cluster: 1
Data: 0,75,70,1 Cluster: 1
Data: 1,72,90,1 Cluster: 2
Data: 1,81,75,0 Cluster: 1
Data: 2,71,91,1 Cluster: 2