$$ \newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} \newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} \renewcommand{\mod}{\,\mathrm{mod}\,} \renewcommand{\div}{\,\mathrm{div}\,} \newcommand{\metar}{\,\mathrm{m}} \newcommand{\cm}{\,\mathrm{cm}} \newcommand{\dm}{\,\mathrm{dm}} \newcommand{\litar}{\,\mathrm{l}} \newcommand{\km}{\,\mathrm{km}} \newcommand{\s}{\,\mathrm{s}} \newcommand{\h}{\,\mathrm{h}} \newcommand{\minut}{\,\mathrm{min}} \newcommand{\kmh}{\,\mathrm{\frac{km}{h}}} \newcommand{\ms}{\,\mathrm{\frac{m}{s}}} \newcommand{\mss}{\,\mathrm{\frac{m}{s^2}}} \newcommand{\mmin}{\,\mathrm{\frac{m}{min}}} \newcommand{\smin}{\,\mathrm{\frac{s}{min}}} $$

Prijavi problem


Obeleži sve kategorije koje odgovaraju problemu

Još detalja - opišite nam problem


Uspešno ste prijavili problem!
Status problema i sve dodatne informacije možete pratiti klikom na link.
Nažalost nismo trenutno u mogućnosti da obradimo vaš zahtev.
Molimo vas da pokušate kasnije.

Тезаурус EuroVoc

У овој секцији упознаћемо детаљније тезаурус EuroVoc и начин на који је организован.

Тезаурус EuroVoc је врста речника која обједињује концепте који се придружују званичним документима Европске уније зарад систематичне организације. На пример, документу који се бави миграцијама се могу придружити концепти family migration или geographical mobility. Овако контролисани вокабулар омогућава униформу организацију докумената између свих чланица Европске уније и њихово лакше претраживање.

Организација тезауруса EuroVoc (слика је преузета са ове адресе)

Информације које су садржане у тезаурусу су физички подељене у већи број датотека и могу се преузети са званичне адресе у већем броју формата. Ми ћемо користити архиву eurovoc_xml.zip која садржи датотеке у формату XML, као и попис свих концепата DOC_1.xml.

Посебно, на нивоу архиве пратићемо документе који се односе на енглески језик тј. документе који у називу имају суфикс _eng.

За обраду информација записаних у XML формату користићемо библиотеку BeаutifulSoup. Функције ове библиотеке нам омогућавају да се лако крећемо кроз хијерархијску структуру докумената, као и да једноставно издвојимо елементе на основу имена или атрибута који им је придружен.

In [1]:
from bs4 import BeautifulSoup

Домени

На највишем нивоу хијерархије тезауруса налазе се домени. Домени се представљају двоцифреним идентификаторима и има их укупно 21. Физички, информације о доменима тезауруса се налазе у датотеци dom_en.xml. Следећим блоком кода се из ове датотека могу издвојити идентификатори и имена домена.

In [2]:
domains_file = open('data/eurovoc_thesaurus/dom_en.xml', 'r') 
domains_file_content = domains_file.read()
In [3]:
domains_soup = BeautifulSoup(domains_file_content, 'html.parser')
domain_ids = [id.get_text() for id in domains_soup.find_all('domaine_id')]
domain_names = [name.get_text() for name in domains_soup.find_all('libelle')]
In [4]:
print('Identifikatori i imena domena: ')
for id, name in zip (domain_ids, domain_names):
    print (id, name)
Identifikatori i imena domena: 
04 POLITICS
08 INTERNATIONAL RELATIONS
10 EUROPEAN UNION
12 LAW
16 ECONOMICS
20 TRADE
24 FINANCE
28 SOCIAL QUESTIONS
32 EDUCATION AND COMMUNICATIONS
36 SCIENCE
40 BUSINESS AND COMPETITION
44 EMPLOYMENT AND WORKING CONDITIONS
48 TRANSPORT
52 ENVIRONMENT
56 AGRICULTURE, FORESTRY AND FISHERIES
60 AGRI-FOODSTUFFS
64 PRODUCTION, TECHNOLOGY AND RESEARCH
66 ENERGY
68 INDUSTRY
72 GEOGRAPHY
76 INTERNATIONAL ORGANISATIONS

Сличан блок кода искористићемо да сачувамо овај пар идентификатора и имена у датотеци domains_with_id_and_name.txt.

In [5]:
domains_with_id_and_name = {}

for id, name in zip (domain_ids, domain_names):
    domains_with_id_and_name[id] = name
    
with open('data/domains_with_id_and_name.txt', 'w') as file:
    file.write(str(domains_with_id_and_name))

Микротезауруси

Микротезауруси представљају сегменте тезауруса који се односе на специфичне домене. Њих карактеришу четвороцифрени идентификатори чије се прве две цифре преклапају са идентификатором домена. Тако, на пример, домену "наука" са идентификатором 36 одговарају два микротезауруса 3606 и 3611 - први обједињује концепте који се односе на природне и примењене науке, а други концепте који се односе на хуманистичке науке. Микротезауруса има укупно 127, а њихова имена и кодови се могу прочитати из датотеке са именом thes_en.xml.

Следећим блоком кода ћемо издвојити имена и кодове микротезауруса.

In [6]:
microthesaurus_file = open('data/eurovoc_thesaurus/thes_en.xml', 'r') 
microthesaurus_file_content = microthesaurus_file.read()
In [7]:
microthesaurus_soup = BeautifulSoup(microthesaurus_file_content, 'html.parser')
microthesaurus_ids = [id.get_text() for id in microthesaurus_soup.find_all('thesaurus_id')]
microthesaurus_names = [name.get_text() for name in microthesaurus_soup.find_all('libelle')]

Identifikatori i imena mikrotezaurusa:

In [8]:
zip(microthesaurus_ids, microthesaurus_names)
Out[8]:
<zip at 0x28b2ef46200>
In [ ]:
 

На основу прочитаних информација можемо објединити домене и микротезаурусе који им припадају. Искористићемо својство да се прве две цифре идентификатора микротезауруса преклапају са идентификатором домена.

In [9]:
microthesauruses_per_domain = {}

for domain_id in domain_ids:
    microthesauruses_per_domain[domain_id] = []

for microthesaurus_id in microthesaurus_ids:
    domain_id = microthesaurus_id[0:2]
    microthesauruses_per_domain[domain_id].append(microthesaurus_id)  
In [10]:
microthesauruses_per_domain
Out[10]:
{'04': ['0406', '0411', '0416', '0421', '0426', '0431', '0436'],
 '08': ['0806', '0811', '0816', '0821'],
 '10': ['1006', '1011', '1016', '1021'],
 '12': ['1206', '1211', '1216', '1221', '1226', '1231', '1236'],
 '16': ['1606', '1611', '1616', '1621', '1626', '1631'],
 '20': ['2006', '2011', '2016', '2021', '2026', '2031', '2036'],
 '24': ['2406',
  '2411',
  '2416',
  '2421',
  '2426',
  '2431',
  '2436',
  '2441',
  '2446',
  '2451'],
 '28': ['2806',
  '2811',
  '2816',
  '2821',
  '2826',
  '2831',
  '2836',
  '2841',
  '2846'],
 '32': ['3206', '3211', '3216', '3221', '3226', '3231', '3236'],
 '36': ['3606', '3611'],
 '40': ['4006', '4011', '4016', '4021', '4026', '4031'],
 '44': ['4406', '4411', '4416', '4421', '4426'],
 '48': ['4806', '4811', '4816', '4821', '4826'],
 '52': ['5206', '5211', '5216'],
 '56': ['5606', '5611', '5616', '5621', '5626', '5631', '5636', '5641'],
 '60': ['6006', '6011', '6016', '6021', '6026', '6031', '6036'],
 '64': ['6406', '6411', '6416'],
 '66': ['6606', '6611', '6616', '6621', '6626'],
 '68': ['6806',
  '6811',
  '6816',
  '6821',
  '6826',
  '6831',
  '6836',
  '6841',
  '6846'],
 '72': ['7206', '7211', '7216', '7221', '7226', '7231', '7236', '7241'],
 '76': ['7606', '7611', '7616', '7621', '7626']}

Највећи број микротезауруса је придружен домену "финансије" са идентификатором 24.

In [11]:
for (domain, all_thesauruses) in microthesauruses_per_domain.items():
    print ('Domen ', domain, ': broj mikrotezaurusa: ', len(all_thesauruses))
Domen  04 : broj mikrotezaurusa:  7
Domen  08 : broj mikrotezaurusa:  4
Domen  10 : broj mikrotezaurusa:  4
Domen  12 : broj mikrotezaurusa:  7
Domen  16 : broj mikrotezaurusa:  6
Domen  20 : broj mikrotezaurusa:  7
Domen  24 : broj mikrotezaurusa:  10
Domen  28 : broj mikrotezaurusa:  9
Domen  32 : broj mikrotezaurusa:  7
Domen  36 : broj mikrotezaurusa:  2
Domen  40 : broj mikrotezaurusa:  6
Domen  44 : broj mikrotezaurusa:  5
Domen  48 : broj mikrotezaurusa:  5
Domen  52 : broj mikrotezaurusa:  3
Domen  56 : broj mikrotezaurusa:  8
Domen  60 : broj mikrotezaurusa:  7
Domen  64 : broj mikrotezaurusa:  3
Domen  66 : broj mikrotezaurusa:  5
Domen  68 : broj mikrotezaurusa:  9
Domen  72 : broj mikrotezaurusa:  8
Domen  76 : broj mikrotezaurusa:  5
In [ ]:
 

Концепти и њихове релације

Концепти тезауруса су, такође, хијерархијски организовани. Главни концепти (енгл. top terms) се налазе на врху хијерархије и везани су за сам микротезаурус, док су преостали концепти везани за главне концепте према нивоима специфичности. Актуелна верзија тезауруса подржава везе генеричког (на пример, концепти protected area и national park) и партитивног (на пример, chemistry и analytical chemistry) типа, као и угњежђавања највише дубине два.

Издвајање свих концепата микротезауруса

Сви концепти тезауруса се могу прочитати из датотеке DOC_1.xml. Нама ће бити занимљиво да издвојимо концепте који припадају одређеном микротезаурусу - идентификатори концепата ће нам значити за само кодирање док ће нам имена ових концепата омогућити да лакше испратимо организацију.

Следећим блоком кода ћемо припремити датотеку DOC_1.xml за рад, док ће нам функција get_concepts_for_microthesaurus омогућити да из овако припремљене датотеке за задати идентификатор микротезауруса прочитамо концепте који му припадају.

In [12]:
main_thesaurus_file = open('data/eurovoc_thesaurus/DOC_1.xml', 'r', encoding='utf-8')
main_thesaurus_content = main_thesaurus_file.read()
In [13]:
main_thesaurus_soup = BeautifulSoup(main_thesaurus_content, 'html.parser')
In [14]:
def get_concepts_for_microthesaurus(microthesaurus_id, main_thesaurus_soup):
    concepts = {}
    for record in main_thesaurus_soup.find_all(thesaurus_id=microthesaurus_id):
        id = record['id']
        concept_wrapper = record.parent.parent.find_all('xs:documentation')[0].get_text()
        concept = concept_wrapper[0:concept_wrapper.find('/')-1]
        concepts[id] = concept
    return concepts

У наставку можемо видети све концепте микротезауруса за природне и примењене науке.

In [15]:
get_concepts_for_microthesaurus('3606', main_thesaurus_soup)
Out[15]:
{'1147': 'geochemistry',
 '1148': 'geography',
 '1149': 'economic geography',
 '1150': 'political geography',
 '1151': 'geology',
 '1152': 'geophysics',
 '1246': 'histology',
 '1276': 'hydrogeology',
 '1278': 'hydrology',
 '1835': 'mathematics',
 '1892': 'meteorology',
 '1896': 'metrology',
 '1936': 'mineralogy',
 '2114': 'oceanography',
 '2232': 'parasitology',
 '2367': 'pharmacology',
 '2373': 'photochemistry',
 '2376': 'nuclear physics',
 '3282': 'neurobiology',
 '3291': 'acoustics',
 '3292': 'optics',
 '3293': 'cybernetics',
 '3294': 'petrology',
 '3790': 'astronomy',
 '3925': 'information science',
 '3931': 'soil science',
 '3941': 'life sciences',
 '3946': 'physical sciences',
 '3949': 'applied sciences',
 '3952': 'earth sciences',
 '4107': 'aerodynamics',
 '4108': 'thermodynamics',
 '4109': 'plasma physics',
 '4110': 'laser physics',
 '4176': 'seismology',
 '442765': 'animal taxonomy',
 '442791': 'plant taxonomy',
 '4770': 'volcanology',
 '4810': 'zoology',
 '4889': 'biochemistry',
 '4921': 'biology',
 '5028': 'botany',
 '5269': 'cartography',
 '5287': 'ionising radiation',
 '5298': 'fundamental particle',
 '5299': 'atom',
 '5300': 'analytical chemistry',
 '5301': 'spectrometry',
 '5303': 'cytology',
 '5338': 'radiobiology',
 '5608': 'embryo and foetus',
 '5651': 'genetics',
 '5740': 'microorganism',
 '5966': 'chemistry',
 '5968': 'industrial chemistry',
 '6111': 'enzyme',
 '6260': 'DNA',
 '632': 'ecology',
 '6381': 'soil analysis',
 '6382': 'space science',
 '6383': 'astronautics',
 '6384': 'climatology',
 '6385': 'bioclimatology',
 '6386': 'soil chemistry',
 '6387': 'cultural geography',
 '6388': 'human geography',
 '6389': 'regional geography',
 '6390': 'geomorphology',
 '6391': 'sedimentology',
 '6392': 'soil type',
 '6715': 'hazard science',
 '6716': 'cosmology',
 '6744': 'eugenics',
 '685': 'agronomy',
 '707': 'electrochemistry',
 '709': 'electronics',
 '710': 'electrotechnology',
 '7218': 'geographical information system',
 '7360': 'historical geography',
 '7410': 'biometrics',
 '7955': 'stem cell',
 '8438': 'geodesy',
 'c_2c5a05a0': 'genetic database',
 'c_590e8349': 'photonics',
 'c_5db9ac34': 'substance of human origin',
 'c_a935cf3f': 'earth observation',
 'c_ff4dd793': 'molecular biology'}

Сдржај датотеке DOC_1.xml можемо искористи и за очитавање имена појединачних концепата на основу њихових идентификатора. Функција get_concept_name имплементира баш овај задатак. Њеним коришћењем је генерисан и листинг свих концепата eurovoc_concepts.jsonl који смо упознали у секцији o EuroLex57k скупу података.

In [16]:
def get_concept_name(concept_id, main_thesaurus_soup):
    concept_value = "eurovoc:" + concept_id
    concept_parent = main_thesaurus_soup.find("xs:enumeration", value=concept_value)
    concept_wrapper = concept_parent.find('xs:documentation').get_text()
    concept = concept_wrapper[0:concept_wrapper.find('/')-1]
    return concept
In [17]:
get_concept_name('1016', main_thesaurus_soup)
Out[17]:
'international finance'

Издвајање главних концепата микротезауруса

Главни концепти тезауруса EuroVoc су концепти који се налазе на врху хијерархије микротезауруса и који немају даљих уопштења. Док је све концепте микротезауруса лако издвојити, да би се добили ови концепти потребно је нешто мало више техничког посла. Датотека mappings.xml која садржи информације о овим мапирањима главних концепата и микротезауруса преузета је са ове адресе.

In [18]:
top_terms_file = open('data/eurovoc_thesaurus/mappings.xml', 'r')
top_terms_file_content = top_terms_file.read()
top_terms_soup = BeautifulSoup(top_terms_file_content, 'html.parser')

Из овако припремљеног документа могу се издвојити линкови до страница које садрже попис главних концепата одговарајућих микротезауруса. Линкова има укупно 127 - са сваки микротезаурус по један. Функција get_top_terms нам омогућава да пратећи линк дохватимо тражене информације.

In [19]:
import requests
In [20]:
top_terms_resources = [resource['rdf:resource'] for resource in top_terms_soup.find_all('ns5:haspart')]
In [21]:
def get_top_terms(resource_link):
    
    response = requests.get(resource_link)
    if response.status_code != 200:
        print('Resource ', resource_link, 'could not be fetched (status code: ', response.status_code, ')')
        return 
    response_text = response.text
    
    soup = BeautifulSoup(response_text, 'html.parser')
    
    microthesaurus_id = soup.find('skos:notation').text
    
    top_terms = []
    for top_term in soup.find_all('skos:hastopconcept'):
        resource = top_term['rdf:resource']
        index = resource.rfind('/') + 1
        id = resource[index: ]
        top_terms.append(id)
    
    return microthesaurus_id, top_terms
In [22]:
top_terms_per_microthesaurus = {}
for top_term_resource in top_terms_resources:
    microthesaurus_id, top_terms = get_top_terms(top_term_resource)
    top_terms_per_microthesaurus[microthesaurus_id] = top_terms
In [23]:
top_terms_per_microthesaurus
Out[23]:
{'6626': ['744'],
 '2441': ['2698', '394', '929', '1012'],
 '5636': ['2505', '1063', '651'],
 '1016': ['4040', '26', '5442', '4057', '4060'],
 '1606': ['2402', '712', '2497'],
 '6026': ['1258', '2736', '2735'],
 '6031': ['656', '1360'],
 '6016': ['6788', '239', '2775', '2763'],
 '6021': ['5017', '4314'],
 '6411': ['4415', '4418', '3641', '3632', '3689', '3797'],
 '6416': ['4185', '2478', '2914', '2817'],
 '6036': ['4416', '6052'],
 '6406': ['2707', '2481'],
 '5621': ['4363', '4412', '4630'],
 '5626': ['2014', '5962'],
 '5611': ['2972', '2493', '2477'],
 '5616': ['3605', '4358', '2551', '962', '2814', '937'],
 '6006': ['2414',
  '1602',
  '1115',
  '2413',
  '2418',
  '2417',
  '5360',
  '2416',
  '2412'],
 '6011': ['2737'],
 '5631': ['2711', '1277', '711', '5877', '2723', '2734'],
 '5641': ['2320', '5913', '1652', '1372', '2476', '3544'],
 '4821': ['4515', '4522', '2512'],
 '4826': ['4505', '3092'],
 '4811': ['3098', '1954', '2181', '2015'],
 '4816': ['4539'],
 '5216': ['2090', '343', '2524', '371'],
 '5606': ['2443', '2442'],
 '5206': ['2470', '2825', 'c_98d1408a', '1707', '1158', '434743'],
 '5211': ['3146', '6011', '833', '3150', '3549'],
 '4406': ['2468', '1074', '3522', '4299', '5974'],
 '4411': ['4276', '5275', '1737', '1802'],
 '4026': ['54', '1155'],
 '4031': ['802', '539', '3581', '2474'],
 '4426': ['2178', '3209', '557'],
 '4806': ['3160', '3131', '2494', '3101'],
 '4416': ['2184', '4543', '82'],
 '4421': ['1163', '3273', '2491'],
 '7621': ['2188'],
 '7626': ['2191', '4826'],
 '7231': ['c_b2c019c8',
  '8369',
  '2117',
  '7207',
  'c_2b2e17b1',
  '5083',
  '8367',
  '1191',
  '5781',
  '6205',
  '8278',
  '5302',
  '4607',
  'c_964c9649',
  '1105',
  '4845',
  '2148',
  '5283',
  '8366',
  '5087',
  '2106',
  '4690',
  '1847',
  '5776',
  '4587',
  '5265',
  '1794',
  'c_c385cfb4',
  '187',
  '5778',
  '1844',
  '594',
  '5780',
  '8365',
  '4069'],
 '7236': ['4483',
  '1658',
  '130',
  '122',
  '2119',
  '2079',
  '4590',
  'c_6e703074',
  '2200',
  'c_789ead37',
  '5775',
  '5655',
  '5437'],
 '7221': ['281', '5424', '311'],
 '7226': ['2705', '2848', '2113', '2838', '5448', '956', '2858'],
 '7611': ['2187'],
 '7616': ['2171', '2167', '2170', '2190', '2172'],
 '7241': ['1087', '3778', '1086', '2287'],
 '7606': ['1455', '2179', '4826', '8380', '4365'],
 '6836': ['1386'],
 '6841': ['1418', '1388'],
 '6826': ['1400', '1401'],
 '6831': ['4414', '3879', '4565'],
 '7211': ['7868',
  '7855',
  '7861',
  '7879',
  '337',
  '6136',
  '1329',
  '8189',
  '1520',
  '2288',
  '7814',
  '7816',
  '7815',
  '864',
  'c_6acbfd25',
  '7817',
  '6138',
  '1088',
  '1506',
  '8301',
  '4840',
  '1184',
  '6135',
  '2564'],
 '7216': ['1615', '5259', '1587', '1632'],
 '6846': ['1398', '3895', '1390', '5359'],
 '7206': ['5781', '913', '912', '909', '914', '911'],
 '6616': ['1274', '2364', '1414'],
 '6621': ['753', '1412', '5350', '3783'],
 '6606': ['3737', '2498'],
 '6611': ['3743', '2767', '1411'],
 '6816': ['1417', '3820', '1882'],
 '6821': ['1410', '1718', '1845', '1834', '5614', '5615'],
 '6806': ['2507', '2720', '3587', '4303'],
 '6811': ['1362', '3810', '3798', '3809'],
 '2006': ['2449', '1810', 'c_4c7717f3', '1786', '2488', '524', '2487', '2450'],
 '2011': ['3156', '4380', '2519', '2520', '5842'],
 '1626': ['4362', '3659', '56'],
 '1631': ['4256', '2616', '1800'],
 '2026': ['139', '3193', '138'],
 '2031': ['87', '13', '5268'],
 '2016': ['2292', '614', '2128'],
 '2021': ['3584', '11', '3185'],
 '1226': ['2351', '5923'],
 '1231': ['566', '4010', '6922', '567', '565'],
 '1216': ['3878', '3954', '1432', '573', '3513'],
 '1221': ['5371', '1538', '5400', '2701'],
 '1616': ['3058', '2515', '5848'],
 '1621': ['637', '4006', '3013'],
 '1236': ['3900', '7347', '3908', '584', '538', '3899', '3901'],
 '1611': ['427', '335', '84'],
 '0821': ['2628', '2464', '3451', '2647'],
 '1006': ['5640', '2163', '4304', '5769', '1451', '5767', '5130', '4067'],
 '0811': ['2460', '3074', '3489'],
 '0816': ['6722', '3450', '99', '2500', '3476', '4697'],
 '1206': ['4222', '5789', '3935'],
 '1211': ['523', '3929'],
 '1011': ['8473', '5258', '525', '4017', '4479'],
 '1021': ['438855', '5576', '3258', '5620', '1005', '5051'],
 '0416': ['4750', '558', '1953', '4157', '4367', '2186', '1748', '695'],
 '0421': ['53', '2246', '3232', '41', '2242'],
 '0406': ['1282', '883', '3025', '1453', '2573', '2370'],
 '0411': ['2258', '2180', '4436'],
 '0436': ['6034', '3062', '2166', '517', '77'],
 '0806': ['1346', '3461', '3474', '3467', '2189'],
 '0426': ['2703', '2702'],
 '0431': ['4045', '4704', '2152', '4179', '2001'],
 '3606': ['6382', '3949', '3941', '3946', '3952'],
 '3611': ['3928', '3956'],
 '3231': ['2472', '4486', '1422'],
 '3236': ['4488', '5922', '3028', '1405', '1426'],
 '4016': ['4189'],
 '4021': ['1154', '4413', '1164'],
 '4006': ['3582', '69', '2469', '554', '4300', '4703'],
 '4011': ['5985', '445', '813'],
 '2846': ['490', '2475', '2496', '1687', '1690', '1221', '4619'],
 '3206': ['668', '2467', '3683'],
 '2836': ['108', '4050', '1004'],
 '2841': ['c_4ee83dea', '1754', '1268', '2789', '5881', '2479', '1415'],
 '3221': ['494', '4366', '486'],
 '3226': ['2012', '4361', '3855', '1370', '2473', 'c_415bab24'],
 '3211': ['784', '873', '2059', '778', '795'],
 '3216': ['3278', '4705', '2175', '4554'],
 '2806': ['2398', '3307', '4184', '965', '540'],
 '2811': ['1909', '1916'],
 '2446': ['1310', '2504', '1321', '1325', '1021', '1326'],
 '2451': ['2656', '2489', '1039', '2639', '2632'],
 '2826': ['2517', '2690', '4706', '1700'],
 '2831': ['2688', '317', '2459', '3257'],
 '2816': ['52', '385', '3300', '3318'],
 '2821': ['4305', '1820', '85', '3487'],
 '2411': ['2486', '1809', '4602', '2510'],
 '2416': ['1452', '2149', '8469', '285', '2495'],
 '2036': ['474', '4291'],
 '2406': ['6332', '1850', '1016', '4370', '4671', '3239'],
 '2431': ['3151'],
 '2436': ['424', '2448', '1018'],
 '2421': ['1804', '1630'],
 '2426': ['1488', '1000']}

Издвајање концепата на основу хијерархије

Хијерархијске релације између концепата су пописане у датотеци relation_bt.xml.

In [24]:
relations_file = open('data/eurovoc_thesaurus/relation_bt.xml', 'r')
relations_content = relations_file.read()
relations_soup = BeautifulSoup(relations_content, 'html.parser')

Функција get_children_for_concept нам може помоћи да прочитамо идентификаторе концепата који се налазе у хијерархији испод задатог концепта (обично такве концепте зовемо децом).

In [25]:
def get_children_for_concept(concept_id, relations_soup):
    records = relations_soup.find_all('record')    
    source_ids = []
    for record in records:
        source_id = record.select('source_id')[0].get_text()
        cible_id = record.select('cible_id')[0].get_text()

        if cible_id == concept_id:
            source_ids.append(source_id)
    return source_ids

Можемо проверити који се то концепти налазе у хијерархији испод концепта population dynamics са идентификатором 3318.

In [26]:
get_children_for_concept('3318', relations_soup)
Out[26]:
['3324', '405', '4231', '4343', '4852', '6544']

Имена ових концепата можемо добити помоћу функције get_concept_name.

In [27]:
children_concepts_3318 = get_children_for_concept('3318', relations_soup)
for concept in children_concepts_3318:
    concept_name = get_concept_name(concept, main_thesaurus_soup)
    print(concept_name)
population ageing
depopulation
underpopulation
overpopulation
population growth
generation renewal

Како ЕuroVoc хијерархија дозвољава угњежђавање концепата до дубине два, уколико желимо да добијемо и ову децу за задати концепт можемо искористити функцију get_all_children_for_concept.

In [28]:
def get_all_children_for_concept(concept_id, relations_soup):
    all_children = []
    
    children = get_children_for_concept(concept_id, relations_soup)
    for child in children:
        all_children.append(child)
        
        children_level_1 = get_children_for_concept(child, relations_soup)
        
        for inner_child in children_level_1:
            all_children.append(inner_child)
            
            children_level_2 = get_children_for_concept(inner_child, relations_soup)
            for very_inner_child in children_level_2:
                all_children.append(very_inner_child)
        
    return all_children

Тако се, на пример, сва деца концепта "демографија" са идентификатором 385 могу добити следећим позивом:

In [29]:
all_children_concepts_385 = get_all_children_for_concept('385', relations_soup)
In [30]:
for concept in all_children_concepts_385:
    concept_name = get_concept_name(concept, main_thesaurus_soup)
    print(concept_name)
demographic analysis
world population
population census
population statistics
migration statistics
population forecast
mortality
infant mortality
occupational mortality
births
fertility
marriage rate
population policy
birth policy
life expectancy

Упаривање домена и свих концепата који му припадају

Следећим блоком кода упарићемо информације о доменима и концептима који им припадају. Оваква структура нам је неопходна за трансформацију обележја скупа EurlLex57k на начин који је подесан за вишелабеларну класификацију.

In [31]:
concepts_per_domain = {}

for (domain, microthesauruses) in microthesauruses_per_domain.items():
    concepts = []
    for microthesaurus_id in microthesauruses:
        concepts_per_microthesaurus = get_concepts_for_microthesaurus(microthesaurus_id, main_thesaurus_soup)
        concepts += concepts_per_microthesaurus
        
    concepts_per_domain[domain] = concepts

Сада се лако могу добити сви концепти који припадају домену науке. Има их укупно 133!

In [32]:
science_concepts = concepts_per_domain['36']
In [33]:
len(science_concepts)
Out[33]:
133

Овако креирану структуру ћемо сачувати за даље коришћење у датотеци са именом concepts_per_domain.txt.

In [34]:
with open('data/concepts_per_domain.txt', 'w') as file:
    file.write(str(concepts_per_domain))