Serbian Legislation Network

Describing Serbian legislation system as a complex network.

Data

The latest version of each current legal document is available at Serbian Legal Information System website. Crawler and Scraper were developed in order to collect all republican legislations with their ID card and list of related regulations. Only legislations with ID card were scraped. Original collected data can be found in dataset/original_data/.

Network

In order to create legislation network, nodes and their links needs to be created.

Nodes

Every collected document is a node. List of document names extracted from their ID cards with custom made id number can be found in dataset/new_data/.

Links between nodes are full-explicit references. References extraction process for every document:

  1. Converting Serbian Cyrillic to Latin, and replacing special characters with their ASCII pairs (č -> c, š -> s...)
  2. Tokenization
  3. Stemming using Serbian Stemmer
  4. Joining stemmed words into space-separated text
  5. Searching for collected document names in joined text
  6. Saving detected reference in this_document_name\t\t\tfound_document_name format

After this, all detected references were aggregated into one document. Also, another document was created by replacing document names with their custom made id numbers.

Result of this process are references by document name and document id, and this documents are our legislation network. Also, references detected in every document can be found in dataset/new_data/graph/.

In order to evaluate process accuracy, full-explicit references were manually detected in 10 randomly selected documents. After validation, obtained accuracy of references extraction process was: %.


In [1]:
# imports
import pandas as pd
import codecs
import graphistry
import warnings
import networkx as nx
from networkx.algorithms import assortativity as assort
from networkx.algorithms import centrality as central
import matplotlib.pyplot as plt
from collections import OrderedDict
from operator import itemgetter
from collections import Counter
from itertools import islice
import numpy as np
import igraph as ig
# setup
warnings.filterwarnings('ignore')
api_key = open('API_key.txt').read()
graphistry.register(key=api_key)
%matplotlib inline

In [2]:
def load_num_doc(file_path):
    """
    Reading num - doc dictonary for mapping document name and id
    """
    f = codecs.open(file_path, 'r', 'utf8')
    lines = f.readlines()
    f.close()
    num_doc_mapper = {}
    clean_lines = [line[:-2] for line in lines if line.endswith('\r\n')]
    clean_lines.append(lines[-1])
    for line in clean_lines:
        number = int(line.split(',')[0])
        text = line[len(str(number))+1:]
        num_doc_mapper[number] = text
    return num_doc_mapper

In [3]:
def sort_dictionary_by_value_asc(input_dict):
    output_dict = OrderedDict(sorted(input_dict.items(), key=itemgetter(1)))
    return output_dict

def sort_dictionary_by_value_desc(input_dict):
    output_dict = OrderedDict(sorted(input_dict.items(), key=itemgetter(1)))
    return output_dict

In [4]:
# reading graph
edges = pd.read_csv('dataset/new_data/all_text_lines.txt', sep='\t\t\t', names=['src', 'dest'])
print(edges.head())
# reading igraph from file
this_igraph = ig.Graph.Read_Ncol('dataset/new_data/all_num_lines.txt', directed=True)


                                                 src                    dest
0  ustavni zakon za sprovodjenje ustava republike...  zakon o ministarstvima
1  ustavni zakon za sprovodjenje ustava republike...  ustav republike srbije
2  uredba o prestanku vazenja uredbe o osnivanju ...           zakon o vladi
3                       uredba o vojnoj legitimaciji           zakon o vladi
4                       uredba o vojnoj legitimaciji   zakon o vojsci srbije

In [5]:
# visualization using graphistry
graphistry.bind(source='src', destination='dest').plot(edges)


Out[5]:

Network Science Measures


In [6]:
# reading num - name dictionary
num_doc_mapper = load_num_doc('dataset/new_data/new_num_doc_sorted.txt')

# reading and creating network using networkx
graph = nx.read_edgelist('dataset/new_data/all_num_lines.txt', create_using=nx.DiGraph(), nodetype=int)
print(nx.info(graph))


Name: 
Type: DiGraph
Number of nodes: 5391
Number of edges: 17343
Average in degree:   3.2170
Average out degree:   3.2170

In [7]:
# highest degrees
print("Nodes with highest degrees: (in + out)\n")
degrees_high = sort_dictionary_by_value_desc(graph.degree())
degrees_high_count = Counter(degrees_high)
for k, v in degrees_high_count.most_common(5):
    print('%s: %i (%i + %i)\n' % (num_doc_mapper[k], v, graph.in_degree(k), graph.out_degree(k)))


Nodes with highest degrees: (in + out)

zakon o vladi: 1492 (1482 + 10)

zakon o planiranju i izgradnji: 319 (284 + 35)

zakon o radu: 310 (290 + 20)

zakon o zastiti zivotne sredine: 302 (282 + 20)

zakon o carinskoj tarifi: 289 (289 + 0)


In [8]:
# lowest degrees
print("Nodes with lowest degrees: (in + out)\n")
deegrees_low = sort_dictionary_by_value_asc(graph.degree())
deegrees_low_count = islice(deegrees_low.items(), 0, 5)
for k, v in deegrees_low_count:
    print('%s: %i (%i + %i)\n' % (num_doc_mapper[k], v, graph.in_degree(k), graph.out_degree(k)))


Nodes with lowest degrees: (in + out)

pravilnik o upotrebi grba, zastave i himne republike srbije u diplomatsko-konzularnim predstavnistvima republike srbije i na zvanicnim dokumentima ministarstva spoljnih poslova: 1 (0 + 1)

pravilnik o blizim uslovima za cuvanje, upravljanje i distribuciju krvi i komponenata krvi: 1 (0 + 1)

zakljucak o upotrebi grba, zastave i himne republike srbije: 1 (1 + 0)

pravilnik o sistemu pracenja, nacinu oznacavanja i drugim pitanjima od znacaja za identifikaciju svakog pojedinacnog uzimanja krvi, odnosno pojedinacne jedinice krvi, kao i o nacinu, postupku i sadrzaju obrasca za prijavljivanje ozbiljnih nezeljenih dogadjaja, odnosno ozbiljnih nezeljenih reakcija: 1 (0 + 1)

pravilnik o nacinu upisa cinjenice drzavljanstva u maticnu knjigu rodjenih, obrascima za vodjenje evidencija o resenjima o sticanju i prestanku drzavljanstva i obrascu uverenja o drzavljanstvu: 1 (0 + 1)


In [9]:
# highest in_degrees
print("Nodes with highest in degrees:\n")
in_degrees_high = sort_dictionary_by_value_desc(graph.in_degree())
in_degrees_high_count = Counter(in_degrees_high)
for k, v in in_degrees_high_count.most_common(5):
    print('%s: %i\n' % (num_doc_mapper[k], v))


Nodes with highest in degrees:

zakon o vladi: 1482

zakon o radu: 290

zakon o carinskoj tarifi: 289

zakon o planiranju i izgradnji: 284

zakon o zastiti zivotne sredine: 282


In [10]:
# highest out_degrees
print("Nodes with highest out degrees:\n")
out_degrees_high = sort_dictionary_by_value_desc(graph.out_degree())
out_degrees_high_count = Counter(out_degrees_high)
for k, v in out_degrees_high_count.most_common(5):
    print('%s: %i\n' % (num_doc_mapper[k], v))


Nodes with highest out degrees:

strategija prevencije i zastite od diskriminacije: 76

zakljucak (o usvajanju nacionalnog akcionog plana za koriscenje obnovljivih izvora energije republike srbije): 73

zakljucak o usvajanju treceg akcionog plana za energetsku efikasnost republike srbije za period do 2018. godine: 67

uredba o utvrdjivanju prostornog plana podrucja posebne namene za infrastrukturni koridor visokonaponskog dalekovoda 110 kv broj 113/x od ts nis 1 do vrle III: 64

strategija reforme javne uprave u republici srbiji: 59

The diameter of a graph is the maximum eccentricity of any vertex in the graph. That is, d is the greatest distance between any pair of vertices.
For directed graphs, the graph density is defined as D = |E| / (|V| (|V| - 1)) where E is the number of edges and V is the number of vertices in the graph.


In [11]:
print("Graph diameter: {0}".format(this_igraph.diameter()))
print("Average path length: {0}".format(this_igraph.average_path_length()))
print("Graph density: {0}".format(this_igraph.density()))


Graph diameter: 14
Average path length: 4.698433048179542
Graph density: 0.0005982622724812088

Cycles

Cycle found via a directed, depth-first traversal.


In [12]:
print("Cycles: \n")
cycles = nx.algorithms.find_cycle(graph)
for cycle in cycles:
    print('%s --> %s\n' % (num_doc_mapper[cycle[0]], num_doc_mapper[cycle[1]]))


Cycles: 

zakon o drzavnoj upravi --> zakon o javnim sluzbama

zakon o javnim sluzbama --> zakon o zdravstvenoj zastiti

zakon o zdravstvenoj zastiti --> zakon o budzetskom sistemu

zakon o budzetskom sistemu --> zakon o platama drzavnih sluzbenika i namestenika

zakon o platama drzavnih sluzbenika i namestenika --> uredba o koeficijentima za obracun i isplatu plata imenovanih i postavljenih lica i zaposlenih u drzavnim organima

uredba o koeficijentima za obracun i isplatu plata imenovanih i postavljenih lica i zaposlenih u drzavnim organima --> poslovnik vlade

poslovnik vlade --> zakon o drzavnoj upravi

Assortativity

The average degree connectivity is the average nearest neighbor degree of nodes with degree k.


In [13]:
print("Nodes with highest average degree connectivity: \n")
adc_high = sort_dictionary_by_value_desc(assort.average_degree_connectivity(graph))
adc_high_count = Counter(adc_high)
for k, v in adc_high_count.most_common(5):
    print('k=%i: %f\n' % (k, v))


Nodes with highest average degree connectivity: 

k=2: 346.546429

k=3: 270.486461

k=1: 241.209135

k=4: 184.614744

k=8: 174.184685

Centrality

In graph theory and network analysis, indicators of centrality identify the most important vertices within a graph.

Degree

The degree centrality for a node v is the fraction of nodes it is connected to.
The in-degree centrality for a node v is the fraction of nodes its incoming edges are connected to.
The out-degree centrality for a node v is the fraction of nodes its outgoing edges are connected to.


In [14]:
print("Nodes with highest degree centrality: \n")
dc_high = sort_dictionary_by_value_desc(central.degree_centrality(graph))
dc_high_count = Counter(dc_high)
for k, v in dc_high_count.most_common(5):
    print('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with highest degree centrality: 

zakon o vladi: 0.276809

zakon o planiranju i izgradnji: 0.059184

zakon o radu: 0.057514

zakon o zastiti zivotne sredine: 0.056030

zakon o carinskoj tarifi: 0.053618


In [15]:
print("Nodes with highest in-degree centrality: \n")
idc_high = sort_dictionary_by_value_desc(central.in_degree_centrality(graph))
idc_high_count = Counter(idc_high)
for k, v in idc_high_count.most_common(5):
    print('%s: %f\n' % (num_doc_mapper[k], v))
    
print("\n\nNodes with highest out-degree centrality: \n")
odc_high = sort_dictionary_by_value_desc(central.out_degree_centrality(graph))
odc_high_count = Counter(odc_high)
for k, v in odc_high_count.most_common(5):
    print('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with highest in-degree centrality: 

zakon o vladi: 0.274954

zakon o radu: 0.053803

zakon o carinskoj tarifi: 0.053618

zakon o planiranju i izgradnji: 0.052690

zakon o zastiti zivotne sredine: 0.052319



Nodes with highest out-degree centrality: 

strategija prevencije i zastite od diskriminacije: 0.014100

zakljucak (o usvajanju nacionalnog akcionog plana za koriscenje obnovljivih izvora energije republike srbije): 0.013544

zakljucak o usvajanju treceg akcionog plana za energetsku efikasnost republike srbije za period do 2018. godine: 0.012430

uredba o utvrdjivanju prostornog plana podrucja posebne namene za infrastrukturni koridor visokonaponskog dalekovoda 110 kv broj 113/x od ts nis 1 do vrle III: 0.011874

strategija reforme javne uprave u republici srbiji: 0.010946

Closeness

Closenes centrality of a node u is the reciprocal of the sum of the shortest path distances form u to all n-1 other nodes. Thus the more central a node is, the closer it is to all other nodes.


In [16]:
print("Nodes with highest closeness centrality: \n")
cc_high = sort_dictionary_by_value_desc(central.closeness_centrality(graph))
cc_high_count = Counter(cc_high)
for k, v in cc_high_count.most_common(5):
    print('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with highest closeness centrality: 

uredba o utvrdjivanju programa implementacije regionalnog prostornog plana za podrucje kolubarskog i macvanskog upravnog okruga za period od 2016. do 2020. godine: 0.045991

zakljucak o usvajanju treceg akcionog plana za energetsku efikasnost republike srbije za period do 2018. godine: 0.044253

fiskalna strategija za 2017. godinu sa projekcijama za 2018. i 2019. godinu: 0.043037

uredba o utvrdjivanju prostornog plana podrucja posebne namene infrastrukturnog koridora visokonaponskog dalekovoda 2h110 kV kraljevo 3  novi pazar 1: 0.042429

uredba o utvrdjivanju regionalnog prostornog plana za podrucje sumadijskog, pomoravskog, raskog i rasinskog upravnog okruga: 0.041519

Betweenness

Computing the shortest-path betweenness centrality for nodes. Betweenness centrality of a node v is the sum of the fraction of all-pairs shortest paths that pass through v.
Betweenness centrality quantifies the number of times a node actts as a bridge along the shortest path between two other nodes.


In [17]:
print("Nodes with lowest betweenness centrality: \n")
bc_low = sort_dictionary_by_value_asc(central.betweenness_centrality(graph))
bc_low_count = islice(bc_low.items(), 0, 5)
for k, v in bc_low_count:
    print('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with lowest betweenness centrality: 

uredba o utvrdjivanju izvornika velikog i malog grba, izvornika zastave i notnog zapisa himne republike srbije: 0.000000

uredba o blizim kriterijumima, nacinu i uslovima za izvodjenje himne republike srbije: 0.000000

pravilnik o upotrebi grba, zastave i himne republike srbije u diplomatsko-konzularnim predstavnistvima republike srbije i na zvanicnim dokumentima ministarstva spoljnih poslova: 0.000000

pravilnik o blizim uslovima za cuvanje, upravljanje i distribuciju krvi i komponenata krvi: 0.000000

zakljucak o upotrebi grba, zastave i himne republike srbije: 0.000000

Page Rank

PageRank computes a ranking of the nodes in the graph based on the structure of the incoming links.


In [18]:
# highest PR
print("Nodes with highest PageRank values: \n")
pr_high = sort_dictionary_by_value_desc(nx.algorithms.pagerank(graph))
pr_high_count = Counter(pr_high)
for k, v in pr_high_count.most_common(10):
    print('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with highest PageRank values: 

zakon o privrednim drustvima: 0.030091

zakon o vladi: 0.026844

zakon o opstem upravnom postupku: 0.026440

zakon o preduzecima: 0.025308

zakon o radu: 0.014170

zakon o obligacionim odnosima: 0.013392

ustav republike srbije: 0.011158

zakon o drzavnoj upravi: 0.011156

zakon o zastiti podataka o licnosti: 0.011069

zakon o drzavnim sluzbenicima: 0.010073


In [19]:
# lowest PR
print("Nodes with lowest PageRank values: \n")
pr_low = sort_dictionary_by_value_asc(nx.algorithms.pagerank(graph))
pr_low_count = islice(pr_low.items(), 0, 10)
for k,  v in pr_low_count:
    print('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with lowest PageRank values: 

uredba o utvrdjivanju izvornika velikog i malog grba, izvornika zastave i notnog zapisa himne republike srbije: 0.000042

uredba o blizim kriterijumima, nacinu i uslovima za izvodjenje himne republike srbije: 0.000042

pravilnik o upotrebi grba, zastave i himne republike srbije u diplomatsko-konzularnim predstavnistvima republike srbije i na zvanicnim dokumentima ministarstva spoljnih poslova: 0.000042

pravilnik o blizim uslovima za cuvanje, upravljanje i distribuciju krvi i komponenata krvi: 0.000042

zakljucak o upotrebi grba, zastave i himne republike srbije na sportskim takmicenjima na kojima ucestvuju reprezentativci, odnosno reprezentacije republike srbije: 0.000042

pravilnik o sistemu pracenja, nacinu oznacavanja i drugim pitanjima od znacaja za identifikaciju svakog pojedinacnog uzimanja krvi, odnosno pojedinacne jedinice krvi, kao i o nacinu, postupku i sadrzaju obrasca za prijavljivanje ozbiljnih nezeljenih dogadjaja, odnosno ozbiljnih nezeljenih reakcija: 0.000042

pravilnik o nacinu upisa cinjenice drzavljanstva u maticnu knjigu rodjenih, obrascima za vodjenje evidencija o resenjima o sticanju i prestanku drzavljanstva i obrascu uverenja o drzavljanstvu: 0.000042

pravilnik o obrascu pismene izjave da se republika srbija smatra svojom drzavom: 0.000042

pravilnik o sadrzaju obrasca izjave o pristanku primaoca organa za presadjivanje organa: 0.000042

odluka o proglasenju dana nauke u republici srbiji: 0.000042

Katz

Katz centrality computes the centrality for a node based on the centrality of its neigbors. It is a generalization of the eigenvector centrality.


In [20]:
# highest K
print("Nodes with highest Katz centrality: \n")
k_high = sort_dictionary_by_value_desc(nx.katz_centrality_numpy(graph))
k_high_count = Counter(k_high)
for k, v in k_high_count.most_common(10):
    print ('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with highest Katz centrality: 

zakon o opstem upravnom postupku: 0.345748

zakon o privrednim drustvima: 0.284821

zakon o obligacionim odnosima: 0.269988

zakon o izvrsenju i obezbedjenju: 0.226137

zakon o radu: 0.198223

porodicni zakon: 0.176478

zakon o trzistu kapitala: 0.176414

zakon o parnicnom postupku: 0.171455

krivicni zakonik: 0.170135

zakon o tajnosti podataka: 0.165140


In [21]:
# lowest Katz
print("Nodes with lowest Katz centrality: \n")
k_low = sort_dictionary_by_value_asc(nx.katz_centrality_numpy(graph))
k_low_count = islice(k_low.items(), 0, 10)
for k, v in k_low_count:
    print('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with lowest Katz centrality: 

zakon o vladi: -0.050060

zakon o predsedniku republike: -0.004407

zakon o strateskoj proceni uticaja na zivotnu sredinu: -0.002881

zakon o carinskoj tarifi: -0.002708

pravilnik o proglasenju i zastiti strogo zasticenih i zasticenih divljih vrsta biljaka, zivotinja i gljiva: -0.002605

zakon o bezbednosti i interoperabilnosti zeleznice: -0.002590

zakon o zeleznici: -0.002408

zakon o zastiti prirode: -0.002378

zakon o transportu opasnog tereta: -0.002358

zakon o metrologiji: -0.002186

Eigenvector

Eigenvector centrality computes the centrality for a node based on the centrality of its neighbors. It assigns relative scores to all nodes in the network based on the concept that connections to high-scoring nodes contribute mode to the score of the node in question that equal connections to low-scoring nodes.


In [22]:
# highest ev
print("Nodes with highest Eigenvector centrality: \n")
ev_high = sort_dictionary_by_value_desc(nx.eigenvector_centrality(graph))
ev_high_count = Counter(ev_high)
for k, v in ev_high_count.most_common(10):
    print('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with highest Eigenvector centrality: 

zakon o opstem upravnom postupku: 0.356343

zakon o privrednim drustvima: 0.279929

zakon o obligacionim odnosima: 0.260806

zakon o izvrsenju i obezbedjenju: 0.211835

zakon o radu: 0.210844

porodicni zakon: 0.166009

krivicni zakonik: 0.165831

zakon o tajnosti podataka: 0.163596

zakon o trzistu kapitala: 0.162711

zakon o parnicnom postupku: 0.159535


In [23]:
# lowest ev
print("Nodes with lowest Eigenvector centrality: \n")
ev_low = sort_dictionary_by_value_asc(nx.eigenvector_centrality(graph))
ev_low_count = islice(ev_low.items(),0, 10)
for k, v in ev_low_count:
    print ('%s: %f\n' % (num_doc_mapper[k], v))


Nodes with lowest Eigenvector centrality: 

zakon o zdravstvenoj dokumentaciji i evidencijama u oblasti zdravstva: 0.000000

uredba o utvrdjivanju izvornika velikog i malog grba, izvornika zastave i notnog zapisa himne republike srbije: 0.000000

uredba o blizim kriterijumima, nacinu i uslovima za izvodjenje himne republike srbije: 0.000000

pravilnik o upotrebi grba, zastave i himne republike srbije u diplomatsko-konzularnim predstavnistvima republike srbije i na zvanicnim dokumentima ministarstva spoljnih poslova: 0.000000

pravilnik o blizim uslovima za cuvanje, upravljanje i distribuciju krvi i komponenata krvi: 0.000000

zakljucak o upotrebi grba, zastave i himne republike srbije: 0.000000

zakljucak o upotrebi grba, zastave i himne republike srbije na sportskim takmicenjima na kojima ucestvuju reprezentativci, odnosno reprezentacije republike srbije: 0.000000

pravilnik o sistemu pracenja, nacinu oznacavanja i drugim pitanjima od znacaja za identifikaciju svakog pojedinacnog uzimanja krvi, odnosno pojedinacne jedinice krvi, kao i o nacinu, postupku i sadrzaju obrasca za prijavljivanje ozbiljnih nezeljenih dogadjaja, odnosno ozbiljnih nezeljenih reakcija: 0.000000

pravilnik o nacinu upisa cinjenice drzavljanstva u maticnu knjigu rodjenih, obrascima za vodjenje evidencija o resenjima o sticanju i prestanku drzavljanstva i obrascu uverenja o drzavljanstvu: 0.000000

pravilnik o obrascu pismene izjave da se republika srbija smatra svojom drzavom: 0.000000

Clustering

In graph theory, a clustering coefficient is a measure of the degree to which nodes in a graph tend to cluster together. The global version of this measure was designed to give an overall indication of the clustering in the network.
The global clustering coefficient is based on triplets of nodes. A triplet consists of three connected nodes. A triangle therefore includes three closed triplets, one centered on each of the nodes. The global clustering coefficient is the number of closed triplets (or 3 x triangles) over the total number of triplets (both open and closed):
C = 3 x number of triangles / number of connected triplets of vertices = number of closed triplets / number of connected triplets of vertices.


In [24]:
print("Global Clustering Coefficient: {0}".format(nx.transitivity(graph)))


Global Clustering Coefficient: 0.09853584921815632

Community Detection

Latapy and Pons algorithm for community detection base on random walks. This algorithm (Walktrap) can be adatped to directed edges, weights, and can alter resolution by walk length. Basic idea: Simulate many short random walks on the network and compute pairwise similarity measures bassed on these walks. Use these similarity values to aggreggate vertices into communities. Time Complexity: depends on walk length, O(|V|^2 log |V|) typically.


In [25]:
dendogram = this_igraph.community_walktrap(steps=10)
clusters = dendogram.as_clustering()
membership = clusters.membership
memberships_dict = {}
for name, membership in zip(this_igraph.vs["name"], membership):
    if membership not in memberships_dict:
        memberships_dict[membership] = []
    memberships_dict[membership].append(num_doc_mapper[int(name)])
print("Total number of communities: {0}".format(len(memberships_dict)))
# number of members 
memership_nums = {}
for k in memberships_dict:
    memership_nums[k] = len(memberships_dict[k])


Total number of communities: 141

In [26]:
# top communities
print("Communities with most members: \n")
mem_num_high = sort_dictionary_by_value_desc(memership_nums)
mem_num_high_count = Counter(mem_num_high)
for k, v in mem_num_high_count.most_common(5):
    print('\nCommunity %i with %i members:' % (k, v))
    #print(memberships_dict[k])


Communities with most members: 


Community 0 with 1687 members:

Community 7 with 985 members:

Community 1 with 502 members:

Community 3 with 334 members:

Community 6 with 288 members:

In [27]:
# bottom communities
print("Communities with least members: \n")
mem_num_low = sort_dictionary_by_value_asc(memership_nums)
mem_num_low_count = islice(mem_num_low.items(), 0, 5)
for k, v in mem_num_low_count:
    print('\nCommunity %i with %i members:' % (k, v))
    print(memberships_dict[k])


Communities with least members: 


Community 60 with 1 members:
['uputstvo o nacinu pretvaranja kredita odobrenih od banaka nosiocima primarne poljoprivredne proizvodnje i turisticke privrede u javni dug federacije']

Community 92 with 1 members:
['zakon o davanju kontragarancije republike srbije srbiji i crnoj gori po zajmu evropske zajednice za izmirenje dospelih a neplacenih ugovornih obaveza prema evropskoj investicionoj banci']

Community 5 with 2 members:
['pravilnik o nacinu vodjenja evidencije o clanovima porodice lica na obaveznoj vojnoj sluzbi', 'zakon o ostvarivanju zastite clanova porodice lica na obaveznoj vojnoj sluzbi']

Community 10 with 2 members:
['pravilnik o nacinu nosenja uniforme policijskih sluzbenika', 'uredba o izgledu uniforme i oznaka policijskih sluzbenika']

Community 11 with 2 members:
['zakljucak o upotrebi grba, zastave i himne republike srbije na sportskim takmicenjima na kojima ucestvuju reprezentativci, odnosno reprezentacije republike srbije', 'zakljucak o upotrebi grba, zastave i himne republike srbije']

In [ ]: