티스토리 뷰
https://github.com/joyhong85/rdf_python 에서 확인할 수 있습니다.
RDF 형태의 데이터를 생성한다.
작성자 : 허홍수
e-mail : su4620@gmail.com
blog : http://joyhong.tistory.com
e-mail : su4620@gmail.com
blog : http://joyhong.tistory.com
CSV 형태의 데이터를 RDF 형태로 변환하기¶
원본데이터
공공데이터포털 - 건강보험심사평가원_전국 병의원 및 약국 현황
https://www.data.go.kr/data/15051059/fileData.do사용하는 라이브러리
RDFLib
(https://rdflib.readthedocs.io/en/6.0.0/index.html)
데이터 확인¶
원본 형태의 데이터를 바로 확인할 수도 있지만 여기서는 판다스를 활용하여 null값 등을 확인하도록 한다.
- 전처리가 잘 되어 있다면 1.1, 1.2 과정을 스킵하고 바로 2번 과정을 수행해도 된다.
In [1]:
import pandas as pd
import numpy as np
df = pd.read_csv('./hospital.csv', header=2)
df.info()
In [2]:
df.count(axis=0)
Out[2]:
null 값이 있는 열 번호 찾기¶
In [3]:
series = df.isnull().sum(axis=0)
np.where((series > 0).tolist())[0]
Out[3]:
11, 12, 13, 15, 16 번 value 값을 처리할 때 null 체크를 해야한다.
CSV 파일 그대로 읽어 RDF로 변환¶
그래프 생성¶
In [4]:
from rdflib import Graph, Literal, RDF, URIRef, Namespace
from rdflib.namespace import FOAF, XSD, RDF, RDFS, SKOS, DCTERMS
from tqdm import tqdm
# 그래프 생성
g = Graph()
# namespace 바인딩
RS = Namespace('http://joyhong.tistory.com/resource/')
ONT = Namespace('http://joyhong.tistory.com/ontology/')
SCHEMA = Namespace("http://schema.org/")
g.bind("rs", RS)
g.bind("ont", ONT)
g.bind("schema", SCHEMA)
g.bind("foaf", FOAF)
g.bind("skos", SKOS)
g.bind("dcterms", DCTERMS)
URI 유효성 검사 모듈 생성¶
RDFLib 에서 URIRef()로 리소스 생성시 유효하지 않은 스트링으로 생성시 시리얼라이즈 되지 않기 때문에 검사를 수행하여야 한다.
In [5]:
_invalid_uri_chars = '<>" {}|\\^`'
def _is_valid_uri(uri):
for c in _invalid_uri_chars:
if c in uri:
return False
return True
매핑 설정¶
In [6]:
from dateutil.parser import parse
def makeTripleForHospital(row):
subject = URIRef(RS+'h_'+row[0])
geo = URIRef(RS+'geo_h'+row[0])
g.add((subject, RDF.type, URIRef(SCHEMA+'Hospital')))
g.add((subject, FOAF.page, URIRef('http://www.hira.or.kr/re/diag/getDiagAmtInfo.do?ykiho='+row[1])))
g.add((subject, DCTERMS.identifier, Literal(row[1])))
g.add((subject, RDFS.label, Literal(row[2])))
if row[11] != '':
g.add((subject, URIRef(SCHEMA+'telephone'), Literal(row[11])))
if row[12] != '' and row[12] != 'http://' and _is_valid_uri(row[12]):
if not row[12].startswith('http'):
g.add((subject, FOAF.homepage, URIRef('http://'+row[12])))
else:
g.add((subject, FOAF.homepage, URIRef(row[12])))
if row[13] != '':
if '-00-' in row[13]:
row[13] = row[13].replace('-00-','-01-')
g.add((subject, URIRef(ONT+'openedDate'), Literal(parse(row[13]).date())))
g.add((subject, URIRef(ONT+'totalNumberOfDoctor'), Literal(row[14])))
#위치
g.add((subject, URIRef(SCHEMA+'geo'), geo))
g.add((geo, URIRef(SCHEMA+'postalCode'), Literal(row[9])))
g.add((geo, URIRef(SCHEMA+'address'), Literal(row[10])))
if row[15] != '':
g.add((geo, URIRef(SCHEMA+'longitude'), Literal(row[15])))
if row[16] != '':
g.add((geo, URIRef(SCHEMA+'latitude'), Literal(row[16])))
#종별 구분
g.add((subject, DCTERMS.subject, URIRef(RS+'cat_'+row[3])))
g.add((URIRef(RS+'cat_'+row[3]), RDF.type, URIRef(SKOS.Concept)))
g.add((URIRef(RS+'cat_'+row[3]), RDFS.label, Literal(row[4])))
g.add((URIRef(RS+'cat_'+row[3]), SKOS.prefLabel, Literal(row[4], lang='ko')))
g.add((URIRef(RS+'cat_'+row[3]), DCTERMS.identifier, Literal(row[3])))
#시도
g.add((subject, DCTERMS.subject, URIRef(RS+'rg_'+row[5])))
g.add((URIRef(RS+'rg_'+row[5]), RDF.type, URIRef(SKOS.Concept)))
g.add((URIRef(RS+'rg_'+row[5]), RDFS.label, Literal(row[6])))
g.add((URIRef(RS+'rg_'+row[5]), SKOS.prefLabel, Literal(row[6], lang='ko')))
g.add((URIRef(RS+'rg_'+row[5]), DCTERMS.identifier, Literal(row[5])))
g.add((URIRef(RS+'rg_'+row[5]), SKOS.narrower, URIRef(RS+'rg_'+row[7])))
g.add((URIRef(RS+'rg_'+row[7]), SKOS.broader, URIRef(RS+'rg_'+row[5])))
#시군구
g.add((subject, DCTERMS.subject, URIRef(RS+'rg_'+row[7])))
g.add((URIRef(RS+'rg_'+row[7]), RDF.type, URIRef(SKOS.Concept)))
g.add((URIRef(RS+'rg_'+row[7]), RDFS.label, Literal(row[8])))
g.add((URIRef(RS+'rg_'+row[7]), SKOS.prefLabel, Literal(row[8], lang='ko')))
g.add((URIRef(RS+'rg_'+row[7]), DCTERMS.identifier, Literal(row[7])))
csv 파일 로딩 및 변환 실행¶
In [7]:
import csv
data = open('./hospital.csv', 'r', encoding='utf-8-sig')
rows = csv.reader(data, delimiter=',')
for row in tqdm(list(rows)[3:]):
makeTripleForHospital(row)
data.close()
파일로 저장¶
In [8]:
g.serialize(destination='./hospital.ttl', format='turtle')
print("Finished..")
Pandas DataFrame 으로부터 RDF 변환¶
데이터 확인을 위해 dataframe으로 불러 들인 데이터를 활용하여 변환하도록 한다.
데이터 전처리¶
In [9]:
df
Out[9]:
In [10]:
df.info()
In [11]:
df= df.astype(str)
In [12]:
df.info()
In [13]:
# 컬렴명 변경
df.columns = list(range(len(df.columns)))
In [14]:
# 문자형으로 강제변환하였기에 NaN 값이 nan으로 변경되어 이를 ''로 처리
df.replace(['None', 'nan'], '', inplace=True)
df
Out[14]:
In [15]:
# 13번 컬럼을 date형으로 변환
from dateutil.parser import parse
df[13] = df[13].map(lambda x: parse(x.replace('-00-','-01-')).date() if x!='' else x)
In [16]:
df
Out[16]:
그래프 생성¶
In [17]:
from rdflib import Graph, Literal, RDF, URIRef, Namespace
from rdflib.namespace import FOAF, XSD, RDF, RDFS, SKOS, DCTERMS
from tqdm import tqdm
# 그래프 생성
g = Graph()
# namespace 바인딩
RS = Namespace('http://joyhong.tistory.com/resource/')
ONT = Namespace('http://joyhong.tistory.com/ontology/')
SCHEMA = Namespace("http://schema.org/")
g.bind("rs", RS)
g.bind("ont", ONT)
g.bind("schema", SCHEMA)
g.bind("foaf", FOAF)
g.bind("skos", SKOS)
g.bind("dcterms", DCTERMS)
URI 유효성 검사 모듈 생성¶
In [18]:
_invalid_uri_chars = '<>" {}|\\^`'
def _is_valid_uri(uri):
for c in _invalid_uri_chars:
if c in uri:
return False
return True
매핑설정(pandas dataframe 활용)¶
In [19]:
def makeTripleForHospitalByDataFrame(row):
subject = URIRef(RS+'h_'+row[0])
geo = URIRef(RS+'geo_h'+row[0])
g.add((subject, RDF.type, URIRef(SCHEMA+'Hospital')))
g.add((subject, FOAF.page, URIRef('http://www.hira.or.kr/re/diag/getDiagAmtInfo.do?ykiho='+row[1])))
g.add((subject, DCTERMS.identifier, Literal(row[1])))
g.add((subject, RDFS.label, Literal(row[2])))
if row[11] != '':
g.add((subject, URIRef(SCHEMA+'telephone'), Literal(row[11])))
if row[12] != '' and row[12] != 'http://' and _is_valid_uri(row[12]):
if not row[12].startswith('http'):
g.add((subject, FOAF.homepage, URIRef('http://'+row[12])))
else:
g.add((subject, FOAF.homepage, URIRef(row[12])))
if row[13] != '':
g.add((subject, URIRef(ONT+'openedDate'), Literal(row[13])))
g.add((subject, URIRef(ONT+'totalNumberOfDoctor'), Literal(row[14])))
#위치
g.add((subject, URIRef(SCHEMA+'geo'), geo))
g.add((geo, URIRef(SCHEMA+'postalCode'), Literal(row[9])))
g.add((geo, URIRef(SCHEMA+'address'), Literal(row[10])))
if row[15] != '':
g.add((geo, URIRef(SCHEMA+'longitude'), Literal(row[15])))
if row[16] != '':
g.add((geo, URIRef(SCHEMA+'latitude'), Literal(row[16])))
#종별 구분
g.add((subject, DCTERMS.subject, URIRef(RS+'cat_'+row[3])))
g.add((URIRef(RS+'cat_'+row[3]), RDF.type, URIRef(SKOS.Concept)))
g.add((URIRef(RS+'cat_'+row[3]), RDFS.label, Literal(row[4])))
g.add((URIRef(RS+'cat_'+row[3]), SKOS.prefLabel, Literal(row[4], lang='ko')))
g.add((URIRef(RS+'cat_'+row[3]), DCTERMS.identifier, Literal(row[3])))
#시도
g.add((subject, DCTERMS.subject, URIRef(RS+'rg_'+row[5])))
g.add((URIRef(RS+'rg_'+row[5]), RDF.type, URIRef(SKOS.Concept)))
g.add((URIRef(RS+'rg_'+row[5]), RDFS.label, Literal(row[6])))
g.add((URIRef(RS+'rg_'+row[5]), SKOS.prefLabel, Literal(row[6], lang='ko')))
g.add((URIRef(RS+'rg_'+row[5]), DCTERMS.identifier, Literal(row[5])))
g.add((URIRef(RS+'rg_'+row[5]), SKOS.narrower, URIRef(RS+'rg_'+row[7])))
g.add((URIRef(RS+'rg_'+row[7]), SKOS.broader, URIRef(RS+'rg_'+row[5])))
#시군구
g.add((subject, DCTERMS.subject, URIRef(RS+'rg_'+row[7])))
g.add((URIRef(RS+'rg_'+row[7]), RDF.type, URIRef(SKOS.Concept)))
g.add((URIRef(RS+'rg_'+row[7]), RDFS.label, Literal(row[8])))
g.add((URIRef(RS+'rg_'+row[7]), SKOS.prefLabel, Literal(row[8], lang='ko')))
g.add((URIRef(RS+'rg_'+row[7]), DCTERMS.identifier, Literal(row[7])))
변환 실행¶
In [20]:
for value in tqdm(df.values):
# print(value[0] ,'\t', value[1])
makeTripleForHospitalByDataFrame(value)
파일로 저장¶
In [21]:
g.serialize(destination='./hospital_df.ttl', format='turtle')
print("Finished..")
Finish
'N:::만지작 거리기' 카테고리의 다른 글
N_18.Fuseki로 SPARQL Endpoint 구성 (0) | 2021.09.09 |
---|---|
N_17. 그래프에 담기/SPARQL (0) | 2021.09.09 |
N_15. TBC에서 RDF 파일을 TDB에 임포트하기 (0) | 2019.12.11 |
N_14. CONSTRUCT 를 이용한 RDF 파일 생성 (0) | 2019.12.10 |
N_13. TBC에 엑셀 데이터 임포트하기 (0) | 2019.12.09 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 트리플
- 그래프 데이터베이스
- Ontology
- RDF 변환
- Linked Data
- neosemantics
- sparql
- pyvis
- Knowledge Graph
- rdfox
- 장고
- 지식그래프
- networkx
- django
- 온톨로지
- 타임리프
- 스프링부트
- RDF
- TDB
- TopBraid Composer
- stardog
- 트리플 변환
- cypher
- Neo4j
- TBC
- 사이퍼
- LOD
- Thymeleaf
- property graph
- 지식 그래프
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함