Real-world problem:
I have data on directors across many firms, but sometimes "John Smith, director of XYZ" and "John Smith, director of ABC" are the same person, sometimes they're not. Also "John J. Smith, director of XYZ" and "John Smith, director of ABC" might be the same person, or might not be. Often examination of additional information (e.g., comparison of biographical data on "John Smith, director of XYZ" and "John Smith, director of ABC") makes it possible to resolve whether two observations are the same person or not.
Conceptual version of the problem:
In that spirit, am collecting data that will identify matching pairs. For example, suppose I have the following matching pairs: {(a, b), (b, c), (c, d), (d, e), (f, g)}
. I want to use the transitivity property of the relation "is the same person as" to generate "connected components" of {{a, b, c, d, e}, {f, g}}
. That is {a, b, c, d, e}
is one person and {f, g}
is another. (An earlier version of the question referred to "cliques", which are apparently something else; this would explain why find_cliques
in networkx
was giving the "wrong" results (for my purposes).
The following Python code does the job. But I wonder: is there a better (less computationally costly) approach (e.g., using standard or available libraries)?
There are examples here and there that seem related (e.g., Cliques in python), but these are incomplete, so I am not sure what libraries they are referring to or how to set up my data to use them.
Sample Python 2 code:
def get_cliques(pairs):
from sets import Set
set_list = [Set(pairs[0])]
for pair in pairs[1:]:
matched=False
for set in set_list:
if pair[0] in set or pair[1] in set:
set.update(pair)
matched=True
break
if not matched:
set_list.append(Set(pair))
return set_list
pairs = [('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e'), ('f', 'g')]
print(get_cliques(pairs))
This produces the desired output: [Set(['a', 'c', 'b', 'e', 'd']), Set(['g', 'f'])]
.
Sample Python 3 code:
This produces [set(['a', 'c', 'b', 'e', 'd']), set(['g', 'f'])]
):
def get_cliques(pairs):
set_list = [set(pairs[0])]
for pair in pairs[1:]:
matched=False
for a_set in set_list:
if pair[0] in a_set or pair[1] in a_set:
a_set.update(pair)
matched=True
break
if not matched:
set_list.append(set(pair))
return set_list
pairs = [('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e'), ('f', 'g')]
print(get_cliques(pairs))
if not matched
byelse
(else
in this case meaning the for has reached the exit condition) – Rubidiuma
andc
are not connected. – Rubidium