Scaling is the main process of turning many-valued data into unary formal contexts. See the book by Ganter and Wille for an introduction.
Suppose we have given the following many-valued formal context
(def mv-context (make-mv-context [1 2 3]
'[color size]
'#{[1 color blue] [1 size large]
[2 color green] [2 size very-large]
[3 color red] [3 size small]}))
mv-context
|color size
--+-----------------
1 |blue large
2 |green very-large
3 |red small
We want to scale this context to make it unary. Of course, if an object is very
large, it is also large, so we use an biordinal scale for the attribute size
.
On the other hand, the colors don’t have share any interrelations, so we just
use the nominal scale for color
.
The macro that implements a high-level abstraction to scaling is
scale-mv-context-with
. It is able of handling every possible scale (as these
are only formal contexts), but provides some convenience definitions for known
scales.
Let us see how scaling can be done, and let us discuss the details afterwards.
(scale-mv-context-with mv-context
[color] (nominal-scale values)
[size] (biordinal-scale '[small large very-large]
'[small large very-large]
1
(order-by '[small])
(order-by '[large very-large])))
|[size [<= small]] [size [>= large]] [size [>= very-large]] [color blue] [color green] [color red]
--+--------------------------------------------------------------------------------------------------
1 |. x . x . .
2 |. x x . x .
3 |x . . . . x
Intuitively, we tell scale-mv-context-with
to scale mv-context
such that
attribute color
gets scaled by a nominal scale and that size
gets scaled
using a biordinal scale. There, the variable values
just stands for all
possible values the corresponding attribute can have.
Now, the functions nominal-scale
and biordinal-scale
are just ordinary
functions, and we can examine which contexts they produced.
The nominal scale is not a surprise:
(nominal-scale '[blue green red])
|blue green red
------+---------------
blue |x . .
green |. x .
red |. . x
To construct the biordinal scale, we supply five arguments:
- the set of values of the corresponding attributes,
- the set of attributes of the resulting scale,
- how many values should be used for the first scale,
- how the first set of attributes should be ordered
- how the second set of attributes should be ordered
Looking at our particular example may help to understand this:
(biordinal-scale '[small large very-large]
'[small large very-large]
1
(order-by '[small])
(order-by '[large very-large]))
|[>= large] [<= small] [>= very-large]
-----------+--------------------------------------
large |x . .
small |. x .
very-large |x . x
Note that biordinal-scale
expects the attributes in ascending order, otherwise
the automatically constructed attributes names don’t make any sense.
Other pre-defined scales include interordinal-scale
, dichotomic-scale
, and
interval-scale
. From the examples above it should also be clear how to define
other scales.
Functional dependencies between attributes of many-valued contexts are defined in the same way as they would be in data bases. Attribute A
is functional dependent on attribute B
if the semiproduct of A
and B
has the same number of unique objects as just A
. The set of all non-redundant functional dependencies can be calculated from any many-valued context by use of the function functional-dependencies
.