In [2]:
#IDEA построить гистограмму распределения слов у Counter
#


#                Дальше идет работы с графом с учетом полученного массива сематической близости пар слов
#                          Соствление нечеткого графа по моногородам  (по словам)

#  Для построения графа если семантика уже собрана то можно начинать с этого места

# preparation
import pymorphy2
import nltk
import pandas as pd
nltk.download('punkt')  #не знаю нужно ли каждый раз это скачивать
nltk.download('stopwords')  #не знаю нужно ли каждый раз это скачивать


# Set global params and praparation
morph = pymorphy2.MorphAnalyzer()
g_path = "D:/Projects/Aspirantura/GASU_SP/"
print("g_path >> ",g_path)
g_max_inds_count = 19995 #19995
print("g_max_inds_count >> ",g_max_inds_count)
g_th = 0.4  #start threshold for fuzzy graph
print("g_th >> ",g_th)

print("Done")


[nltk_data] Downloading package punkt to
[nltk_data]     D:\Users\PDudarin\AppData\Roaming\nltk_data...
[nltk_data]   Package punkt is already up-to-date!
[nltk_data] Downloading package stopwords to
[nltk_data]     D:\Users\PDudarin\AppData\Roaming\nltk_data...
[nltk_data]   Package stopwords is already up-to-date!
g_path >>  D:/Projects/Aspirantura/GASU_SP/
g_max_inds_count >>  19995
g_th >>  0.4
Done

In [2]:
# Составление справочника слов и формирование дата сета (матрицы графа) слов и списков показателей и слов
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import pickle
import pymorphy2
import nltk
from nltk.corpus import stopwords
import time
from time import gmtime, strftime
import random
import collections

print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()

print("Start creating Indictors DataSet")

#Загрузка даных
xl_file = pd.ExcelFile(g_path+'Показатели моногородов.xlsx')
ds = xl_file.parse("Лист1")


#clear symbols
# эти символы разбивают слово на два
chars_to_remove = [u'«', u'»', u'!', u'<', u'>', u'?', u',', u'.', u'-', u'(', u')', u'[', u']', u'"']
dd = {ord(c):' ' for c in chars_to_remove}
# эти символы убирают слово из сравнения
stop_sybols = [u'/', u'\\', u'№', u':', u'1', u'2', u'3', u'4' , u'5', u'6', u'7', u'8', u'9', u'0', u'–']

# Загружаем стоп слова
xl_file = pd.ExcelFile(g_path+'Стоп слова.xlsx')
# dfs = {sheet_name: xl_file.parse(sheet_name)
#           for sheet_name in xl_file.sheet_names}
ds_stop_words = xl_file.parse("Лист1")
stop_list = [morph.parse(x)[0].normal_form for x in ds_stop_words.STOP_WORDS.str.upper().tolist() ]
# add common stop words
for w in stopwords.words('russian'):
    stop_list.append(w)
print("Кол-во стоп слов: ",len(stop_list))


# List of indicators
inds = []
i = 0

l_inds_list = ds.IND_NAME.str.upper().tolist()
if g_max_inds_count < len(l_inds_list)*0.9:
  sample_list = random.sample(l_inds_list, g_max_inds_count)
else:
  sample_list = l_inds_list[0:g_max_inds_count]

for j in sample_list:
    inds.append([i, j, [], {}])
    inds[i][2] = [morph.parse(x)[0].normal_form for x in nltk.word_tokenize(j.translate(dd))
                  if (not any(st in x for st in stop_sybols)) and (morph.parse(x)[0].normal_form not in stop_list)]
    i+=1

print("indicators >>", inds[0:10])

output = open(g_path+'monocity_inds_'+str(g_max_inds_count)+'.pkl', 'wb')
pickle.dump(inds, output)
output.close()
print("Indicators saved in ", g_path+'monocity_inds_'+str(g_max_inds_count)+'.pkl')
print("\n--------------------------------------------------------\n")

print("Start creating Words DataSet")
l_words_counter = collections.Counter([w for ind in inds for w in ind[2]]) # получили слова с их количествами
# print("l_words_counter ", l_words_counter)

# теперь нормируем важность слова относительно
l_values = [int(v)  for k,v in dict(l_words_counter).items()]
l_cntr_mean = np.mean(l_values)
l_cntr_std = np.std(l_values)
print("l_cntr_mean >> ", l_cntr_mean)
print("l_cntr_std >> ", l_cntr_std)

# l_words_dict = {k: (v-l_cntr_mean)/l_cntr_std  for k,v in dict(l_words_counter).items()}
l_words_dict = [ [k, (v-l_cntr_mean)/l_cntr_std]  for k,v in dict(l_words_counter).items()]
# words = list(set())  #delete duplicates

print("Words cnt: ", len(l_words_dict))

# l_dt_smpl = {}
# i = 0
# for k,v in l_words_dict.items():
#     i +=1
#     if i < 10:
#         l_dt_smpl[k] = v
#     else:
#         break
print("Words (normalized) [0:10]>> ", l_words_dict[0:10])

#вывести все слова с частотами в отдельный текстовый файл
l_df = pd.DataFrame(l_words_dict)
l_df.to_csv(g_path+'monocity_words_'+str(g_max_inds_count)+'.csv', index=False, header=True)
print("Words with frequencies saved in ", g_path+'monocity_words_'+str(g_max_inds_count)+'.csv')

print("\n--------------------------------------------------------\n")


# words = list(l_words_dict.keys())
l_words_cnt = len(l_words_dict)

words_ds = [[0 for j in range(0, l_words_cnt)] for i in range(0, l_words_cnt)]

# IDEA может быть повышать важность (силу) связей между словами на основании важности сами слов (частота или еще как) ?

# Semantic dictionary
pkl_file = open(g_path+'words_dict_monocities_sem.pkl', 'rb')
l_words_sem_dist_dict = pickle.load(pkl_file)
pkl_file.close()
l_sem_dict_empty = {k:v for k, v in l_words_sem_dist_dict.items() if v is None } #all not empty
print("Available processed pair count: ", len(l_words_sem_dist_dict)-len(l_sem_dict_empty))


for i in range(0, l_words_cnt):
    for j in range(0, l_words_cnt):
        if l_words_dict[i][0] == l_words_dict[j][0]:  # FIXME actually only when i==j
            words_ds[i][j] = 1
            words_ds[j][i] = 1
        else:
            mc=""
            m = 0
            w1 = l_words_dict[i][0]
            w2 = l_words_dict[j][0]
            try:
                if  w1 > w2:
                    mc=l_words_sem_dist_dict[w1+"__"+w2]
                else:
                    mc=l_words_sem_dist_dict[w2+"__"+w1]
                if mc not in [None, "Error", "Unknown"]:
                    m = abs(float(mc))  # [-1;1] !!!
            except:
                None

            words_ds[i][j] = m
            words_ds[j][i] = m


# # добавим сильные связи слов внутри одного показателя
# j = 0
# m = 1
# for ind in inds:
#     for j1 in range(0, len(ind[2])):
#         if j1>0:
#             words_ds[j][j-1] = m
#             words_ds[j-1][j] = m
#
#         j+=1

output = open(g_path+'monocity_words_ds_'+str(g_max_inds_count)+'.pkl', 'wb')
pickle.dump(words_ds, output)
output.close()
print("Words DS saved in ", g_path+'monocity_words_ds_'+str(g_max_inds_count)+'.pkl')


output = open(g_path+'monocity_words_'+str(g_max_inds_count)+'.pkl', 'wb')
pickle.dump(l_words_dict, output)
output.close()
print("Words dictionary saved in ", g_path+'monocity_words_'+str(g_max_inds_count)+'.pkl')

print("WORDS_DS[5][0:11] example: ", words_ds[5][0:20])

print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))


--- Start time Thu, 30 Mar 2017 07:24:40 ---
Start creating Indictors DataSet
Кол-во стоп слов:  396
indicators >> [[0, 'ДОЛЯ НАСЕЛЕНИЯ ИМЕЮЩЕГО ДЕНЕЖНЫЕ ДОХОДЫ НИЖЕ ВЕЛИЧИНЫ ПРОЖИТОЧНОГО МИНИМУМА В ОБЩЕЙ ЧИСЛЕННОСТИ НАСЕЛЕНИЯ АЛЕЙСКОГО РАЙОНА АЛТАЙСКОГО КРАЯ', ['население', 'денежный', 'доход', 'ниже', 'величина', 'прожиточный', 'население', 'алейский', 'район', 'край'], {}], [1, 'КОЛИЧЕСТВО ИСТОРИКОПАТРИОТИЧЕСКИХ ГЕРОИКОПАТРИОТИЧЕСКИХ И ВОЕННОПАТРИОТИЧЕСКИХ МУЗЕЕВ ИЛИ МУЗЕЙНЫХ КОМНАТ В ОБЩЕОБРАЗОВАТЕЛЬНЫХ УЧРЕЖДЕНИЯХ', ['историкопатриотический', 'героикопатриотический', 'военнопатриотический', 'музей', 'музейный', 'комната', 'общеобразовательный'], {}], [2, 'ОХВАТ ПРОФИЛАКТИЧЕСКИМИ МЕРАМИ ПОДРОСТКОВ И МОЛОДЕЖИ В ВОЗРАСТЕ ОТ ДО ЛЕТ', ['охват', 'профилактический', 'подросток', 'молодёжь', 'возраст'], {}], [3, 'УРОВЕНЬ ЗАНЯТОСТИ НАСЕЛЕНИЯ', ['занятость', 'население'], {}], [4, 'УДЕЛЬНЫЙ ВЕС РАБОТНИКОВ С ПРОФЕССИОНАЛЬНЫМ ОБРАЗОВАНИЕМ В ОБЩЕЙ ЧИСЛЕННОСТИ ЗАНЯТЫХ В ЭКОНОМИКЕ', ['вес', 'работник', 'профессиональный', 'занятой', 'экономика'], {}], [5, 'ДОЛЯ ВЫПУСКНИКОВ ОБЩЕОБРАЗОВАТЕЛЬНЫХ ОРГАНИЗАЦИЙ ПОСТУПИВШИХ В ПРОФЕССИОНАЛЬНЫЕ ОБРАЗОВАТЕЛЬНЫЕ ОРГАНИЗАЦИИ', ['выпускник', 'общеобразовательный', 'поступить', 'профессиональный', 'образовательный'], {}], [6, 'ОБЪЕМ ОТГРУЖЕННЫХ ТОВАРОВ СОБСТВЕННОГО ПРОИЗВОДСТВА ВЫПОЛНЕННЫХ РАБОТ УСЛУГ СОБСТВЕННЫМИ СИЛАМИ ПО КРУГУ КРУПНЫХ И СРЕДНИХ ОРГАНИЗАЦИЙ', ['объесть', 'отгрузить', 'товар', 'собственный', 'производство', 'выполнить', 'работа', 'услуга', 'собственный', 'сила', 'круг', 'крупный'], {}], [7, 'ОБЪЕМ ИНВЕСТИЦИЙ ЗА СЧЕТ ВСЕХ ИСТОЧНИКОВ ФИНАНСИРОВАНИЯ БЕЗ СУБЪЕКТОВ МАЛОГО ПРЕДПРИНИМАТЕЛЬСТВА И ОБЪЕМОВ ИНВЕСТИЦИЙ НЕ НАБЛЮДАЕМЫХ ПРЯМЫМИ СТАТИСТИЧЕСКИМИ МЕТОДАМИ', ['объесть', 'инвестиция', 'счёт', 'источник', 'финансирование', 'субъект', 'предпринимательство', 'инвестиция', 'наблюдать', 'прямая', 'статистический', 'метод'], {}], [8, 'УВЕЛИЧЕНИЕ ЧИСЛА ДЕТЕЙ ОЗДОРОВЛЕННЫХ В ПОЕЗДКАХ С РОДИТЕЛЯМИ', ['ребёнок', 'оздоровить', 'поездка', 'родитель'], {}], [9, 'ДОЛЯ УЧАЩИХСЯ ШКОЛ ГОРОДА УЧАСТВУЮЩИХ В ГОРОДСКИХ И КРАЕВЫХ МЕРОПРИЯТИЯХ ПАТРИОТИЧЕСКОЙ НАПРАВЛЕННОСТИ', ['учащийся', 'школа', 'город', 'участвовать', 'городской', 'краевой', 'мероприятие', 'патриотический', 'направленность'], {}]]
Indicators saved in  D:/Projects/Aspirantura/GASU_SP/monocity_inds_19995.pkl

--------------------------------------------------------

Start creating Words DataSet
l_cntr_mean >>  22.241721349
l_cntr_std >>  84.0264187792
Words cnt:  6553
Words (normalized) [0:10]>>  [['сооружение', 2.1036036191838656], ['информатизация', -0.2051940520552924], ['заполняемость', -0.25279812775094512], ['районный', 0.8420956132490679], ['ввод', 2.8414667924664831], ['налог', 1.5561567486838592], ['профориентация', -0.25279812775094512], ['ремонтный', -0.12188691958790011], ['гбуз', -0.25279812775094512], ['ограничение', -0.10998590066398693]]
Words with frequencies saved in  D:/Projects/Aspirantura/GASU_SP/monocity_words_19995.csv

--------------------------------------------------------

Available processed pair count:  21869191
Words DS saved in  D:/Projects/Aspirantura/GASU_SP/monocity_words_ds_19995.pkl
Words dictionary saved in  D:/Projects/Aspirantura/GASU_SP/monocity_words_19995.pkl
WORDS_DS[5][0:11] example:  [0.0186236916537, 0.0675680233711, 0.119470180412, 0.0709973016005, 0.037454129799, 1, 0.0801358016419, 0.00246889946354, 0.0256127526734, 0.416408220953, 0.248680515419, 0.147238670951, 0.113274846876, 0.00842275648886, 0.188756284591, 0.109573469217, 0, 0, 0.0428798598092, 0.103593132204]
Done
--- 9241.772263765335 seconds ---

In [2]:
# Construct fuzzy graph from WORDS
import igraph
# from igraph import *
import pickle
import time
from time import gmtime, strftime

print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()

#----------------------------------------------------------------------------------------

# def calc_weigth(p_vw1, p_vw2, p_ew) -> float:
#     l_vw = max(p_vw1, p_vw2)
#     if l_vw > 0:
#         l_w = min(1, p_ew + l_vw/10)
#         return l_w
#     else:
#         return p_ew

def calc_weigth(p_vw1, p_vw2, p_ew) -> float:
    return p_ew

#----------------------------------------------------------------------------------------

def create_graph(p_words_ds, p_words, p_edge_treshold, p_graph_file_name):
    graph_ver_cnt = len(p_words)
    g = igraph.Graph()
    g.add_vertices(graph_ver_cnt)
    # g.vs["name"] = [p_words[i] for i in range(0, graph_ver_cnt)]
    g.vs["name"] = [k[0] for k in p_words]
    g.vs["norm_weight"] = [k[1] for k in p_words]
    # g.vs["cluster_n"] = [0 for i in range(0, graph_ver_cnt)]
    # g.vs["cluster_n"] = [0 for k in p_words.items()]

    edgs = [ (i,j) for i in range(0, graph_ver_cnt) for j in range(0, graph_ver_cnt)
             if i>j and p_words_ds[i][j] >= p_edge_treshold]
    # print(edgs)
    g.add_edges(edgs)

    g.es["weight"] = [ calc_weigth(p_words[i][1], p_words[j][1], p_words_ds[i][j])
                         for i in range(0, graph_ver_cnt)
                           for j in range(0, graph_ver_cnt) if i>j and p_words_ds[i][j] > p_edge_treshold
                     ]


    # delete isolated vertices
    l_exclude_list = []
    l_exclude_vs = []
    for i in reversed(range(0,graph_ver_cnt)):
        if g.vs[i].degree() == 0:
           l_exclude_list.append(g.vs[i]["name"])
           l_exclude_vs.append(i)

    g.delete_vertices(l_exclude_vs)

    print("Excluded cnt: ", len(l_exclude_list))
    print("Exclude list [0:50]: ", l_exclude_list[0:100])
    g.write_graphml(p_graph_file_name)
    print("Graph "+p_graph_file_name+" created.")
    igraph.summary(g)
    return g

#----------------------------------------------------------------------------------------

pkl_file = open(g_path+'monocity_words_ds_'+str(g_max_inds_count)+'.pkl', 'rb')
words_ds = pickle.load(pkl_file)
pkl_file.close()
print("words_ds len: ", len(words_ds))

pkl_file = open(g_path+'monocity_words_'+str(g_max_inds_count)+'.pkl', 'rb')
words = pickle.load(pkl_file)
pkl_file.close()
print("words len: ", len(words))

# for th in [0.5, 0.7, 0.9]:
# for th in [0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]:
for th in [g_th]:
    l_graph_main = create_graph(words_ds, words, th,
                                g_path+"monocity_words_graph_"
                                +str(g_max_inds_count)+"_"+str(round(th*100))+".graphml"
                               )

print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))


--- Start time Thu, 30 Mar 2017 11:30:22 ---
words_ds len:  6553
words len:  6553
Excluded cnt:  2100
Exclude list [0:50]:  ['устранить', 'исток', 'архитектурноградостроительный', 'увеличесние', 'лишить', 'выполненый', 'увелмчение', 'гшс', 'предоставить', 'продолжить', 'семьигражданин', 'упарвление', 'предпрития', 'пвр', 'показать', 'тысчеловек', 'учебновоспитательный', 'лёгкое', 'разделить', 'путёвка', 'спортивномассовый', 'предпринимательтсв', 'отнести', 'среднеспециальный', 'государственнуюмуниципальный', 'directum', 'финансовокредитный', 'опечение', 'учрежденийя', 'населенияпроживать', 'барс', 'проведнный', 'безъбарьерный', 'каквинский', 'программноцелевой', 'переселеныгородский', 'застроить', 'отметить', 'перерасчёт', 'информационноконсультационный', 'аварийнотехнический', 'неструдостпособность', 'распорядителейсредство', 'среденемесячный', 'ндфл', 'первое', 'фот', 'оказаться', 'тоспа', 'освещённость', 'причитать', 'возвести', 'удовлетворнный', 'часто', 'выше', 'звукофикация', 'коррупциогенный', 'нормативноправовой', 'постановить', 'выплнения', 'дежурнодиспетчерский', 'социальнотрудов', 'гяровой', 'гоодскома', 'геоинформационный', 'далеести', 'чебаркульский', 'g', 'совместителеймалый', 'терристический', 'лесом', 'затратить', 'висимоуткинск', 'отчётность', 'утвержденый', 'твинформация', 'возникнуть', 'производствавыполненный', 'холоджный', 'галексин', 'недоремонт', 'отобщий', 'оснащнность', 'миниципальный', 'набрать', 'осветить', 'наёмный', 'хозяйственноэксплуатационный', 'бизнесинкубатор', 'доставить', 'db', 'среднесписачный', 'телевид', 'социальнопсихологический', 'превысить', 'волонтеровпропагандист', 'задолжность', 'отчтность', 'vipnetкоординатор', 'учта']
Graph D:/Projects/Aspirantura/GASU_SP/monocity_words_graph_19995_40.graphml created.
IGRAPH UNW- 4453 36194 -- 
+ attr: name (v), norm_weight (v), weight (e)
Done
--- 29.793979167938232 seconds ---

In [59]:
# Проверки. Временное


pkl_file = open(g_path+'monocity_words_ds_'+str(g_max_inds_count)+'.pkl', 'rb')
words_ds = pickle.load(pkl_file)
pkl_file.close()
print("words_ds len: ", len(words_ds))

# pkl_file = open(g_path+'monocity_words_'+str(g_max_inds_count)+'.pkl', 'rb')
# words = pickle.load(pkl_file)
# pkl_file.close()
# print("words len: ", len(words))

l_cnt = 0 
# for ws in words_ds:
#   if max(w for w in ws if w != 1)  < 0.001:
#       l_cnt +=1
print("l_cnt >> ", l_cnt)
print(l_words_sem_dist_dict["ребёнок__девочка"])
# print(l_words_sem_dist_dict["девочка__ребёнок"])
print(l_words_sem_dist_dict["факт__оборот"])
# print(l_words_sem_dist_dict["оборот__факт"])
# print("None cnt >> ", sum(1 for k,v in l_words_sem_dist_dict.items() if v==None))
# print("Error cnt >> ",sum(1 for k,v in l_words_sem_dist_dict.items() if v=='Error'))
# print("Unknown cnt >> ", sum(1 for k,v in l_words_sem_dist_dict.items() if v=='Unknown'))

i = 0
print("Unknown pairs:")
for k,v in l_words_sem_dist_dict.items():
    if v == "Unknown":
      print(k)
      i += 1
    if i > 10:
        break

print("Done")


words_ds len:  6573
l_cnt >>  0
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-59-f87169930329> in <module>()
     17 #       l_cnt +=1
     18 print("l_cnt >> ", l_cnt)
---> 19 print(l_words_sem_dist_dict["ребенок__девочка"])
     20 # print(l_words_sem_dist_dict["девочка__ребёнок"])
     21 print(l_words_sem_dist_dict["факт__оборот"])

KeyError: 'ребенок__девочка'

In [19]:
# Hierarchical clustering based on fuzzy connectedness

import igraph
# from igraph import *
import pickle
import time
import random
from time import gmtime, strftime
from typing import List

#---------------------------------------------------------------------------

def del_edges(p_graph: igraph.Graph, p_edge_threshold: float):

    for e in p_graph.es:
        if e["weight"] < p_edge_threshold:
            p_graph.delete_edges(e.index)

    # for v in p_graph.vs:
    #     if v.degree() == 0:
    #         p_graph.delete_vertices(v.index)


#---------------------------------------------------------------------------

def get_subgraph_weight(p_graph: igraph.Graph) -> float:

    # l_degree = p_graph.degree()
    l_norm_weight = [1 if v <= 0 else v+1 for v in p_graph.vs["norm_weight"]]
    # l_name = p_graph.vs["name"]
    l_weight = sum(l_norm_weight[i] for i in range(0, len(p_graph.vs)) )

    return l_weight

#---------------------------------------------------------------------------

def get_subgraph_keywords(p_graph: igraph.Graph, p_keyword_cnt: int) -> List[str]:

    l_degree = p_graph.degree()
    l_norm_weight = [1 if v <= 0 else v+1 for v in p_graph.vs["norm_weight"]]
    l_name = p_graph.vs["name"]

    l_dict = {l_name[i]: l_degree[i]*l_norm_weight[i] for i in range(0, len(p_graph.vs)) }

    return sorted(l_dict, key=l_dict.get, reverse=True)[0:min(p_keyword_cnt, len(p_graph.vs))]

#---------------------------------------------------------------------------

#возвращает разрезанный граф, всегда больше одного подграфа,
# за исключением случая, когда разрезание противоречит органичениям
# старается получить разбиение с заданным количеством значимых (те которые превратятся в узлы) подграфов
def cut_graph(pGraph: igraph.Graph, p_edge_threshold: float,
              p_edge_th_step: float,
              p_max_edge_threshold: float,
              p_avg_bouquet: int,
              p_min_subgraph_coeff: float = 10 #коэффициент при котором субграф добавляется в иерархию
             ) -> [[igraph.Graph], float]:

    l_edge_threshold = p_edge_threshold
    l_prev_sgs_cnt = 1
    l_prev_sgs =  [pGraph]
    l_sgs = [pGraph]

    #пока возможно разбиение
    while (l_edge_threshold<1) and (l_edge_threshold < p_max_edge_threshold):
      del_edges(pGraph, l_edge_threshold)
      l_comps = pGraph.components(mode='STRONG')  #Returns:a VertexClustering object
      l_sgs = l_comps.subgraphs()
      l_sgs_cnt = sum(1 if (get_subgraph_weight(sg) >= p_min_subgraph_coeff) else 0 for sg in l_sgs)

      #подходит ли нам такое рзбиение?
      #если разбиаение подошло то выходим из цикла
      if (l_prev_sgs_cnt == 1) and (l_sgs_cnt >= p_avg_bouquet):
          break
      else:
          # единственная ситуация продолжения разбиения: не достигли среднего
          if (l_prev_sgs_cnt == 1) and (l_sgs_cnt < p_avg_bouquet):
              l_prev_sgs_cnt = l_sgs_cnt
              l_prev_sgs = l_sgs
          else:
            # если отклонение от среднего количества на предыдущем шаге было меньше, то возвращаем его
            if abs(l_prev_sgs_cnt - p_avg_bouquet) < abs(l_sgs_cnt - p_avg_bouquet):
              l_sgs = l_prev_sgs
              break
            # достигои идеального количества подграфов
            else:
              break

      #шаг для следующего разбиения
      l_edge_threshold += p_edge_th_step

    # if abs(l_edge_threshold - p_edge_threshold) > 10E-4:
    #     print("Different th ", l_edge_threshold, " ", p_edge_threshold)
    return [l_sgs, l_edge_threshold]

#---------------------------------------------------------------------------

def add_layer(p_hier_graph: igraph.Graph, p_graph: igraph.Graph, p_parent_vtx: str,
              p_layer_n: int,
              p_edge_threshold: float, #уровень с которого нужно начинать разбивать граф (для первого случая это текущий уровень)
              p_edge_th_step: float,
              p_max_edge_threshold: float,
              p_max_layer_cnt: int,
              p_min_subgraph_coeff: float = 10, #коэффициент при котором субграф добавляется в иерархию
              p_keywords_cnt: int = 10, #количество ключевых слов для узла
              p_keyword_coeff: float = 100, #коэффициент значимости первого слова от каждого подграфа
              p_avg_bouquet: int = 4
             ) -> {str: int}:


    #нарежем граф так, чтобы было нужно число подграфов (получим один подграф, только если разрезать не возможно)
    l_edge_threshold = p_edge_threshold
    if p_layer_n > 1: #первый шаг уже приходит нарезанным, поэтому для него условие ELSE
        [sgs, l_edge_threshold] = cut_graph(p_graph, l_edge_threshold,  p_edge_th_step, p_max_edge_threshold, p_avg_bouquet, p_min_subgraph_coeff)
    else: #первый шаг особенный
        l_comps = p_graph.components(mode='STRONG')  #Returns:a VertexClustering object
        sgs = l_comps.subgraphs()
        if len(sgs) == 1: #если в самом начале нам дали не разбитый граф, то нужно его тоже разбить
            [sgs, l_edge_threshold] = cut_graph(p_graph, l_edge_threshold+p_edge_th_step,  p_edge_th_step, p_max_edge_threshold, p_avg_bouquet, p_min_subgraph_coeff)

    #устанавливаем начальные переменные
    l_keywords = {}
    l_prnt_index = len(p_hier_graph.vs)-1
    l_node_cnt = 1 # если считать с нуля то будет умножение на ноль и пропадут многие ключевые сслова

    #проходимся по всем подграфам
    for sg in sgs:
        l_sg_keywords = {}
        # l_sg_vrtx_indx = 0
        # если вес данного подграфа достин собственного узла в иерархии то
        # также у нас теперь не может граф распадаться только на одну вершину, мы этого не допускаем процедурой разрезания
        # if (get_subgraph_weight(sg) >= p_min_subgraph_coeff) or (len(sgs) == 1):
        if (get_subgraph_weight(sg) >= p_min_subgraph_coeff) and (len(sgs) != 1):
            # Add vertex

            # TODO от такого именования нужно будет уйти на более абстрактное, когда будут ключевые слова сделаны
            if len(sg.vs) > p_keywords_cnt:
              l_vrtx_name = "Layer "+str(p_layer_n)+" "+' '.join(list(random.sample(sg.vs["name"], 3)))
            else:
              l_vrtx_name = "Layer "+str(p_layer_n)+" "+' '.join(list(sg.vs["name"]))

            p_hier_graph.add_vertex(l_vrtx_name)
            l_sg_vrtx_indx = len(p_hier_graph.vs)-1
            # print(l_sg_vrtx_indx)
            l_node_cnt += 1
            p_hier_graph.vs["layer"] = ["Layer "+str(l_edge_threshold) if x is None else x for x in p_hier_graph.vs["layer"]]
            p_hier_graph.vs["layer_n"] = [l_edge_threshold if x is None else x for x in p_hier_graph.vs["layer_n"]]
            p_hier_graph.vs["graph"] = [sg if x is None else x for x in p_hier_graph.vs["graph"]]
            p_hier_graph.vs["parent_node"] = ["n"+str(l_prnt_index)  if x is None else x for x in p_hier_graph.vs["parent_node"]]

            p_hier_graph.add_edge(p_parent_vtx, l_vrtx_name)

            # Recursion
            l_next_edge_threshold = l_edge_threshold+p_edge_th_step
            #Условие входа в рекурсию:
            #создавали узел
            #максимальное число шагов не достигнуто
            if (len(sg.vs)>1) and (p_layer_n < p_max_layer_cnt) and (l_next_edge_threshold<1) and (l_next_edge_threshold < p_max_edge_threshold):
              # del_edges(sg, p_edge_threshold)
              l_sg_keywords = add_layer(p_hier_graph, sg, l_vrtx_name, p_layer_n+1, l_next_edge_threshold, p_edge_th_step, p_max_edge_threshold,
                                        p_max_layer_cnt, p_min_subgraph_coeff, p_keywords_cnt, p_keyword_coeff, p_avg_bouquet)
              i = 0
              for k,v in l_sg_keywords.items(): #пополним список ключевых слов родительской вершины
                  if i == 0:
                    l_keywords[k] = v*p_keyword_coeff
                  else:
                    l_keywords[k] = v
                  i += 1
            else: # в рекурсию не вошли, значит просто пополняем список ключевых слов родителя
              i = 0
              for w in get_subgraph_keywords(sg, p_keywords_cnt):
                if i == 0:
                    l_keywords[w] = 1*p_keyword_coeff
                else:
                    l_keywords[w] = 1
                l_sg_keywords[w] = 1
                i += 1

            # Для добавленного узла нужно вставить его ключевые слова и количество детей
            l_words = ' '.join(l_sg_keywords.keys())
            # print(l_words)
            # print(p_hier_graph.vs["keywords"][0:5])
            p_hier_graph.vs["keywords"]  = [l_words if i == l_sg_vrtx_indx else p_hier_graph.vs["keywords"][i]
                                            for i in range(0, len(p_hier_graph.vs))
                                           ]
            # print(p_hier_graph.vs["keywords"][0:5])
            p_hier_graph.vs["child_node_cnt"]  = [len(sg.vs()) if i == l_sg_vrtx_indx else p_hier_graph.vs["child_node_cnt"][i]
                                                  for i in range(0, len(p_hier_graph.vs))
                                                 ]

        # если вес данного подграфа НЕ достин собственного узла в иерархии то просто пополняем ключевые слова родителя
        else:
            # just add keywords
            i = 0
            for w in get_subgraph_keywords(sg, p_keywords_cnt):
                if i == 0:
                    l_keywords[w] = 1*p_keyword_coeff
                else:
                    l_keywords[w] = 1
                i += 1

    # if p_layer_n == 1:
    #     print(l_keywords)
    l_list = sorted(l_keywords, key=l_keywords.get, reverse=True)[0:p_keywords_cnt] # у нас уже столько сколько нужно слов


    return {k: l_node_cnt for k in l_list}

#---------------------------------------------------------------------------

def getEdgeStat(pGraph: igraph.Graph) -> [float, float, float]:

    if len(pGraph.es["weight"]) == 0:
        return [1,1,1]

    l_max = max(w for w in  pGraph.es["weight"])
    l_min = min(w for w in  pGraph.es["weight"])
    l_avg = sum(w for w in  pGraph.es["weight"])/len(pGraph.es["weight"])

    return [l_max, l_min, l_avg]

#---------------------------------------------------------------------------

def getVertexStat(pGraph: igraph.Graph) -> float:

    l_sum = sum(vw for vw in p_graph.vs["norm_weight"])

    return [l_min, l_avg, l_max]

#---------------------------------------------------------------------------
#---------------------------------------------------------------------------

# main part
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()


#parameters
l_th = g_th  #0.4
l_max_inds_count = g_max_inds_count #19995 # для определения имени файлов для чтения и запии
l_th_start = l_th # старовый уровень уничтоженных ребер
l_th_step = 0.01 # шаг рекурсии по уничтожению ребер
l_th_max = 0.99 # максимальный уровень до которого уничтожаем ребра
l_max_depth = 1000 #максимальная глубина рекурсии
l_avg_bouquet = 3 # целевое количество подузлов в дереве

l_min_subgraph_coeff = 9.0 #коэффициент при котором субграф добавляется в иерархию
l_keywords_cnt = 10 #количество ключевых слов определяющих узел
l_keyword_coeff = 100 # множитель для первого слова в ключевых словах от каждого узла (чтобы один узел не затмил своими словами другие)

#load graph
l_graph_main = igraph.Graph().Load(g_path+"monocity_words_graph_"
                        +str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
                       )
print("Main graph summary: ", l_graph_main.summary())

l_hier_graph = igraph.Graph() # результирующий иерархический граф
l_hier_graph.add_vertices(1)
l_hier_graph.vs["name"] = ["_Моногорода_"]
l_hier_graph.vs["keywords"] = ["_Моногорода_"]
l_hier_graph.vs["layer"] = ["Layer "+str(0)]
l_hier_graph.vs["layer_n"] = [0]
l_hier_graph.vs["child_node_cnt"] = [len(l_graph_main.vs)]
l_hier_graph.vs["parent_node"] = ["n"]
l_hier_graph.vs["graph"] = [l_graph_main]
# l_hier_graph.vs["child_cnt"] = [-1]
# l_hier_graph.vs["child"] = [[]]


l_layer = 1
l_parent_vrtx_name = "_Моногорода_"

# l_comps = l_graph_main.components(mode='STRONG')  #Returns:a VertexClustering object
# l_layer += 1
l_mono_dict = add_layer(l_hier_graph, l_graph_main, l_parent_vrtx_name, l_layer,
                        l_th_start, l_th_step, l_th_max,
                        l_max_depth,
                        l_min_subgraph_coeff, l_keywords_cnt, l_keyword_coeff,
                        l_avg_bouquet
                       )
# print(add_layer(l_hier_graph, l_graph_main, l_parent_vrtx_name, l_layer, 0.75, 0.95, 0.05, 7))
l_words = ' '.join(l_mono_dict.keys())
l_hier_graph.vs["keywords"]  = [l_words if i == 0 else l_hier_graph.vs["keywords"][i]
                                for i in range(0, len(l_hier_graph.vs))
                               ]
l_hier_graph.vs["child_cnt"]  = l_hier_graph.degree()

# l_hier_graph.vs["child"] = [l_words if i == 0 else l_hier_graph.vs["child"][i]
#                             for i in range(0, len(l_hier_graph.vs))
#                            ]

print("Hier graph summary: ", l_hier_graph.summary())
print("Graphs' samples: ", l_hier_graph.vs["parent_node"][0:15])
print("Graphs' in hierarchy: ", len(l_hier_graph.vs["graph"]))
print("Graphs' samples: ", l_hier_graph.vs["graph"][0:5])
print("One graph words sample: ", l_hier_graph.vs["graph"][0].vs["name"][0:10])


#Вычислим дополнительные полезные характеристики
# - суммарный вес слов
# - мин макс и среднее значение веса ребер


l_hier_graph.vs["subgraph_weigth"] = [get_subgraph_weight(sg)  for sg in  l_hier_graph.vs["graph"]]
l_sg_edge_stats = [getEdgeStat(sg)  for sg in l_hier_graph.vs["graph"]]


l_hier_graph.vs["subgraph_edge_mins"] = [i[0] for i in l_sg_edge_stats]
l_hier_graph.vs["subgraph_edge_avgs"] = [i[1] for i in l_sg_edge_stats]
l_hier_graph.vs["subgraph_edge_maxs"] = [i[2] for i in l_sg_edge_stats]


l_hier_graph.write_graphml(g_path+"monocity_words_hier_graph_"
                           +str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
                          )

print("Graph file: "+g_path+"monocity_words_hier_graph_"
      +str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
     )
print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
#---------------------------------------------------------------------------


--- Start time Thu, 06 Apr 2017 14:43:57 ---
Main graph summary:  IGRAPH UNW- 4453 36194 -- 
+ attr: id (v), name (v), norm_weight (v), weight (e)
Hier graph summary:  IGRAPH UN-- 149 148 -- 
+ attr: child_cnt (v), child_node_cnt (v), graph (v), keywords (v), layer (v), layer_n (v), name (v), parent_node (v)
Graphs' samples:  ['n', 'n0', 'n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9', 'n10', 'n10', 'n12', 'n13']
Graphs' in hierarchy:  149
Graphs' samples:  [<igraph.Graph object at 0x0000000014F1E408>, <igraph.Graph object at 0x000000000D8836D8>, <igraph.Graph object at 0x0000000014F345E8>, <igraph.Graph object at 0x0000000014F1EC78>, <igraph.Graph object at 0x000000000C1638B8>]
One graph words sample:  ['сооружение', 'информатизация', 'заполняемость', 'районный', 'ввод', 'налог', 'профориентация', 'ремонтный', 'гбуз', 'ограничение']
Graph file: D:/Projects/Aspirantura/GASU_SP/monocity_words_hier_graph_19995_40.graphml
Done
--- 53.571356534957886 seconds ---

In [20]:
# Indicators fuzzy clustering
# выполняется всегда сразу после предыдущего пункта, т.к. тут не загружается граф иерархический

import igraph
# from igraph import *
import pickle
import time
import random
from time import gmtime, strftime
from typing import List

#---------------------------------------------------------------------------
# main part
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()

#parameters
l_th = g_th #0.4
l_max_inds_count = g_max_inds_count #19995 # для определения имени файлов для чтения и запии
# l_th_start = l_th # старовый уровень уничтоженных ребер
# l_th_step = 0.01 # шаг рекурсии по уничтожению ребер
# l_th_max = 0.9 # максимальный уровень до которого уничтожаем ребра
# l_max_depth = 20 #максимальная глубина рекурсии
#
# l_min_subgraph_coeff = 3.0 #коэффициент при котором субграф добавляется в иерархию
# l_keywords_cnt = 10 #количество ключевых слов определяющих узел
# l_keyword_coeff = 100 # множитель для первого слова в ключевых словах от каждого узла (чтобы один узел не затмил своими словами другие)

#load graph
# l_hier_graph = igraph.Graph().Load("D:/Projects/Aspirantura/GASU_SP/monocity_words_hier_graph_"
#                         +str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
#                        )


#load indicators
pkl_file = open(g_path+'monocity_inds_'+str(l_max_inds_count)+'.pkl', 'rb')
inds = pickle.load(pkl_file)
pkl_file.close()
print("Inds len: ", len(inds))

for v in l_hier_graph.vs:
    for i in inds:
        if len(i[2])>0:
            l_cnt = 0
            l_index = v.index
            l_graphs = l_hier_graph.vs["graph"]
            l_graph = l_graphs[l_index]
            for w in l_graph.vs:
                if w["name"] in i[2]:
                    l_cnt += 1
            # print(i[0])
            l_pcnt = l_cnt/len(i[2])
            if l_pcnt > 0.1:
                i[3][l_index] = round(l_pcnt,3)


print("Inds sample [0:10]: ", inds[0:9])

#write indicators
output = open(g_path+'monocity_inds_hier_'+str(l_max_inds_count)+'.pkl', 'wb')
pickle.dump(inds, output)
output.close()

#write indicators to csv
l_df = pd.DataFrame(inds)
l_df.to_csv(g_path+'monocity_inds_hier_'+str(g_max_inds_count)+'.csv', index=False, header=True)
print("Indicators clustering results saved in ", g_path+'monocity_inds_hier_'+str(g_max_inds_count)+'.csv')


print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
#---------------------------------------------------------------------------


--- Start time Thu, 06 Apr 2017 14:45:25 ---
Inds len:  19995
Inds sample [0:10]:  [[0, 'ДОЛЯ НАСЕЛЕНИЯ ИМЕЮЩЕГО ДЕНЕЖНЫЕ ДОХОДЫ НИЖЕ ВЕЛИЧИНЫ ПРОЖИТОЧНОГО МИНИМУМА В ОБЩЕЙ ЧИСЛЕННОСТИ НАСЕЛЕНИЯ АЛЕЙСКОГО РАЙОНА АЛТАЙСКОГО КРАЯ', ['население', 'денежный', 'доход', 'ниже', 'величина', 'прожиточный', 'население', 'алейский', 'район', 'край'], {0: 0.8, 1: 0.8, 2: 0.8, 3: 0.7, 4: 0.6, 5: 0.6, 6: 0.5, 7: 0.4, 8: 0.2}], [1, 'КОЛИЧЕСТВО ИСТОРИКОПАТРИОТИЧЕСКИХ ГЕРОИКОПАТРИОТИЧЕСКИХ И ВОЕННОПАТРИОТИЧЕСКИХ МУЗЕЕВ ИЛИ МУЗЕЙНЫХ КОМНАТ В ОБЩЕОБРАЗОВАТЕЛЬНЫХ УЧРЕЖДЕНИЯХ', ['историкопатриотический', 'героикопатриотический', 'военнопатриотический', 'музей', 'музейный', 'комната', 'общеобразовательный'], {0: 0.571, 1: 0.571, 2: 0.571, 3: 0.571, 4: 0.571, 5: 0.571, 6: 0.571, 7: 0.571, 8: 0.571, 9: 0.286, 10: 0.286, 103: 0.286, 12: 0.143, 66: 0.143, 81: 0.143, 104: 0.286}], [2, 'ОХВАТ ПРОФИЛАКТИЧЕСКИМИ МЕРАМИ ПОДРОСТКОВ И МОЛОДЕЖИ В ВОЗРАСТЕ ОТ ДО ЛЕТ', ['охват', 'профилактический', 'подросток', 'молодёжь', 'возраст'], {0: 1.0, 1: 1.0, 2: 0.8, 3: 0.6, 4: 0.6, 5: 0.6, 6: 0.4, 7: 0.4, 8: 0.4, 9: 0.4, 142: 0.2, 89: 0.2}], [3, 'УРОВЕНЬ ЗАНЯТОСТИ НАСЕЛЕНИЯ', ['занятость', 'население'], {0: 1.0, 1: 1.0, 2: 1.0, 3: 0.5, 4: 0.5, 5: 0.5, 6: 0.5, 7: 0.5, 116: 0.5, 114: 0.5}], [4, 'УДЕЛЬНЫЙ ВЕС РАБОТНИКОВ С ПРОФЕССИОНАЛЬНЫМ ОБРАЗОВАНИЕМ В ОБЩЕЙ ЧИСЛЕННОСТИ ЗАНЯТЫХ В ЭКОНОМИКЕ', ['вес', 'работник', 'профессиональный', 'занятой', 'экономика'], {0: 0.8, 1: 0.8, 2: 0.8, 3: 0.8, 4: 0.6, 5: 0.4, 6: 0.4, 7: 0.4, 8: 0.4, 9: 0.4, 10: 0.4, 75: 0.2, 12: 0.2, 76: 0.2, 69: 0.2}], [5, 'ДОЛЯ ВЫПУСКНИКОВ ОБЩЕОБРАЗОВАТЕЛЬНЫХ ОРГАНИЗАЦИЙ ПОСТУПИВШИХ В ПРОФЕССИОНАЛЬНЫЕ ОБРАЗОВАТЕЛЬНЫЕ ОРГАНИЗАЦИИ', ['выпускник', 'общеобразовательный', 'поступить', 'профессиональный', 'образовательный'], {0: 1.0, 1: 1.0, 2: 1.0, 3: 0.8, 4: 0.8, 5: 0.6, 6: 0.6, 7: 0.6, 8: 0.6, 9: 0.6, 10: 0.6, 12: 0.4, 64: 0.2, 81: 0.2, 61: 0.4, 62: 0.2, 63: 0.2}], [6, 'ОБЪЕМ ОТГРУЖЕННЫХ ТОВАРОВ СОБСТВЕННОГО ПРОИЗВОДСТВА ВЫПОЛНЕННЫХ РАБОТ УСЛУГ СОБСТВЕННЫМИ СИЛАМИ ПО КРУГУ КРУПНЫХ И СРЕДНИХ ОРГАНИЗАЦИЙ', ['объесть', 'отгрузить', 'товар', 'собственный', 'производство', 'выполнить', 'работа', 'услуга', 'собственный', 'сила', 'круг', 'крупный'], {0: 0.667, 1: 0.667, 2: 0.583, 3: 0.417, 4: 0.333, 5: 0.333, 6: 0.25, 7: 0.167, 8: 0.167, 9: 0.167, 10: 0.167}], [7, 'ОБЪЕМ ИНВЕСТИЦИЙ ЗА СЧЕТ ВСЕХ ИСТОЧНИКОВ ФИНАНСИРОВАНИЯ БЕЗ СУБЪЕКТОВ МАЛОГО ПРЕДПРИНИМАТЕЛЬСТВА И ОБЪЕМОВ ИНВЕСТИЦИЙ НЕ НАБЛЮДАЕМЫХ ПРЯМЫМИ СТАТИСТИЧЕСКИМИ МЕТОДАМИ', ['объесть', 'инвестиция', 'счёт', 'источник', 'финансирование', 'субъект', 'предпринимательство', 'инвестиция', 'наблюдать', 'прямая', 'статистический', 'метод'], {0: 0.667, 1: 0.667, 2: 0.667, 3: 0.583, 4: 0.5, 5: 0.5, 6: 0.417, 7: 0.25, 8: 0.25, 9: 0.167, 10: 0.167, 12: 0.167}], [8, 'УВЕЛИЧЕНИЕ ЧИСЛА ДЕТЕЙ ОЗДОРОВЛЕННЫХ В ПОЕЗДКАХ С РОДИТЕЛЯМИ', ['ребёнок', 'оздоровить', 'поездка', 'родитель'], {0: 0.75, 1: 0.75, 2: 0.5, 3: 0.5, 4: 0.5, 5: 0.5, 6: 0.5, 7: 0.5, 8: 0.5, 9: 0.5, 148: 0.25, 87: 0.25, 91: 0.25}]]
Indicators clustering results saved in  D:/Projects/Aspirantura/GASU_SP/monocity_inds_hier_19995.csv
Done
--- 344.57845425605774 seconds ---

In [7]:
# test fuzzy hierarchical clustering results

import igraph
# from igraph import *
import pickle
import time
import random
from time import gmtime, strftime
from typing import List

#---------------------------------------------------------------------------


#parameters
l_th = g_th
l_max_inds_count = g_max_inds_count # для определения имени файлов для чтения и запии

#---------------------------------------------------------------------------



def getIndicatorsByNode(pNodeIndex: int, pInds: list) -> []:
    l_list=[]
    for i in pInds:
        l_pt = i[3].get(pNodeIndex, None)
        if l_pt != None:
            l_list.append([i, l_pt])

    l_list.sort(key=lambda arg: arg[1],  reverse=True)

    return l_list

#---------------------------------------------------------------------------
# main part
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()


# load graph
l_hier_graph = igraph.Graph().Load(g_path+'monocity_words_hier_graph_'+str(g_max_inds_count)+"_"+str(round(g_th*100))+".graphml")

#load indicators
pkl_file = open(g_path + 'monocity_inds_hier_'+str(l_max_inds_count)+'.pkl', 'rb')
inds = pickle.load(pkl_file)
pkl_file.close()
# print("Inds len: ", len(inds))


# for n in [65, 83, 85, 91, 93, 41]:
for n in [596, 600, 601, 594]:
    print("Node ID: ", n, " keywords: ", l_hier_graph.vs["keywords"][n])
    l_inds = getIndicatorsByNode(n, inds)
    print("Inds cnt: ", len(l_inds))
    print("Inds sample [0:10]:")
    for i in l_inds[0:10]:
        print(i[1]," - ",i[0][0]," - ",i[0][1])
    print("----------------------------------")


print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
#---------------------------------------------------------------------------


--- Start time Fri, 31 Mar 2017 18:13:44 ---
Node ID:  596  keywords:  футбольный хоккей хоккейный волейбол баскетбол футбол
Inds cnt:  12
Inds sample [0:10]:
0.25  -  258  -  ДОЛЯ НАСЕЛЕНИЯ СИСТЕМАТИЧЕСКИ ЗАНИМАЮЩЕГОСЯ ФУТБОЛОМ 
0.25  -  3644  -  ПРОВЕДЕНИЕ ПЕРВЕНСТВА ДЮСШ ПО БАСКЕТБОЛУ
0.25  -  10626  -  КОЛИЧЕСТВО ФУТБОЛЬНЫХ СТАДИОНОВ СООТВЕТСТВУЮЩИХ ГОСУДАРСТВЕННЫМ ТРЕБОВАНИЯМ 
0.25  -  11067  -  ПРОВЕДЕНИЕ ПЕРВЕНСТВА ДЮСШ ПО ФУТБОЛУ
0.25  -  16038  -  ОТКРЫТОЕ ПЕРВЕНСТВО ГОРОДА ПО ВОЛЕЙБОЛУ
0.25  -  18596  -  ПРОВЕДЕНИЕ ПЕРВЕНСТВА ДЮСШ ПО ВОЛЕЙБОЛУ
0.2  -  1256  -  РЕЗУЛЬТАТ ВЫСТУПЛЕНИЙ В СЕЗОНЕ ХОККЕЙНОГО КЛУБА
0.2  -  3753  -  РЕЗУЛЬТАТ ВЫСТУПЛЕНИЙ В СЕЗОНЕ ФУТБОЛЬНОГО КЛУБА
0.2  -  16035  -  СОРЕВНОВАНИЯ ПО ВОЛЕЙБОЛУ ПОСВЯЩЕННЫЕ ДНЮ ЗАЩИТНИКА
0.182  -  11152  -  КОЛИЧЕСТВО ТРЕНЕРОВПРЕПОДАВАТЕЛЕЙ ОКАЗЫВАЮЩИХ УСЛУГИ ПО ПРОВЕДЕНИЮ УЧЕБНОТРЕНИРОВОЧНЫХ ЗАНЯТИЙ ПО ХОККЕЮ С ШАЙБОЙ ФИГУРНОМУ КАТАНИЮ И ФУТБОЛУ
----------------------------------
Node ID:  600  keywords:  клуб команда сезон
Inds cnt:  65
Inds sample [0:10]:
0.4  -  1256  -  РЕЗУЛЬТАТ ВЫСТУПЛЕНИЙ В СЕЗОНЕ ХОККЕЙНОГО КЛУБА
0.4  -  3753  -  РЕЗУЛЬТАТ ВЫСТУПЛЕНИЙ В СЕЗОНЕ ФУТБОЛЬНОГО КЛУБА
0.333  -  3477  -  КОЛИЧЕСТВО СБОРНЫХ КОМАНД ГОРОДА
0.333  -  6566  -  КОЛИЧЕСТВО ДЕТСКИХ И ПОДРОСТКОВЫХ КЛУБОВ
0.333  -  7672  -  ОРГАНИЗАЦИЯ РАБОТЫ И ПОДДЕРЖКА КЛУБОВ 
0.25  -  1228  -  ЧИСЛЕННОСТЬ СПОРТСМЕНОВ ВХОДЯЩИХ В СБОРНЫЕ КОМАНДЫ РАЗЛИЧНОГО УРОВНЯ
0.25  -  4954  -  КОЛИЧЕСТВО ДЕЙСТВУЮЩИХ ПАТРИОТИЧЕСКИХ ОБЪЕДИНЕНИЙ КЛУБОВ 
0.25  -  7620  -  ДОЛЯ НАСЕЛЕНИЯ МУНИЦИПАЛЬНОГО ОБРАЗОВАНИЯ ПОСЕЩАЮЩИХ МОЛОДЕЖНЫЕ КЛУБЫ
0.25  -  10349  -  КОЛИЧЕСТВО СОЗДАННЫХ ДОБРОВОЛЬНЫХ ПОЖАРНЫХ КОМАНД
0.25  -  10695  -  УВЕЛИЧЕНИЕ УЧАСТНИКОВ КРУЖКОВ КЛУБОВ ПО ИНТЕРЕСАМ 
----------------------------------
Node ID:  601  keywords:  тренировочный тренировка упражнение
Inds cnt:  6
Inds sample [0:10]:
0.25  -  10627  -  КОЛИЧЕСТВО ТРЕНИРОВОЧНЫХ ПЛОЩАДОК СООТВЕТСТВУЮЩИХ ГОСУДАРСТВЕННЫМ ТРЕБОВАНИЯМ
0.2  -  13254  -  КОЛИЧЕСТВО ПРОВЕДЕННЫХ ТРЕНИРОВОК СОРЕВНОВАНИЙ СМОТРОВКОНКУРСОВ В ОБЛАСТИ ГО И ЧС
0.167  -  1671  -  ПРОВЕДЕНИЕ ТРЕНИРОВОЧНЫХ УЧЕНИЙ С СИЛАМИ РСЧС РАЙОНА
0.143  -  12772  -  ДОЛЯ ГОРОЖАН ПОДДЕРЖИВАЮЩИХ СОБСТВЕННОЕ ЗДОРОВЬЕ ПРИ ПОМОЩИ ФИЗИЧЕСКИХ УПРАЖНЕНИЙ
0.125  -  19024  -  КОЛИЧЕСТВО ПРОВЕДЕННЫХ ТРЕНИРОВОК СОРЕВНОВАНИЙ СМОТРОВКОНКУРСОВ В ОБЛАСТИ ПРЕДУПРЕЖДЕНИЯ И ЛИКВИДАЦИИ ЧРЕЗВЫЧАЙНЫХ СИТУАЦИЙ 
0.111  -  15807  -  КОЛИЧЕСТВО ПРОВЕДЕННЫХ РАЙОННЫХ ТРЕНИРОВОК СОРЕВНОВАНИЙ СМОТРОВКОНКУРСОВ В ОБЛАСТИ ПРЕДУПРЕЖДЕНИЯ И ЛИКВИДАЦИИ ЧРЕЗВЫЧАЙНЫХ СИТУАЦИЙ
----------------------------------
Node ID:  594  keywords:  олимпиада тренировочный футбол футзал соревнование кубок физкультурник хоккей физкультурный первенство
Inds cnt:  478
Inds sample [0:10]:
1.0  -  17981  -  КОЛИЧЕСТВО СПОРТИВНЫХ УЧРЕЖДЕНИЙ
0.667  -  6159  -  ЧЕМПИОНАТ И ПЕРВЕНСТВО РК ПО КАРАТЭ
0.667  -  14359  -  КОЛИЧЕСТВО ФИЗКУЛЬТУРНЫХ И СПОРТИВНЫХ МЕРОПРИЯТИЙ
0.667  -  15306  -  КОЛИЧЕСТВО КОМАНД УЧАСТВУЮЩИХ В КУБКЕ И ЧЕМПИОНАТЕ РОССИИ ПО ВОЛЕЙБОЛУ
0.667  -  16868  -  КОЛИЧЕСТВО ФИЗКУЛЬТУРНЫХ И СПОРТИВНЫХ МЕРОПРИЯТИЙ
0.667  -  18600  -  ЧЕМПИОНАТ И ПЕРВЕНСТВО РК ПО КАРАТЭ 
0.6  -  1256  -  РЕЗУЛЬТАТ ВЫСТУПЛЕНИЙ В СЕЗОНЕ ХОККЕЙНОГО КЛУБА
0.6  -  3753  -  РЕЗУЛЬТАТ ВЫСТУПЛЕНИЙ В СЕЗОНЕ ФУТБОЛЬНОГО КЛУБА
0.5  -  1075  -  КОЛИЧЕСТВО КЛУБНЫХ ФОРМИРОВАНИЙ
0.5  -  1600  -  УВЕЛИЧЕНИЕ ЧИСЛА МЕРОПРИЯТИЙ ПРОВОДИМЫХ КЛУБНЫМИ УЧРЕЖДЕНИЯМИ
----------------------------------
Done
--- 1.1240642070770264 seconds ---

In [21]:
# Для более содержательного анализа было бы хорошо модифицировать наш граф, добавив туда еще два свойства
# - количесво показателей ассоциированных с вершний
# - общий вес показателей ассоциированных с вершиной

import igraph
# from igraph import *
import pickle
import time
import random
from time import gmtime, strftime
from typing import List

#---------------------------------------------------------------------------

#parameters
l_th = g_th
l_max_inds_count = g_max_inds_count # для определения имени файлов для чтения и запии

#---------------------------------------------------------------------------

def getIndicatorsByNode(pNodeIndex: int, pInds: list) -> []:
    l_list=[]
    for i in pInds:
        l_pt = i[3].get(pNodeIndex, None)
        if l_pt != None:
            l_list.append([i, l_pt])

    l_list.sort(key=lambda arg: arg[1],  reverse=True)

    return l_list

#---------------------------------------------------------------------------
# main part
print("--- Start time %s ---" % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
start_time = time.time()


# load graph
l_hier_graph = igraph.Graph().Load(g_path+'monocity_words_hier_graph_'+str(g_max_inds_count)+"_"+str(round(g_th*100))+".graphml")

#load indicators
pkl_file = open(g_path + 'monocity_inds_hier_'+str(l_max_inds_count)+'.pkl', 'rb')
inds = pickle.load(pkl_file)
pkl_file.close()
# print("Inds len: ", len(inds))

l_inds_cnt = []
l_ind_weigths = []

for v in l_hier_graph.vs():
    l_inds = getIndicatorsByNode(v.index, inds)
    l_inds_cnt.append(len(l_inds))
    l_ind_weigths.append(sum(i[1] for i in l_inds))

l_hier_graph.vs["inds_cnt"] = l_inds_cnt
l_hier_graph.vs["inds_weigth"] = l_ind_weigths

l_hier_graph.write_graphml(g_path+"monocity_words_hier_graph_"
                           +str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
                          )

print("Graph file: "+g_path+"monocity_words_hier_graph_"
      +str(l_max_inds_count)+"_"+str(round(l_th*100))+".graphml"
     )


print("Done")
end_time = time.time()
print("--- %s seconds ---" % (end_time - start_time))
#---------------------------------------------------------------------------


--- Start time Thu, 06 Apr 2017 14:51:19 ---
Graph file: D:/Projects/Aspirantura/GASU_SP/monocity_words_hier_graph_19995_40.graphml
Done
--- 2.374237537384033 seconds ---

In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]: