Позвольте мне начать с определения структур данных на месте, так как считывание csv ортогонально реальной проблеме:
lines = [line.split(',') for line in """\
event,rack,role,dc
network,north,mobile,africa
network,east,mobile,asia
oom,south,desktop,europe
cpu,east,web,northamerica
oom,north,mobile,europe
cpu,south,web,northamerica
cpu,west,web,northamerica
""".splitlines()]
for line in lines:
print line
который печатает:
['event', 'rack', 'role', 'dc']
['network', 'north', 'mobile', 'africa']
['network', 'east', 'mobile', 'asia']
['oom', 'south', 'desktop', 'europe']
['cpu', 'east', 'web', 'northamerica']
['oom', 'north', 'mobile', 'europe']
['cpu', 'south', 'web', 'northamerica']
['cpu', 'west', 'web', 'northamerica']
Теперь давайте создадим все возможные комбинации из 2 или более слов в каждой строке. Существует 11 способов выбора 2, 3 или 4 из 4 (4C2 + 4C3 + 4C4 == 6 + 4 + 1 == 11).
Алгоритм, который я использую для нахождения комбинаций, просматривает двоичные числа из 4 цифр (т.е. 0000, 0001, 0010, 0011, 0100 и т. Д.) И для каждого такого числа создает комбинацию слов в зависимости от того, соответствующая двоичная цифра равна 1. Например, для 0101 выбрано второе и четвертое слово:
def find_combinations(line):
combinations = []
for i in range(2**len(line)):
bits = bin(i)[2:].zfill(len(line))
if bits.count('1') < 2: # skip numbers with less than two 1-bits
continue
combination = set()
for bit, word in zip(bits, line):
if bit == '1':
combination.add(word)
combinations.append('-'.join(sorted(combination)))
return combinations
теперь мы можем перебрать все комбинации и посчитать их частоту:
from collections import defaultdict
counter = defaultdict(int)
for line in lines:
for c in find_combinations(line):
counter[c] += 1
и, наконец, мы можем отсортировать (по убыванию) по частоте
for combination_freq in sorted(counter.items(), key=lambda item: item[1], reverse=True):
print combination_freq
чтобы получить:
('cpu-northamerica', 3)
('northamerica-web', 3)
('cpu-northamerica-web', 3)
('cpu-web', 3)
('mobile-north', 2)
('mobile-network', 2)
('europe-oom', 2)
('east-network', 1)
('asia-east-mobile', 1)
('asia-east-network', 1)
('cpu-south-web', 1)
('east-northamerica-web', 1)
('europe-north', 1)
('cpu-east', 1)
...etc.