Completed
Push — master ( f7faf9...ef8477 )
by Chris
12:37
created

abydos.clustering.omission_key()   B

Complexity

Conditions 6

Size

Total Lines 41
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 16
nop 1
dl 0
loc 41
rs 8.6666
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
3
# Copyright 2014-2018 by Christopher C. Little.
4
# This file is part of Abydos.
5
#
6
# Abydos is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# Abydos is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with Abydos. If not, see <http://www.gnu.org/licenses/>.
18
19
"""abydos.clustering.
20
21
The clustering module implements clustering algorithms such as:
22
    - mean pair-wise similarity
23
"""
24
25
from __future__ import division, unicode_literals
26
27
from six.moves import range
28
29
from .distance import sim
30
from .stats import hmean
31
32
33
def mean_pairwise_similarity(collection, metric=sim,
34
                             meanfunc=hmean, symmetric=False):
35
    """Calculate the mean pairwise similarity of a collection of strings.
36
37
    Takes the mean of the pairwise similarity between each member of a
38
    collection, optionally in both directions (for asymmetric similarity
39
    metrics.
40
41
    :param list collection: a collection of terms or a string that can be split
42
    :param function metric: a similarity metric function
43
    :param function mean: a mean function that takes a list of values and
44
        returns a float
45
    :param bool symmetric: set to True if all pairwise similarities should be
46
        calculated in both directions
47
    :returns: the mean pairwise similarity of a collection of strings
48
    :rtype: str
49
50
    >>> mean_pairwise_similarity(['Christopher', 'Kristof', 'Christobal'])
51
    0.51980198019801982
52
    >>> mean_pairwise_similarity(['Niall', 'Neal', 'Neil'])
53
    0.54545454545454541
54
    """
55
    if hasattr(collection, 'split'):
56
        collection = collection.split()
57
    if not hasattr(collection, '__iter__'):
58
        raise ValueError('collection is neither a string nor iterable type')
59
    elif len(collection) < 2:
60
        raise ValueError('collection has fewer than two members')
61
62
    collection = list(collection)
63
64
    pairwise_values = []
65
66
    for i in range(len(collection)):
0 ignored issues
show
unused-code introduced by
Consider using enumerate instead of iterating with range and len
Loading history...
67
        for j in range(i+1, len(collection)):
68
            pairwise_values.append(metric(collection[i], collection[j]))
69
            if symmetric:
70
                pairwise_values.append(metric(collection[j], collection[i]))
71
72
    if not callable(meanfunc):
73
        raise ValueError('meanfunc must be a function')
74
    return meanfunc(pairwise_values)
75
76
77
if __name__ == '__main__':
78
    import doctest
79
    doctest.testmod()
80