1. 기업맞춤형 빅데이터 분석가 양성과정 소개
2. Notion 일과 삶 & 빅데이터 분석가 양성과정 대시보드
https://lifemoment.notion.site/497bff9488aa4dec9171d08224a7a978?pvs=4
3. Jupyter Notebook
stringfunction - Jupyter Notebook
regularexpression-checkpoint - Jupyter Notebook
1.plaintext_file_format - Jupyter Notebook
2.csv_file_format - Jupyter Notebook
3.xml_file_format - Jupyter Notebook
4.json_file_format - Jupyter Notebook
4. Naver 블로그 포스팅
https://blog.naver.com/moment_by_moment/223330676955
5. 필기노트
빅데이터에서 자연어 처리 등의 대규모가 아닌 경우
로컬에서 CPU로 돌릴 수 있는 아나콘다와 주피터노트북을 활용하는 것이 좋다.
→ 로컬 환경에 있는 쥬피터노트북과 아나콘다를 사용하는 것이 좋다.
코랩: 구글에서 대규모 라이브러리를 설치해 두었다.
→ 자연스럽게 환경에 적응되어 있다.
2007년도 인터넷 연결 커넥션이 만들어졌다.
기본적인 표현, 데이터 처리 등을 강의
기본적인 데이터 입출력
PyQt로 미니 프로젝트 진행
1년차: 풀타임 강사
작년부터는 어려운 과목들을 받게 되었다.
기초 과목을 탄탄하게 다진 다음, 어려운 쪽으로 들어가게 되면
컨텐츠와 코드를 보고 어떻게 쓸 것인지 큰 그림을 보고 가야 한다.
나중에는 큰 그림만 그리고 코드를 쓸 줄 알면 된다.
CPU는 써도 기본적으로 메모리가 8기가 이상이다.
CPU와 메모리 쪽에서 누수없이 사용할 수 있다.
외국 쪽 엔지니어는 한 분야만 하기에 최적화 코드를 만들어낸다.
→ 깊이가 다르다.
애플 같은 경우, 상당히 견고하다.
한국 엔지니어가 만들면,
디버그 문제 발생 시, 어디가 문제인지 발견하지 못하는 경우가 많다.
→ 나의 수준을 100에서 4~60까지는 올려야 한다.
→ 어떻게 사용할 것인지는 나의 역량에 따라 다르다.
- 요구가 많으면, 공부할 수 밖에 없다.
파이썬이 강력한 이유
: 직관적이다, 자료를 떄려넣어도 통한다, 문자 숫자 정수 다 넣어도 다 인식할 수 있다.
ITK라는 라이브러리가 있다.
(Insight Toolkit)
컴퓨터 비전: 컴퓨터로 영상처리 하는 것
ITK: 의료영상을 처리하는 라이브러리
→ 파이썬이 들어온 뒤, 컴파일링 할 필요없이 바로 쓸 수 있게 되었다.
빅데이터를 가져올 때, 공공데이터센터(전국에 있는 지자체별)
→ 사람들이 한땀한땀 모은 것
내가 원하는 데이터를 내가 만들고 싶다면, 인터넷에서 사진이나 기사를 긁어와야 한다.
→ 크롤링 (특정 문서에서 원하는 데이터를 코드로 가져와서, 엑셀 파일 등으로 정리할 수 있다.)
용어를 잘 설명해야 한다.
re.sub('\\[0-9]+\\]','',item.get_text()))
→ 이 코드에 대해 쓸 수 있는 표현들을 알고 있으면 쉽게 일하고 집에 갈 수 있다.
정규표현식
age: 나이
Parch: 부모님와 아이
Embarked: 정차, 내리는가
빅데이터 처리를 할 때
어려운 점
: 해당 도메인에 대한 이해가 없으면 절대 접근할 수 없다.
금융, 보험, 의료 데이터 등에 대한 지식이 없으면 접근할 수 없다.
→ 어떻게 도메인을 이해할 것인가? (가장 어려운 부분)
빅데이터: 정량적을 보여주는 것도 있지만, 정성적으로 설득하기 위한 도구일 뿐이다.
→ 나만의 스토리텔링을 만들어서 다른 사람에게 설명할 수 있어야 한다.
가장 스토리를 잘 만든 사람에게 과제를 넘겨준다.
→ 이 스토리텔링을 하기 위해선, 내가 중심이 되어서 어떻게 이야기를 꾸며 나갈 것인가에 대한 생각이 있어야 한다.
- 기승전결로 매끄럽게 이어나가면 좋다.
- 중간에 뭔가 막히면 out이다.
스토리텔링을 잘 만들어나가면서 도메인을 이해해 나가면 된다.
import openpyxl
import re
regex = re.compile(' [A-Za-z]+\\.')
# 엑셀파일 열기
work_book = openpyxl.load_workbook('train.xlsx')
# 현재 Active Sheet 얻기
work_sheet = work_book.active
# work_sheet.rows는 해당 쉬트의 모든 행을 객체로 가지고 있음
for each_row in work_sheet.rows:
print (each_row[3].value)
print (regex.findall(each_row[3].value))
if len(regex.findall(each_row[3].value)) > 0:
if regex.findall(each_row[3].value)[0].strip() == "Mr.":
print ("남성")
work_book.close()
예제: 왜 정규표현식이 필요할까?
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
res = urlopen('<https://davelee-fun.github.io/blog/crawl_test_css.html>')
soup = BeautifulSoup(res, "html.parser")
data = soup.select('ul#dev_course_list li.course')
for item in data:
print (item.get_text())
(초급) - 강사가 실제 사용하는 자동 프로그램 소개 [2]
(초급) - 필요한 프로그램 설치 시연 [5]
(초급) - 데이터를 엑셀 파일로 만들기 [9]
(초급) - 엑셀 파일 이쁘게! 이쁘게! [8]
(초급) - 나대신 주기적으로 파이썬 프로그램 실행하기 [7]
(초급) - 파이썬으로 슬랙(slack) 메신저에 글쓰기 [40]
(초급) - 웹사이트 변경사항 주기적으로 체크해서, 메신저로 알람주기 [12]
(초급) - 네이버 API 사용해서, 블로그에 글쓰기 [42]
(중급) - 자동으로 쿠팡파트너스 API 로 가져온 상품 정보, 네이버 블로그/트위터에 홍보하기 [412]
바퀴를 새로 만들 필요가 없다.
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
res = urlopen('<https://davelee-fun.github.io/blog/crawl_test_css.html>')
soup = BeautifulSoup(res, "html.parser")
data = soup.select('ul#dev_course_list li.course')
for item in data:
print (re.sub('\\[[0-9]+\\]', '', item.get_text()) )
(초급) - 강사가 실제 사용하는 자동 프로그램 소개
(초급) - 필요한 프로그램 설치 시연
(초급) - 데이터를 엑셀 파일로 만들기
(초급) - 엑셀 파일 이쁘게! 이쁘게!
(초급) - 나대신 주기적으로 파이썬 프로그램 실행하기
(초급) - 파이썬으로 슬랙(slack) 메신저에 글쓰기
(초급) - 웹사이트 변경사항 주기적으로 체크해서, 메신저로 알람주기
(초급) - 네이버 API 사용해서, 블로그에 글쓰기
(중급) - 자동으로 쿠팡파트너스 API 로 가져온 상품 정보, 네이버 블로그/트위터에 홍보하기
정규표현식
프로그래밍 연습(생각만 해보기)
다음 코드를 실행해보고, 이름 정보를 통해 남자인지, 여자인지, 기타인지(남녀 구별 불가)를 확인할 수 있는 방법 생각해보기
세 라인의 코드를 추가하면 이름의 특징을 추출할 수 있음
import re
regex = re.compile('[A-Za-z]+\\.')
print ( regex.findall('찾을 문자열') )
pip install openpyxl
import openpyxl
import re
regex = re.compile(' [A-Za-z]+\\.')
# 엑셀파일 열기
work_book = openpyxl.load_workbook('train.xlsx')
# 현재 Active Sheet 얻기
work_sheet = work_book.active
# work_sheet.rows는 해당 쉬트의 모든 행을 객체로 가지고 있음
for each_row in work_sheet.rows:
print (each_row[3].value)
print (regex.findall(each_row[3].value))
work_book.close()
이름 데이터만 보고 성별관련 정보 알아내기
import openpyxl
import re
regex = re.compile(' [A-Za-z]+\\.')
# 엑셀파일 열기
work_book = openpyxl.load_workbook('train.xlsx')
# 현재 Active Sheet 얻기
work_sheet = work_book.active
# work_sheet.rows는 해당 쉬트의 모든 행을 객체로 가지고 있음
for each_row in work_sheet.rows:
print (each_row[3].value)
print (regex.findall(each_row[3].value))
if len(regex.findall(each_row[3].value)) > 0:
if regex.findall(each_row[3].value)[0].strip() == "Mr.":
print ("남성")
work_book.close()
' [A-Za-z]+.' --> regular expression 이라고 함
- 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식
예: 문자, 숫자가 아닌 데이터를 찾아서, '' 로 대체해라(삭제해라)
import re
string = "(Dave)"
re.sub('[^A-Za-z0-9]', '', string) # 문자, 숫자가 아닌 데이터를 찾아서, '' 로 대체해라(삭제해라)
string.replace("(", '').replace(")", '')
정규식에 대한 규칙을 알면 해당 내용들을 규칙별로 찾아낼 수 있다.
위 정규 표현식은 일정한 규칙을 가지고 작성됨, 필요한 패턴은 직접 만들 수도 있음
1. Dot .
- Dot . 메타 문자는 줄바꿈 문자인 \n를 제외한 모든 문자(한 개)를 의미함
- 예: D.A 는 D + 모든 문자(한 개) + A 를 의미
- DAA, DvA, D1A
# 정규 표현식 라이브러리 임포트하기
import re
# 정규 표현식 패턴 만들기
pattern = re.compile('D.A')
# 패턴에 매칭되는지 여부 확인하기 (실습)
pattern.search("DAA")
pattern.search("D1A")
pattern.search("D00A")
pattern.search("DA")
pattern.search("d0A")
pattern.search("d0A D1A 0111")
정말 Dot . 이 들어간 패턴을 찾으려면?
\\. 으로 표시하거나, [.] 으로 표시하면 됨
pattern = re.compile('D\\.A')
pattern.search("D.A")
pattern.search("DDA")
pattern = re.compile('D[.]A')
찾고 바꾸기 (특정 패턴이 매칭되는 것을 찾아서, 다른 문자열로 바꾸기)
string = "DDA D1A DDA DA"
# re.sub(패턴, 바꿀데이터, 원본데이터)
re.sub('D.A', 'Dave', string) # 문자, 숫자가 아닌 데이터를 찾아서, '' 로 대체해라(삭제해라)
2. 반복 ? , * , +
- ? 는 앞 문자가 0번 또는 1번 표시되는 패턴 (없어도 되고, 한번 있어도 되는 패턴)
- 는 앞 문자가 0번 또는 그 이상 반복되는 패턴
-
- 는 앞 문자가 1번 또는 그 이상 반복되는 패턴
# ?사용 예
pattern = re.compile('D?A') # 앞에 문자 D가 없거나, 여러번 반복되고 마지막이 A 인 문자열
pattern.search("A")
=> <re.Match object; span=(0, 1), match='A'>
pattern.search("DA")
=> <re.Match object; span=(0, 2), match='DA'>
pattern.search("DDDDDDA")
=> <re.Match object; span=(5, 7), match='DA'>
# *사용 예
pattern = re.compile('D*A') # 앞에 문자 D가 없거나, 여러번 반복되고 마지막이 A 인 문자열
pattern.search("A")
=> <re.Match object; span=(0, 1), match='A'>
pattern.search("DA")
=> <re.Match object; span=(0, 2), match='DA'>
pattern.search("DDDDDDDDDDDDDDDDDDDDDDDDDDDDA")
=> <re.Match object; span=(0, 29), match='DDDDDDDDDDDDDDDDDDDDDDDDDDDDA'>
pattern = re.compile('AD*A') # 앞에 문자 D가 없거나, 여러번 반복되고 마지막이 A 인 문자열
pattern.search("ADA")
=> <re.Match object; span=(0, 3), match='ADA'>
pattern.search("ADDDDDDDDDDDDDDDDDDA")
=> <re.Match object; span=(0, 20), match='ADDDDDDDDDDDDDDDDDDA'>
또다른 반복 표현: {n}, {m,n}
- {n} : 앞 문자가 n 번 반복되는 패턴
- {m, n} : 앞 문자가 m 번 반복되는 패턴부터 n 번 반복되는 패턴까지
# {n} 사용 예
pattern = re.compile('AD{2}A')
pattern.search("ADA")
pattern.search("ADDA")
=> <re.Match object; span=(0, 4), match='ADDA'>
pattern.search("ADDDA")
# {m,n} 사용 예
pattern = re.compile('AD{2,6}A') # {m,n} 은 붙여 써야 함 {m, n} 으로 쓰면 안됨(특이함)
pattern.search("ADDA")
=> <re.Match object; span=(0, 4), match='ADDA'>
pattern.search("ADDDA")
=> <re.Match object; span=(0, 5), match='ADDDA'>
pattern.search("ADDDDDDA")
=> <re.Match object; span=(0, 8), match='ADDDDDDA'>
3. 괄호 : 괄호 안에 들어가는 문자가 들어 있는 패턴
- 예: [abc] 는 a, b, c 중 하나가 들어 있는 패턴을 말함
pattern = re.compile('[abcdefgABCDEFG]')
pattern.search("a1234")
=> <re.Match object; span=(0, 1), match='a'>
pattern.search("z1234")
하이픈(-)을 이용하면 알파벳 전체를 나타낼 수 있음
- 예: [a-c] 는 a, b, c 중 하나가 들어 있는 패턴을 말함
pattern = re.compile('[a-z]')
pattern.search("k1234")
=> <re.Match object; span=(0, 1), match='k'>
pattern.search("Z1234")
=> <re.Match object; span=(0, 1), match='Z'>
[a-zA-Z] 으로 표기하면 대소문자를 모두 포함해서 알파벳 전체를 나타낼 수 있음
pattern = re.compile('[a-zA-Z]')
pattern.search("Z1234")
=> <re.Match object; span=(0, 1), match='Z'>
[a-zA-Z0-9] 로 표기하면 대소문자를 모두 포함해서 알파벳 전체와 함께 숫자 전체도 나타낼 수 있음
pattern = re.compile('[a-zA-Z0-9]')
pattern.search("1234---")
=> <re.Match object; span=(0, 1), match='1'>
pattern.search("---------------!@#!@$!$%#%%%#%%@$!$!---")
괄호 안에서 [ 바로 뒤에 ^ 을 쓰면 그 뒤에 오는 문자가 아닌 패턴을 찾음
- 문자를 결국 알파벳, 숫자, 특수문자, whitespace(스페이스, 탭, 엔터등) 로 분류할 수 있으므로
- [^ \t\n\r\f\v] 는 이중에서 whitespace 가 아닌 알파벳, 숫자, 특수문자를 지칭함
pattern = re.compile('[^a-zA-Z0-9]')
pattern.search("---------------!@#!@$!$%#%%%#%%@$!$!---")
=> <re.Match object; span=(0, 1), match='-'>
pattern = re.compile('[^ \\t\\n\\r\\f\\v]')
pattern.search("-")
=> <re.Match object; span=(0, 1), match='-'>
pattern.search(" ")
그러면 한글만? --> [가-힣]
pattern = re.compile('[가-힣]')
pattern.search("안")
=> <re.Match object; span=(0, 1), match='안'>
4. 조합해서 써보자
import re
pattern = re.compile('[a-zA-Z]+')
matched = pattern.search("Dave")
print(matched)
=> <re.Match object; span=(0, 4), match='Dave'>
5. 정규 표현식 라이브러리 함수 사용법
match 와 search 함수
- match : 문자열 처음부터 정규식과 매칭되는 패턴을 찾아서 리턴
- search : 문자열 전체를 검색해서 정규식과 매칭되는 패턴을 찾아서 리턴
import re
pattern = re.compile('^[a-z]+')
matched = pattern.match('Dave')
searched = pattern.search("Dave")
print (matched)
=> None
print(searched)
=> <re.Match object; span=(1, 4), match='ave'>
findall 함수: 정규표현식과 매칭되는 모든 문자열을 리스트 객체로 리턴함
import re
pattern = re.compile('[a-z]+')
findalled = pattern.findall('Game of Life in Python')
print (findalled)
=> ['ame', 'of', 'ife', 'in', 'ython']
pattern2 = re.compile('[A-Za-z]+')
findalled2 = pattern2.findall('Game of Life in Python')
print (findalled2)
=> ['Game', 'of', 'Life', 'in', 'Python']
findall 함수를 사용해서 정규표현식에 해당되는 문자열이 있는지 없는지 확인하기
import re
pattern = re.compile('[a-z]+')
findalled = pattern.findall('GAME')
if len(findalled) > 0:
print ("정규표현식에 맞는 문자열이 존재함")
else:
print ("정규표현식에 맞는 문자열이 존재하지 않음")
=> 정규표현식에 맞는 문자열이 존재하지 않음
→
import re
pattern = re.compile('[a-z]+')
findalled = pattern.findall('game')
if len(findalled) > 0:
print ("정규표현식에 맞는 문자열이 존재함")
else:
print ("정규표현식에 맞는 문자열이 존재하지 않음")
=> 정규표현식에 맞는 문자열이 존재함
- 대문자는 존재 X, 소문자 존재 O
split 함수: 찾은 정규표현식 패턴 문자열을 기준으로 문자열을 분리
(분리(분류)해준다.)
import re
pattern2 = re.compile(':')
splited = pattern2.split('python:java')
print (splited)
=> ['python', 'java']
콜론에 맞춰서 Python 과 Java가 분리되며, 리스트 형식으로 반환해준다.
프로그래밍 연습
' VS ' 로 문자열 앞뒤를 분리해보기
A부터 Z까지 숫자가 반복되며 반환하는코드
import re
pattern2 = re.compile(' [A-Z]{2} ')
splited = pattern2.split('python VS java')
print (splited)
=> ['python', 'java']
- ‘VS’가 소문자가 아닌, 대문자로 걸려야 작동한다.
sub 함수: 찾은 정규표현식 패턴 문자열을 다른 문자열로 변경
(특정 문자열이 나오면, 어떠한 것으로 바꿔준다)
import re
pattern2 = re.compile('-')
subed = pattern2.sub('*', '801210-1011323') # sub(바꿀문자열, 본래문자열)
print (subed)
=> 801210*1011323
subed = re.sub('-', '*', '801210-1011323') # sub(정규표현식, 바꿀문자열, 본래문자열)
print (subed)
=>801210*1011323
- 어떤 표현을 쓰는지에 대해 이해하고 있어야 한다.
주민등록번호 뒷자리를 일괄적으로 다른 형태로 표시하는 것을 해보자.
도전 과제
주민번호 뒷자리를 * 로 바꿔서 가려보기
re.sub('-------', '------', each_row[1].value) <--- 정규표현식, 바꿀문자열 을 넣어봅니다.
import openpyxl
work_book = openpyxl.load_workbook('data_kr.xlsx')
work_sheet = work_book.active
for each_row in work_sheet.rows:
print(re.sub('-[0-9]{7}', '-*******', each_row[1].value))
work_book.close()
=>
주민등록번호
800215-*******
821030-*******
841230-*******
790903-*******
800125-*******
820612-*******
→ ‘*’로 일괄 처리에 대한 코드
# 핵심 코드
for each_row in work_sheet.rows:
print(re.sub('-[0-9]{7}', '-*******', each_row[1].value))
응용 과제: 뒷 번호 1자리만 남겨두고 나머지는 변환
import openpyxl
work_book = openpyxl.load_workbook('data_kr.xlsx')
work_sheet = work_book.active
for each_row in work_sheet.rows:
print(re.sub('-[0-9]{7}', '-*******', each_row[1].value))
work_book.close()
=>
주민등록번호
800215-*******
821030-*******
841230-*******
790903-*******
800125-*******
820612-*******
import openpyxl
work_book = openpyxl.load_workbook('data_kr.xlsx')
work_sheet = work_book.active
for each_row in work_sheet.rows:
print(re.sub('[^가-힣].....$', '******', each_row[1].value))
work_book.close()
=>
주민등록번호
800215-2******
821030-1******
841230-2******
790903-1******
800125-1******
820612-2******
PyQt: GUI도 같이 사용할 수 있게 되었다.
→ 파이썬의 약점 보완
머신러닝을 배우게 되면, 함수들을 어떻게 사용할 것인가에 대한 정의를 잘 정리해둬야 한다.
(너무 얕지도, 깊지도 않게 사용해야 한다.)
오캄스 레이저
: 모든 조건이 동등했을 때, 단순한 게 정답이다.
→ 아무리 어려운 문제를 만나더라도, 단순하게 생각하자.
다차원 공간
- 머신러닝과 인공지능은 다차원 공간으로 확장된다.
일상적인 생활에 냄새가 들어가면 4차원
소리가 들어가면 5차원
내가 만약에 그랬었더라면
→ 내가 요리사가 되는 길이 있고, 중국인 요리사가 되는 길이 있고, 경영할 수 있는 길이 있었다.
(다차원 공간에서 사랑이라는 결론을 내린다.)
in my time: 인공지능도 다차원 공간에서 차원을 축소하고 오캄스 레이저로 가장 간단한 답이 나오면, 그것이 정답이다.
- 세상의 모든 원리는 비슷하다.
퀀텀 컴퓨터: 빛의 입자속도로 계산해준다.
→ 단순하게 문제를 풀어내자.
문자열 관련 함수 알아보기
문자열에 있는 특정 문자 갯수 세기 (count 함수)
data = 'Dave David'
data.count('v') # 문자열에 D 가 몇 번 나올까요? 대소문자도 구별함
문자열에 있는 특정 문자의 위치 알려주기
index 함수
string = 'Dave ID is dave'
string.index('i') # 맨 앞 자리부터 0, 1, ... 순으로 위치를 표시
=> 8
해당 문자가 문자열에 없을 때, 에러를 안낼 수는 없을까? --> find 함수를 사용하면 됨
- find 함수는 해당 문자가 문자열에 없으면 -1 을 리턴함 (에러는 내지 않음)
- 이외에는 index 함수와 동일
string = 'dave is david'
string.find('x')
string = 'Dave ID is dave'
string.find('D ') # 맨 앞 자리부터 0, 1, ... 순으로 위치를 표시
if string.find('x') == -1:
print ("x는 스트링에 없습니다.")
=> x는 스트링에 없습니다.
문자열 사이에 다른 문자 넣기
string = "12345"
comma = ','
comma.join(string) # 껴넣을 문자.join(문자열)
=> '1,2,3,4,5'
문자열 앞뒤에 공백 지우기
- 실제 현실 세계에 있는 문자열 데이터를 정리하다보면, 문자열 앞뒤에 공백 또는 기호가 있는 경우가 많음
strip( )함수: 지워주다, 제거하다.
data = " Dave "
data.strip() # 앞 뒤 공백을 다 지움
=> 'Dave'
string2 = " David "
string2.strip() # 앞 뒤 공백이 여러개 있어도 한번에 다 지움
=> 'David'
string2.lstrip() # 앞쪽(문자열 왼쪽)만 지우기 left strip 의 약자
=> 'David '
string2.rstrip() # 앞쪽(문자열 오른쪽)만 지우기 right strip 의 약자
=> ' David'
string = " 9999999999999999(Dave)888888888888888888 "
string.strip(" 98()") # 앞 뒤 괄호를 다 지움
=> 'Dave'
- 퍼테이션마크: 문자열을 지정하는 ‘ ‘를 의미
영문자 대소문자로 변환하기¶
- 대소문자를 구별하기 때문에, 대소문자 구별하지 않고 처리를 하기 위해 임의로 대문자 또는 소문자로 다 바꿀 때가 있음
소문자를 대문자로 바꾸기
string = 'Dave'
string.upper() # 본래 대문자는 놔두고, 소문자인 문자만 대문자로 변경
=> 'DAVE'
대문자를 소문자로 바꾸기
string = 'Dave'
string.lower() # 본래 소문자는 놔두고, 대문자인 문자만 대문자로 변경
=> 'dave'
문자열을 나누기
string = "Dave goes to Korea"
string.split() # split() 인자를 넣지 않으면 디폴트로 스페이스를 기준으로 분리
=> ['Dave', 'goes', 'to', 'Korea']
string = "Dave goes to Korea"
string.split()[3]
=> 'korea'
string.split(' ') # 명시적으로 스페이스를 기준으로 분리하겠다고 넣어줘도 됨
=> ['Dave', 'goes', 'to', 'Korea']
string = "Dave/goes/to/Korea"
string.split('/') # split() 인자를 넣으면 해당 인자를 기준으로 분리
=> ['Dave', 'goes', 'to', 'Korea']
프로그래밍 연습
string = "10,11,22,33,44" 를 컴마(,) 로 분리해서 리스트 변수를 만들어 각 값을 정수형 리스트 데이터로 넣기
int('11') 을 실행하면 숫자 11로 변환
string = "10,11,22,33,44"
string.split(',')
=> ['10', '11', '22', '33', '44']
string = "10,11,22,33,44"
listdata = string.split(',')
for index, listitem in enumerate(listdata):
listdata[index] = int(listitem)
print (listdata)
=> [10, 11, 22, 33, 44]
string = "10,11,22,33,44"
split_string = string.split(',')
for index, split_item in enumerate(split_string):
split_string[index] = int(split_item)
print (split_string)
=> [10, 11, 22, 33, 44]
문자열 중 일부를 다른 문자로 바꾸거나, 삭제하기
string = "David goes to Korea"
string.replace("David", "Dave") # David 를 Dave 로 바꾸기
=> 'Dave goes to Korea'
string2 = "(Dave)"
string2.replace("()", "") # 연결된 문자열은 해당 문자열이 동일하게 매칭이 되어야 함
=> '(Dave)'
string2.replace("(", "")
=> 'Dave)'
string2.replace(")", "")
=> '(Dave'
string2 = string2.replace("(", "") # ( 가 삭제된 문자열로 변수 값을 덮어 씌운 후에 다시 ) 를 삭제하면 됨
string2.replace(")", "")
=> 'Dave'
string2 = "(Dave)"
string2.replace("(", "").replace(")", "")
=> 'Dave'
프로그래밍 연습
string = "10,11,22,33,44" 에서 컴마(,) 를 / 으로 대체하기
string = "10,11,22,33,44"
string.replace(",", " ")
=> '10 11 22 33 44'=
- xml파일: HTML에서 시작과 끝을 알려주는 태그형식
→ 과거 정부에서는 csv파일보단, xml파일형식이 더 많았다.
- json파일: 딕셔너리 형식으로 제공되는 형식
특정 데이터 포맷을 사용하지 않는, 일반적인 텍스트를 Plain Text라고 한다.
1. 다양한 데이터 포멧 이해하기: Plain Text
- Plain Text: 특정 데이터 포멧을 사용하지 않는, 일반적인 텍스트를 의미함
- 주요 데이터 포멧
- csv, xml, json
- 참고: https://www.data.go.kr/search/index.do
통상적으로 데이터 처리에서 다루는 Plain Text 보다는 특정 데이터 포멧을 사용하는 경우가 많음
1.1 파일 오픈 (Plain Text)
- 프로그래밍에서 파일은 다음과 같은 3가지 명령의 순서로 처리할 수 있음
- 파일 오픈
- 파일 읽기 또는 쓰기
- 파일 닫기
- 파일디스크립터변수 = open(파일이름, 파일열기모드)
data_file = open('00_data/text_data.txt', 'r', encoding='utf-8-sig')
- 파일 디스크립터 (file descriptor) 변수: 오픈한 파일 객체를 가리키고 있는 변수
- 파일 이름 명시시, open 함수 실행 위치와 파일 이름이 저장된 위치를 파일 절대 경로 또는 상대 경로로 정확히 명시해야 함
- 파일 열기 모드
파일열기모드 설명
r | 읽기 모드: 파일을 읽기만 할 때 사용함 |
w | 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) |
a | 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함 |
컴퓨터를 끄지 않고 사용할 경우, 컴퓨터가 느려진다.
→ 메모리에 있는 명령어를 처리하는데 시간이 오래 걸린다.
(자잘한 문서들이 많이 쌓이면
Java: 객체 지향형 언어로, 객체들이 붕어빵 찍듯이 만들어낼 수 있다.
(단일 상속), 상속을 1번만 해준다.
인터페이스 상속이라고 어떻게 상속하는지
정기적으로 자기가 만들어낸 객체를 지워주는 가비지클리닝 기능이 들어있다.
시스템을 관리하는 측에서 컴퓨터를 매번 껏다 킬 필요가 없다.
→ 항상 최적의 상태를 유지할 수 있다.
필요없는 파일은 닫아두는 습관을 길들일 필요가 있다.
encoding: 아스키 코드를 표준규약에 맞춰 화면에 주는 하나의 규약
- 인코더와 디코더
인코더: 암호를 만든다.
디코더: 암호를 푼다.
딥러닝의 오토 인코더: 자동으로 인코딩을 해준다.
- 인코딩: 압축한다.
- 딥러닝의 비지도학습: 오토인코더
(데이터가 많이 없을 때 사용하는 방식)
공장을 돌릴 때, 비정상 데이터가 더 적다.
정상 데이터와 비정상 데이터의 수를 맞춰야 하므로 오토인코딩을 통해 가공으로 비정상 데이터를 만들어준다.
- 자연어 처리에서 핫한 트랜스포머
: 인코더와 디코더 부분을 따로 해준 것
인코더: 자연어 처리를 할 수 있는 바트
디코더: GPT
⇒ 트랜스포머
트랜스포머와 자연어 처리는 책이 없고, 논문밖에 없다.
→ 공부하고 싶어도 어렵다.
참고: 인코딩과 utf-8 과 utf-8-sig
인코딩이란?
utf-8 과 utf-8-sig
- 기존에는 영어 인코딩, 한국어 인코딩 방식이 달랐음. 이에 따라 각 국가에서 작성된 파일을 읽을 수 없는 경우가 발생
- 모든 언어를 지원하는 인코딩 방식을 통해 다른 언어 지원, 이를 유니코드 라고 함
- 각 인코딩 방식마다 이름이 존재 하며, 유니코드는 utf-8 이라는 이름을 사용함
- 각 인코딩 방식에 맞게, 데이터를 저장하고, 데이터를 읽을 때에는 해당 인코딩 방식을 명시해주어, 데이터를 알맞게 읽을 수 있음
- utf 방식도 세부적으로는 utf-8, utf-16, utf-32 등 다양한 방식이 있으며, 이를 구별하기 위해, 윈도우의 텍스트 편집기들은 데이터 저장시 앞부분에 특정 기호(signature)를 추가함
- 해당 기호(signature)를 Byte Order Mark(BOM) 이라고 부름
- 문제는 해당 기호(signature)를 맥 또는 리눅스등 다른 운영체제 환경에서는 지원하지 않아서 잘못 인식할 수 있음
- 근본적으로 윈도우를 개발한 MS사가 표준과 다른, 자기만의 signature를 넣는 방식을 썼다는 것이 문제임
- 그래서, 데이터 오픈시, BOM이 있다면, BOM 빼고, 데이터를 읽을 수 있도록 하여, 호환성 문제를 해결하는 방식이 utf-8-sig 임
- 파일 데이터 오픈시, 인코딩에 문제가 있어 보일 경우, 또는 기본적으로 encoding='utf-8-sig' 를 사용하면 큰 문제가 없음
참고: 파일 절대 경로와 상대 경로
- 절대 경로
- 최초의 시작점으로 경유한 경로를 전부 기입하는 방식
- 윈도우 예: 드라이브명부터 시작, C:\ 등
- C:\\Users\\UserID\\Desktop\\test.txt
- 맥 예: 최상단 디렉토리를 나타내는 / 부터 시작
- 맥: /Users/tae/test.txt
- 상대 경로
- 파일을 찾는 위치부터 상대적인 경로를 기입하는 방식
- 예
- 현재 폴더가 /Users/tae/code 인 상태에서 동일 폴더에 있는 testfile.txt 를 찾는 경우
- testfile.txt
- 현재 폴더가 /Users/tae/code 인 상태에서 하위 폴더인 /Users/tae/code/data 폴더에 있는 testfile.txt 를 찾는 경우
- 현재 폴더 안에 있는 폴더를 하위 폴더라고 함
- 하위 폴더명/파일명 과 같은 형태로 상대 경로를 작성하면 됨
data/testfile.txt
- 현재 폴더가 /Users/tae/code 인 상태에서 상위 폴더인 /Users/tae/ 폴더에 있는 testfile.txt 를 찾는 경우
- 현재 폴더를 포함하고 있는 상위에 있는 폴더를 상위 폴더라고 함
- 상위 폴더는 ../ 로 명시할 수 있음
../testfile.txt
리눅스와 윈도우 중, 리눅스 일처리가 더 빠르다.
리눅스는 30분에 설치가 다 된다.
쉽게 쉽게 컴퓨팅 환경 구성이 될 수 있다.
- 개발 환경 맞추는 것도 어렵다.
버전이 다를 경우, 맞춰야 한다.
→ 어떻게 환경을 꾸릴 것인가?
연습문제
- 다음 상황에서 파일 절대 경로와 상대 경로 작성하기
- 현재 폴더: /Users/tae/code
- 파일 위치: /Users/
- 파일 명: testfile.txt
- data/testfile.txt
- 상대 경로: ../../testfile.txt
- 다음 상황에서 파일 절대 경로와 상대 경로 작성하기
- 현재 폴더: /Users/tae/code
- 파일 위치: /Users/tae/code/program/data
- 파일 명: testfile.txt
- 파일디스크립터변수.close() 함수로 파일을 닫을 수 있음
- 항상 오픈한 파일은 닫아야 함 (파일을 오픈한 채로 놔두면, 컴퓨터에서 관련 자원을 계속 사용중인 상태가 될 수 있음)
data_file = open('text_data.txt', 'r', encoding='utf-8-sig') data_file.close()
- 자동으로 파일을 닫기 위해 with 구문을 사용활용할 수 있음
- with open() 명령 as 파일디스크립터:
- with 구문 안에서 동작할 코드를 탭으로 들여쓰기 해서 사용하면, with 구문이 모두 끝난 후, 자동으로 해당 파일을 닫아줌
1.3 파일 읽기with open('00_data/text_data.txt', 'r', encoding='utf-8-sig') as file_desc: print ('test') => test
- 오픈한 파일 디스크립터.readlines() 함수를 호출해서, 전체 데이터를 한줄씩 리스트타입으로 읽어올 수 있음
• 리스트 타입 변수는 항상 for 구문을 사용해서, 각 아이템을 가져오기readline() 함수 사용하기data_file = open('text_data.txt', 'r', encoding='utf-8-sig') data_lines = data_file.readlines() data_lines => ['안녕하세요. tae 입니다.\\n', '본 예제는 Plain Text 파일 예제입니다.\\n', '감사합니다.']
- 오픈한 파일 디스크립터.readline() 함수를 호출해서, 현재까지 읽은 파일 데이터의 다음 한 줄을 문자열 타입으로 읽을 수 있음
read() 함수 사용하기data_file = open('00_data/text_data.txt', 'r', encoding='utf-8-sig') data_line = data_file.readline() print (data_line) => 안녕하세요. tae 입니다. data_line = data_file.readline() print (data_line) => 본 예제는 Plain Text 파일 예제입니다. data_line = data_file.readline() print (data_line) => 감사합니다. data_file.close()
- 오픈한 파일 디스크립터.read() 함수를 호출해서, 전체 파일 데이터를 문자열 타입으로 읽을 수 있음
1.4 파일 쓰기data_file = open('00_data/text_data.txt', 'r', encoding='utf-8-sig') data = data_file.read() data => '안녕하세요. tae 입니다.\\n본 예제는 Plain Text 파일 예제입니다.\\n감사합니다.' data_file.close()
- open() 함수에 파일열기모드를 'w' 로 해서, 파일 쓰기
r 읽기 모드: 파일을 읽기만 할 때 사용함 w 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) a 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함 - open() 함수에 파일열기모드를 'a' 로 해서, 파일 쓰기
r 읽기 모드: 파일을 읽기만 할 때 사용함 w 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) a 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함
연습문제data_file = open('00_data/text_data_write.txt', 'a', encoding='utf-8-sig') data_file.write('본 파일은 임시 파일입니다.') data_file.close()
- 00_data/text_data_practice.txt 파일 만들고, 다음 내용 쓰기 (각 데이터별 라인을 바꿔주도록 저장)
- 00_data/text_data_practice.txt 파일에 다음 내용 추가하기
- 00_data/text_data_practice.txt 파일 읽고, 다음과 같이 출력되는지 확인하기
# Write to the text file with open('text_data_practice.txt', 'w') as file: file.write("유치원A\\n초등학교B\\n중학교C\\n고등학교D\\n") # Append to the text file with open('text_data_practice.txt', 'a') as file: file.write("대학교E\\n") # Read from the text file and print the content with open('text_data_practice.txt', 'r') as file: content = file.read() print(content) => 유치원A 초등학교B 중학교C 고등학교D 대학교E
2. 다양한 데이터 포멧 이해하기: CSV- 주요 데이터 포멧
- csv, xml, json, plain text
- 파일디스크립터변수 = open(파일이름, 파일열기모드)
data_file = open('00_data/USvideos.csv', 'r', encoding='utf-8-sig')
- 파일 디스크립터 (file descriptor) 변수: 오픈한 파일 객체를 가리키고 있는 변수
- 파일 이름 명시시, open 함수 실행 위치와 파일 이름이 저장된 위치를 파일 절대 경로 또는 상대 경로로 정확히 명시해야 함
- 파일 열기 모드
r 읽기 모드: 파일을 읽기만 할 때 사용함 w 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) a 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함 - encoding
- open(파일이름, 파일열기모드, encoding='utf-8-sig') 와 같이 끝에 encoding 구문 추가 가능 (옵션)
- 파일 오픈시, 해당 파일의 인코딩 방식을 명시해주는 것임
- # text_data_practice.txt 파일을 만들고, # 각 데이터 별 라인을 바꿔주도록 내용 적기 # 유치원A, 초등학교B, 중학교C, 고등학교D data_file = open('text_data_practice.txt', 'w', encoding='utf-8-sig') data_file.write('유치원A\\n') data_file.write('초등학교B\\n') data_file.write('중학교C\\n') data_file.write('고등학교D\\n') data_file.close() # 해당 파일에 '대학교E' 내용 추가하기 data_file = open('text_data_practice.txt', 'a', encoding='utf-8-sig') data_file.write('대학교E\\n') data_file.close() # 해당 파일을 읽고, 다음과 같이 출력되는지 확인하기 # 유치원A # 초등학교B # 중학교C # 고등학교D # 대학교E data_file = open('text_data_practice.txt', 'r', encoding='utf-8-sig') data = data_file.read() data => '유치원A\\n초등학교B\\n중학교C\\n고등학교D\\n대학교E\\n'
- 고등학교D
- 초등학교B
- 고등학교D
- 초등학교B
- data_file = open('text_data_write.txt', 'w', encoding='utf-8-sig') data_file.write('안녕하세요\\n') data_file.write('tae 입니다.\\n') data_file.close()
- data_file = open('text_data_write.txt', 'w', encoding='utf-8-sig') data_file.write('안녕하세요') data_file.write('tae 입니다.') data_file.close()
- write() 함수 사용하기
- for data_line in data_lines: print (data_line) data_file.close() => 안녕하세요. tae 입니다. 본 예제는 Plain Text 파일 예제입니다. 감사합니다.
- readlines() 함수 사용하기
- 상대 경로: program/data/testfile.txt
2.2. csv 파일 읽기
- CSV(Comma-Separated Values): 스프레드시트 데이터를 저장할 때 가장 널리 쓰이는 파일 형식
- 엑셀등 여러 응용프로그램에서도 지원
- CSV 형식 (각 열은 콤마로 구분, 각 행은 줄바꿈 문자로 구분)
- tae, taepark apple, 2 korea, japan, chian
- 파이썬에서 CSV 파일로 저장/읽기 방법
- csv 라이브러리 사용
csv 라이브러리
- anaconda 에 포함
- 만약 다음 코드 실행시 No module 에러 메세지가 나오면, csv 라이브러리 설치 후, 재실행
pip install csv
머신러닝을 배우게 되면 데이터가 tab 형식으로 나눠져 있다.
가장 많이 쓰이는 데이터 형식이 csv파일이다.
csv 파일을 join( 2개를 하나로 합쳐서)해서 사용하기도 한다.
시간별로 데이터를 분리해서 월 평균, 주 평균 등등을 만들어서
머신러닝과 딥러닝을 할 수 있는 하나의 피처로 만든다.
데이터에서 csv파일이 많은 이유가 뭘까?
xml파일에서 csv파일이 많아진 이유가 무엇일까?
ERP, CRM(고객 관계 관리), SCM(어떻게 물건을 공급해서 맞출 것인가?)
⇒ 이 3가지를 회사에선 SQL문으로 만든다.
모든 데이터들을 오라클에서 사용하는 SQL로 만든다.
기업체에서 만들어지는 데이터들은 csv파일로 만들어진다.
기업체에서는 각각의 테이블을 잘라두었다.
은행권에서 SQL을 사용한다고 하면,
2개의 테이블을 상관없는 것끼리 뭉친다.
→ SQL의 기본
csv파일에 대해서 SQL을 기본적으로 어떻게 다뤄야 하는지 알고 있어야 한다.
기업체에서 사용하는 모든 것들은 SQL로 만들어진다.
그래서, csv파일이 많을 수 밖에 없다.
import csv
- 분석 SQL을 배우는 것은 좋지만, 어렵다.
자연어 처리, 분석 SQL
→ 파이썬기반으로 처리할 수 있다.
csv.reader(오픈한 파일 디스크립터, delimiter=',')
- open 함수를 통해 오픈한 파일 디스크립터
- delimiter=데이터구분자: csv 파일 내에 데이터 구분자를 명시할 수 있음 (옵션)delimeter로 바꾸면 똑같은 csv 형식으로 불러올 수 있다.데이터 읽기
- 각 라인별 데이터를 읽기 위해, for 문을 사용하면 됨
- data_lines = csv.reader(data_file, delimiter=',') for data_line in data_lines: print (data_line)
- 대부분 ‘,’로 구분되어 있다.
- data_file = open('00_data/USvideos.csv', 'r', encoding='utf-8-sig') data_lines = csv.reader(data_file, delimiter=',')
파일 닫기 (close)
- 오픈한 파일은 반드시 닫아야 함, 닫지 않으면 파일이 오픈된 채로 남아있을 수 있음
data_file = open('00_data/USvideos.csv', 'r', encoding='utf-8-sig')
data_lines = csv.reader(data_file, delimiter=',')
for data_line in data_lines:
print (data_line)
data_file.close()
예 (한줄만 출력해봄)
import csv
data_file = open('USvideos.csv', 'r', encoding='utf-8-sig')
data_lines = csv.reader(data_file, delimiter=',')
for data_line in data_lines:
print (data_line)
break
data_file.close()
=> ['video_id', 'title', 'channel_title', 'category_id', 'tags', 'views', 'likes', 'dislikes', 'comment_total', 'thumbnail_link', 'date']
csv 파일 읽기 다른 기법
- with 문법을 사용해서, 파일 데이터를 읽은 후, with 내부 구문 실행 완료 후, 자동으로 파일을 닫을 수 있음
import csv
with open('00_data/USvideos.csv', 'r', encoding='utf-8-sig') as reader_csv:
reader = csv.reader(reader_csv, delimiter=',')
for row in reader:
print (row)
break
=> ['video_id', 'title', 'channel_title', 'category_id', 'tags', 'views', 'likes', 'dislikes', 'comment_total', 'thumbnail_link', 'date']
2.3 csv 파일 쓰기
- open 시 'w' 로 옵션을 설정
- open() 함수에 newline='' 를 넣어주는 이유는 윈도우의 경우에만 csv 모듈에서 데이타를 쓸 때 각 라인 뒤에 빈 라인이 추가되는 문제가 있기 때문
- 이를 없애기 위해 (파이썬 3 에서) 파일을 open 할 때 newline='' 와 같은 옵션을 지정
data_file = open('00_data/data.csv', 'w', encoding='utf-8-sig', newline='')
- csv.reader 대신, csv.writer 함수 사용
data_write = csv.writer(data_file, delimiter=',')
- writerow 함수에 리스트 형식으로 데이터를 넣으면, 한 라인씩 파일에 추가 됨
- 파일 close 는 파일 읽기와 동일함
import csv
data_file = open('tmp_csv.csv', 'w', encoding='utf-8-sig', newline='')
data_write = csv.writer(data_file, delimiter=',')
data_write.writerow(['1', '2', '3'])
data_file.close()
(pandas가 기본이다.)
csv 파일 쓰기 다른 기법 (with)
- with 문법을 사용해서, with 내부 구문 실행 완료 후, 자동으로 파일을 닫을 수 있음
쓰레기 데이터가 들어가면, 쓰레기가 나온다.
어떤 데이터는 평균이 0과 1사이이고 어떤 데이터는 평균이 100이면 outlyler라고 한다. 빈 데이터는 기존에 있던 평균값을 대체하는 식으로 빈 칸을 채워넣음을 통해 결과를 산출해야 한다.
데이터는 태국이나 방글라데시에서 만든다. (아웃소싱)
→ 데이터를 어떻게 사용하는가가 핵심이다.
import csv
with open('tmp_csv.csv', 'w', encoding='utf-8-sig', newline='') as writer_csv:
writer = csv.writer(writer_csv, delimiter=',')
writer.writerow(['love']*3 + ['banana']) # ['love', 'love', 'love', 'banana'] 와 동일
writer.writerow(['apple', 2]) # 문자열 외에도 다양한 타입 데이터 쓰기 가능
writer.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
csv 파일 쓰기 다른 기법 (사전 타입으로 파일 쓰기)
- csv.writer 함수 대신에, csv.DictWriter 함수 사용
- field 이름 선언 후, 데이터 넣기
import csv
with open('00_data/tmp_csv.csv', 'w', encoding='utf-8-sig', newline='') as writer_csv:
field_name_list =['First Name', 'Last Name'] # 필드명 정의
writer = csv.DictWriter(writer_csv, fieldnames=field_name_list) # 필드명을 미리 선언할 수 있음
writer.writeheader() # 보통 csv 파일 상단에는 필드명을 넣기 때문에, 선언된 필드명을 writerheader() 함수로 넣을 수 있음
writer.writerow({'First Name': 'tae', 'Last Name': 'park'}) # 각 데이터는 사전 타입으로 저장 가능
writer.writerow({'First Name': 'David', 'Last Name': 'Kim'})
writer.writerow({'First Name': 'Robin', 'Last Name': 'Park'})
• 사전 타입으로 읽기 가능
import csv
with open('tmp_csv.csv', 'r', encoding='utf-8-sig') as reader_csv:
reader = csv.DictReader(reader_csv)
for row in reader:
print(row['First Name'], row['Last Name'])
=>
tae park
David Kim
Robin Park
파이썬은 3총사를 데리고 있다.
- pandas, numpy (데이터 분석)
- matplib, seaborn (시각화)
3. 다양한 데이터 포멧 이해하기: XML
3.1. XML 포멧 이해하기
- XML(Extensible Markup Language)
- 특정 목적에 따라 데이터를 태그로 감싸서 마크업하는 범용적인 포멧
- 마크업 언어는 태그 등을 이용하여 데이터의 구조를 기술하는 언어의 한 가지
- 가장 친숙한 마크업 언어가 HTML
- XML은 HTML과 마찬가지로 데이터를 계층 구조로 표현
- XML 기본 구조
- <태그 속성="속성값">내용</태그>
- 태그와 속성은 특정 목적에 따라 임의로 이름을 정해서 사용
- <product id="M001" price="300000">32인치 LCD 모니터</product>
- 다른 요소와 그룹으로 묶을 수도 있음YAML (야물파일)서버를 일일히 100개를 구성해야 할 때,그래서 XML포맷은 절대 없어지지 않는다.xml언어는 태그를 만들어주면 된다. 태그가 시작되면 끝나는 태그를 만들어줘야 한 문장이 끝난다.
- html은 정해져있는 규칙들이 있다.
- YAML로 만들어서 올리면 자동으로 서버 100대가 만들어진다.
- 데이터포맷에 대해 어떻게 쓸 것인지
- <products type="전자제품"> <product id="M001" price="300000">32인치 LCD 모니터</product> <product id="M002" price="210000">24인치 LCD 모니터</product> </products>
3.2. XML 파일 읽고 데이터 추출하기
- open() 함수로 xml 데이터 읽기
- xml 데이터 파싱하기
- select() 로 원하는 데이터 태그 선택하기
- 리턴값은 리스트 타입
- 원하는 데이터가 하나일 경우에는 select_one() 함수 사용
- 실제 데이터는 각 아이템.text 로 추출가능
data_file = open('users.xml', 'r', encoding='utf-8-sig')
# 1. xml 데이터 읽기
soup = BeautifulSoup(data_file, 'xml')
# 2. xml 데이터 파싱하기
users = soup.select('user')
# 3. 원하는 데이터 관련 태그 선택하기
for user in users:
# 4. 리스트이므로 for 문으로 아이템 추출
print(user.text)
# 5. 각 아이템.text 로 원하는 데이터 출력
파싱 (parsing)과 데이터 추출 코드 이해
- 일종의 xml 데이터를 분석해서, 빠르게 원하는 데이터를 추출할 수 있도록 트리(tree) 형태로 만드는 것
- pip install bs4
from bs4 import BeautifulSoup
soup= BeautifulSoup(xml파일디스크립터, 'xml')
soup.select(원하는 데이터 태그)
트리 형식: 가장 높은 카테고리가 올라가고, 가장 낮은 카테고리가 내려가는 것
- 마크업 언어를 이용해 문서를 구성한다.
예제 코드
from bs4 import BeautifulSoup
data_file = open('users.xml', 'r', encoding='utf-8-sig')
soup = BeautifulSoup(data_file, 'lxml')
users = soup.select('user')
for user in users:
print(user.text)
=>
bigdata-python
30
tae park
21
이름과 나이 각각 추출하려면?
from bs4 import BeautifulSoup
data_file = open('users.xml', 'r', encoding='utf-8-sig')
soup = BeautifulSoup(data_file, 'lxml')
users = soup.select('user')
for user in users:
name = user.select_one('name')
print ('이름:', name.text)
age = user.select_one('age')
print ('나이:', age.text)
=>
이름: bigdata-python
나이: 30
이름: tae park
나이: 21
csv파일도 읽어 본 다음, 나에게 꼭 필요한 데이터만 파싱해서 사용하면 된다. → xml도 도메인에 대한 이해를 하고 들어가야 한다.
예제 코드 (연습 문제 풀이)
연습문제
- <http://suggestqueries.google.com/complete/search?output=toolbar&q=> 에 키워드를 추가하면 연관 검색어를 추출 가능
- XML 포멧으로 되어 있으므로, 태그과 속성값 추출 기술을 활용해서 추출 가능
원하는 데이터가 태그의 속성값에 있을 때에는 아이템[속성이름] 로 추출 가능
다음 셀에 다음 코드를 넣고 다음 마지막 문장을 입력하여 코드를 완성하시오
import requests
from bs4 import BeautifulSoup
keyword = '스마트폰'
google_related_keyword_api = '<http://suggestqueries.google.com/complete/search?output=toolbar&q=>' + keyword
response = requests.get(google_related_keyword_api)
# 파일이 아니라, 데이터를 Open API 에서 가져오기 위한 함수
soup = BeautifulSoup(response.content, 'xml')
# requests.get() 의 리턴값은 객체
# 객체.content 에 가져온 데이터가 있음
datas1 = [-------------------]
for item in datas1:
print(item['data'])
- 답변
import requests
from bs4 import BeautifulSoup
keyword = '아시안컵'
google_related_keyword_api = '<http://suggestqueries.google.com/complete/search?output=toolbar&q=>' + keyword
response = requests.get(google_related_keyword_api) # 파일이 아니라, 데이터를 Open API 에서 가져오기 위한 함수
soup = BeautifulSoup(response.content, 'xml') # requests.get() 의 리턴값은 객체
# 객체.content 에 가져온 데이터가 있음
datas1 = soup.select('suggestion')
for item in datas1:
print(item['data'])
=>
아시안컵
아시안컵 한국 일정
아시안컵 일정
아시안컵 순위
아시안컵 대진표
아시안컵 중계
아시안컵 경기
아시안컵 조별순위
아시안컵 조편성
아시안컵 경기일정
import requests
from bs4 import BeautifulSoup
keyword = '스마트폰'
google_related_keyword_api = '<http://suggestqueries.google.com/complete/search?output=toolbar&q=>' + keyword
response = requests.get(google_related_keyword_api) # 파일이 아니라, 데이터를 Open API 에서 가져오기 위한 함수
soup = BeautifulSoup(response.content, 'xml') # requests.get() 의 리턴값은 객체
# 객체.content 에 가져온 데이터가 있음
datas1 = soup.select('suggestion')
for item in datas1:
print(item['data'])
=>
스마트폰
스마트폰 갤러리
스마트폰 중독
스마트폰을 떨어뜨렸을 뿐인데
스마트폰 중독 테스트
스마트폰 찾기
스마트폰 중독 문제점
스마트폰 배경화면
스마트폰 tv 미러링
스마트폰갤
4. 다양한 데이터 포멧 이해하기: JSON
4.1. JSON 데이터 포멧 이해하기
- JavaScript Object Notation 줄임말
- JSON은 서버와 클라이언트 또는 컴퓨터/프로그램 사이에 데이터를 주고 받을 때 사용하는 데이터 포멧
- 키와 값을 괄호와 세미콜론과 같이 간단한 기호로 구성하여 표현할 수 있고, 언어나 운영체제에 구애받지 않기 때문에 많이 사용됨
- 특히 웹/앱 환경에서 Rest API를 사용하여, 서버와 클라이언트 사이에 데이터를 주고 받을때 많이 사용
- JSON 포멧 예{ "id":"01", "language": "Java", "edition": "third", "author": "Herbert Schildt" }
4.2. JSON 데이터 포멧 읽기
- json 라이브러리 제공
json.loads() 함수로 문자열로된 json 데이터를 사전처럼 다룰 수 있음
import json # pip install json
# 변수에 문자열로 된 JSON 포멧의 데이터가 있을 경우
data = '{ "id":"01", "language": "Java", "edition": "third", "author": "Herbert Schildt" }'
jsondata = json.loads(data)
print (jsondata['id'], jsondata['language'], jsondata['edition'], jsondata['author'], type(jsondata))
=> 01 Java third Herbert Schildt <class 'dict'>
json.dumps() 함수로 파이썬 사전 데이터를 JSON 문자열 데이터로 변환할 수 있음
import json
# 변수에 문자열로 된 JSON 포멧의 데이터가 있을 경우
data = { "id":"01", "language": {"Java":"basic", "Java":"advance"}, "edition": "third", "author": "Herbert Schildt" }
jsondata = json.dumps(data)
print (jsondata, type(jsondata))
jsondata = json.dumps(data, indent=2) # 들여쓰기
print (jsondata, type(jsondata))
=>
{"id": "01", "language": {"Java": "advance"}, "edition": "third", "author": "Herbert Schildt"} <class 'str'>
{
"id": "01",
"language": {
"Java": "advance"
},
"edition": "third",
"author": "Herbert Schildt"
} <class 'str'>
csv파일의 key 값: 가장 위 쪽 목록
→ 이것을 key와 value로 만든 것
json.load() 함수로 파일로된 json 데이터를 사전처럼 다룰 수 있음
- JSON 파일 예: 유투브 카테고리 (미국)
{
"kind": "youtube#videoCategoryListResponse",
"etag": "\\"m2yskBQFythfE4irbTIeOgYYfBU/S730Ilt-Fi-emsQJvJAAShlR6hM\\"",
"items": [
{
"kind": "youtube#videoCategory",
"etag": "\\"m2yskBQFythfE4irbTIeOgYYfBU/Xy1mB4_yLrHy_BmKmPBggty2mZQ\\"",
"id": "1",
"snippet": {
"channelId": "UCBR8-60-B28hp2BmDPdntcQ",
"title": "Film & Animation",
"assignable": true
}
},
{
"kind": "youtube#videoCategory",
"etag": "\\"m2yskBQFythfE4irbTIeOgYYfBU/UZ1oLIIz2dxIhO45ZTFR3a3NyTA\\"",
"id": "2",
"snippet": {
"channelId": "UCBR8-60-B28hp2BmDPdntcQ",
"title": "Autos & Vehicles",
"assignable": true
}
}
]
}
이렇게 데이터를 파싱해서 원하는 데이터를 얻어내야 한다.
items에서 kind, snippet, title을 불러오겠다.
import json
with open('US_category_id.json', 'r', encoding='utf-8-sig') as json_file:
json_data = json.load(json_file)
for item in json_data['items']:
print (item['kind'], item['snippet']['title'])
=>
youtube#videoCategory Film & Animation
youtube#videoCategory Autos & Vehicles
youtube#videoCategory Music
youtube#videoCategory Pets & Animals
youtube#videoCategory Sports
youtube#videoCategory Short Movies
youtube#videoCategory Travel & Events
youtube#videoCategory Gaming
youtube#videoCategory Videoblogging
youtube#videoCategory People & Blogs
youtube#videoCategory Comedy
youtube#videoCategory Entertainment
youtube#videoCategory News & Politics
youtube#videoCategory Howto & Style
youtube#videoCategory Education
youtube#videoCategory Science & Technology
youtube#videoCategory Nonprofits & Activism
youtube#videoCategory Movies
youtube#videoCategory Anime/Animation
youtube#videoCategory Action/Adventure
youtube#videoCategory Classics
youtube#videoCategory Comedy
youtube#videoCategory Documentary
youtube#videoCategory Drama
youtube#videoCategory Family
youtube#videoCategory Foreign
youtube#videoCategory Horror
youtube#videoCategory Sci-Fi/Fantasy
youtube#videoCategory Thriller
youtube#videoCategory Shorts
youtube#videoCategory Shows
youtube#videoCategory Trailers
빅데이터에서 자연어 처리 등의 대규모가 아닌 경우
로컬에서 CPU로 돌릴 수 있는 아나콘다와 주피터노트북을 활용하는 것이 좋다.
→ 로컬 환경에 있는 쥬피터노트북과 아나콘다를 사용하는 것이 좋다.
코랩: 구글에서 대규모 라이브러리를 설치해 두었다.
→ 자연스럽게 환경에 적응되어 있다.
2007년도 인터넷 연결 커넥션이 만들어졌다.
기본적인 표현, 데이터 처리 등을 강의
기본적인 데이터 입출력
PyQt로 미니 프로젝트 진행
1년차: 풀타임 강사
작년부터는 어려운 과목들을 받게 되었다.
기초 과목을 탄탄하게 다진 다음, 어려운 쪽으로 들어가게 되면
컨텐츠와 코드를 보고 어떻게 쓸 것인지 큰 그림을 보고 가야 한다.
나중에는 큰 그림만 그리고 코드를 쓸 줄 알면 된다.
CPU는 써도 기본적으로 메모리가 8기가 이상이다.
CPU와 메모리 쪽에서 누수없이 사용할 수 있다.
외국 쪽 엔지니어는 한 분야만 하기에 최적화 코드를 만들어낸다.
→ 깊이가 다르다.
애플 같은 경우, 상당히 견고하다.
한국 엔지니어가 만들면,
디버그 문제 발생 시, 어디가 문제인지 발견하지 못하는 경우가 많다.
→ 나의 수준을 100에서 4~60까지는 올려야 한다.
→ 어떻게 사용할 것인지는 나의 역량에 따라 다르다.
- 요구가 많으면, 공부할 수 밖에 없다.
파이썬이 강력한 이유
: 직관적이다, 자료를 떄려넣어도 통한다, 문자 숫자 정수 다 넣어도 다 인식할 수 있다.
ITK라는 라이브러리가 있다.
(Insight Toolkit)
컴퓨터 비전: 컴퓨터로 영상처리 하는 것
ITK: 의료영상을 처리하는 라이브러리
→ 파이썬이 들어온 뒤, 컴파일링 할 필요없이 바로 쓸 수 있게 되었다.
빅데이터를 가져올 때, 공공데이터센터(전국에 있는 지자체별)
→ 사람들이 한땀한땀 모은 것
내가 원하는 데이터를 내가 만들고 싶다면, 인터넷에서 사진이나 기사를 긁어와야 한다.
→ 크롤링 (특정 문서에서 원하는 데이터를 코드로 가져와서, 엑셀 파일 등으로 정리할 수 있다.)
용어를 잘 설명해야 한다.
re.sub('\\[0-9]+\\]','',item.get_text()))
→ 이 코드에 대해 쓸 수 있는 표현들을 알고 있으면 쉽게 일하고 집에 갈 수 있다.
정규표현식
age: 나이
Parch: 부모님와 아이
Embarked: 정차, 내리는가
빅데이터 처리를 할 때
어려운 점
: 해당 도메인에 대한 이해가 없으면 절대 접근할 수 없다.
금융, 보험, 의료 데이터 등에 대한 지식이 없으면 접근할 수 없다.
→ 어떻게 도메인을 이해할 것인가? (가장 어려운 부분)
빅데이터: 정량적을 보여주는 것도 있지만, 정성적으로 설득하기 위한 도구일 뿐이다.
→ 나만의 스토리텔링을 만들어서 다른 사람에게 설명할 수 있어야 한다.
가장 스토리를 잘 만든 사람에게 과제를 넘겨준다.
→ 이 스토리텔링을 하기 위해선, 내가 중심이 되어서 어떻게 이야기를 꾸며 나갈 것인가에 대한 생각이 있어야 한다.
- 기승전결로 매끄럽게 이어나가면 좋다.
- 중간에 뭔가 막히면 out이다.
스토리텔링을 잘 만들어나가면서 도메인을 이해해 나가면 된다.
import openpyxl
import re
regex = re.compile(' [A-Za-z]+\\.')
# 엑셀파일 열기
work_book = openpyxl.load_workbook('train.xlsx')
# 현재 Active Sheet 얻기
work_sheet = work_book.active
# work_sheet.rows는 해당 쉬트의 모든 행을 객체로 가지고 있음
for each_row in work_sheet.rows:
print (each_row[3].value)
print (regex.findall(each_row[3].value))
if len(regex.findall(each_row[3].value)) > 0:
if regex.findall(each_row[3].value)[0].strip() == "Mr.":
print ("남성")
work_book.close()
예제: 왜 정규표현식이 필요할까?
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
res = urlopen('<https://davelee-fun.github.io/blog/crawl_test_css.html>')
soup = BeautifulSoup(res, "html.parser")
data = soup.select('ul#dev_course_list li.course')
for item in data:
print (item.get_text())
(초급) - 강사가 실제 사용하는 자동 프로그램 소개 [2]
(초급) - 필요한 프로그램 설치 시연 [5]
(초급) - 데이터를 엑셀 파일로 만들기 [9]
(초급) - 엑셀 파일 이쁘게! 이쁘게! [8]
(초급) - 나대신 주기적으로 파이썬 프로그램 실행하기 [7]
(초급) - 파이썬으로 슬랙(slack) 메신저에 글쓰기 [40]
(초급) - 웹사이트 변경사항 주기적으로 체크해서, 메신저로 알람주기 [12]
(초급) - 네이버 API 사용해서, 블로그에 글쓰기 [42]
(중급) - 자동으로 쿠팡파트너스 API 로 가져온 상품 정보, 네이버 블로그/트위터에 홍보하기 [412]
바퀴를 새로 만들 필요가 없다.
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
res = urlopen('<https://davelee-fun.github.io/blog/crawl_test_css.html>')
soup = BeautifulSoup(res, "html.parser")
data = soup.select('ul#dev_course_list li.course')
for item in data:
print (re.sub('\\[[0-9]+\\]', '', item.get_text()) )
(초급) - 강사가 실제 사용하는 자동 프로그램 소개
(초급) - 필요한 프로그램 설치 시연
(초급) - 데이터를 엑셀 파일로 만들기
(초급) - 엑셀 파일 이쁘게! 이쁘게!
(초급) - 나대신 주기적으로 파이썬 프로그램 실행하기
(초급) - 파이썬으로 슬랙(slack) 메신저에 글쓰기
(초급) - 웹사이트 변경사항 주기적으로 체크해서, 메신저로 알람주기
(초급) - 네이버 API 사용해서, 블로그에 글쓰기
(중급) - 자동으로 쿠팡파트너스 API 로 가져온 상품 정보, 네이버 블로그/트위터에 홍보하기
정규표현식
프로그래밍 연습(생각만 해보기)
다음 코드를 실행해보고, 이름 정보를 통해 남자인지, 여자인지, 기타인지(남녀 구별 불가)를 확인할 수 있는 방법 생각해보기
세 라인의 코드를 추가하면 이름의 특징을 추출할 수 있음
import re
regex = re.compile('[A-Za-z]+\\.')
print ( regex.findall('찾을 문자열') )
pip install openpyxl
import openpyxl
import re
regex = re.compile(' [A-Za-z]+\\.')
# 엑셀파일 열기
work_book = openpyxl.load_workbook('train.xlsx')
# 현재 Active Sheet 얻기
work_sheet = work_book.active
# work_sheet.rows는 해당 쉬트의 모든 행을 객체로 가지고 있음
for each_row in work_sheet.rows:
print (each_row[3].value)
print (regex.findall(each_row[3].value))
work_book.close()
이름 데이터만 보고 성별관련 정보 알아내기
import openpyxl
import re
regex = re.compile(' [A-Za-z]+\\.')
# 엑셀파일 열기
work_book = openpyxl.load_workbook('train.xlsx')
# 현재 Active Sheet 얻기
work_sheet = work_book.active
# work_sheet.rows는 해당 쉬트의 모든 행을 객체로 가지고 있음
for each_row in work_sheet.rows:
print (each_row[3].value)
print (regex.findall(each_row[3].value))
if len(regex.findall(each_row[3].value)) > 0:
if regex.findall(each_row[3].value)[0].strip() == "Mr.":
print ("남성")
work_book.close()
' [A-Za-z]+.' --> regular expression 이라고 함
- 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식
예: 문자, 숫자가 아닌 데이터를 찾아서, '' 로 대체해라(삭제해라)
import re
string = "(Dave)"
re.sub('[^A-Za-z0-9]', '', string) # 문자, 숫자가 아닌 데이터를 찾아서, '' 로 대체해라(삭제해라)
string.replace("(", '').replace(")", '')
정규식에 대한 규칙을 알면 해당 내용들을 규칙별로 찾아낼 수 있다.
위 정규 표현식은 일정한 규칙을 가지고 작성됨, 필요한 패턴은 직접 만들 수도 있음
1. Dot .
- Dot . 메타 문자는 줄바꿈 문자인 \n를 제외한 모든 문자(한 개)를 의미함
- 예: D.A 는 D + 모든 문자(한 개) + A 를 의미
- DAA, DvA, D1A
# 정규 표현식 라이브러리 임포트하기
import re
# 정규 표현식 패턴 만들기
pattern = re.compile('D.A')
# 패턴에 매칭되는지 여부 확인하기 (실습)
pattern.search("DAA")
pattern.search("D1A")
pattern.search("D00A")
pattern.search("DA")
pattern.search("d0A")
pattern.search("d0A D1A 0111")
정말 Dot . 이 들어간 패턴을 찾으려면?
\\. 으로 표시하거나, [.] 으로 표시하면 됨
pattern = re.compile('D\\.A')
pattern.search("D.A")
pattern.search("DDA")
pattern = re.compile('D[.]A')
찾고 바꾸기 (특정 패턴이 매칭되는 것을 찾아서, 다른 문자열로 바꾸기)
string = "DDA D1A DDA DA"
# re.sub(패턴, 바꿀데이터, 원본데이터)
re.sub('D.A', 'Dave', string) # 문자, 숫자가 아닌 데이터를 찾아서, '' 로 대체해라(삭제해라)
2. 반복 ? , * , +
- ? 는 앞 문자가 0번 또는 1번 표시되는 패턴 (없어도 되고, 한번 있어도 되는 패턴)
- 는 앞 문자가 0번 또는 그 이상 반복되는 패턴
-
- 는 앞 문자가 1번 또는 그 이상 반복되는 패턴
# ?사용 예
pattern = re.compile('D?A') # 앞에 문자 D가 없거나, 여러번 반복되고 마지막이 A 인 문자열
pattern.search("A")
=> <re.Match object; span=(0, 1), match='A'>
pattern.search("DA")
=> <re.Match object; span=(0, 2), match='DA'>
pattern.search("DDDDDDA")
=> <re.Match object; span=(5, 7), match='DA'>
# *사용 예
pattern = re.compile('D*A') # 앞에 문자 D가 없거나, 여러번 반복되고 마지막이 A 인 문자열
pattern.search("A")
=> <re.Match object; span=(0, 1), match='A'>
pattern.search("DA")
=> <re.Match object; span=(0, 2), match='DA'>
pattern.search("DDDDDDDDDDDDDDDDDDDDDDDDDDDDA")
=> <re.Match object; span=(0, 29), match='DDDDDDDDDDDDDDDDDDDDDDDDDDDDA'>
pattern = re.compile('AD*A') # 앞에 문자 D가 없거나, 여러번 반복되고 마지막이 A 인 문자열
pattern.search("ADA")
=> <re.Match object; span=(0, 3), match='ADA'>
pattern.search("ADDDDDDDDDDDDDDDDDDA")
=> <re.Match object; span=(0, 20), match='ADDDDDDDDDDDDDDDDDDA'>
또다른 반복 표현: {n}, {m,n}
- {n} : 앞 문자가 n 번 반복되는 패턴
- {m, n} : 앞 문자가 m 번 반복되는 패턴부터 n 번 반복되는 패턴까지
# {n} 사용 예
pattern = re.compile('AD{2}A')
pattern.search("ADA")
pattern.search("ADDA")
=> <re.Match object; span=(0, 4), match='ADDA'>
pattern.search("ADDDA")
# {m,n} 사용 예
pattern = re.compile('AD{2,6}A') # {m,n} 은 붙여 써야 함 {m, n} 으로 쓰면 안됨(특이함)
pattern.search("ADDA")
=> <re.Match object; span=(0, 4), match='ADDA'>
pattern.search("ADDDA")
=> <re.Match object; span=(0, 5), match='ADDDA'>
pattern.search("ADDDDDDA")
=> <re.Match object; span=(0, 8), match='ADDDDDDA'>
3. 괄호 : 괄호 안에 들어가는 문자가 들어 있는 패턴
- 예: [abc] 는 a, b, c 중 하나가 들어 있는 패턴을 말함
pattern = re.compile('[abcdefgABCDEFG]')
pattern.search("a1234")
=> <re.Match object; span=(0, 1), match='a'>
pattern.search("z1234")
하이픈(-)을 이용하면 알파벳 전체를 나타낼 수 있음
- 예: [a-c] 는 a, b, c 중 하나가 들어 있는 패턴을 말함
pattern = re.compile('[a-z]')
pattern.search("k1234")
=> <re.Match object; span=(0, 1), match='k'>
pattern.search("Z1234")
=> <re.Match object; span=(0, 1), match='Z'>
[a-zA-Z] 으로 표기하면 대소문자를 모두 포함해서 알파벳 전체를 나타낼 수 있음
pattern = re.compile('[a-zA-Z]')
pattern.search("Z1234")
=> <re.Match object; span=(0, 1), match='Z'>
[a-zA-Z0-9] 로 표기하면 대소문자를 모두 포함해서 알파벳 전체와 함께 숫자 전체도 나타낼 수 있음
pattern = re.compile('[a-zA-Z0-9]')
pattern.search("1234---")
=> <re.Match object; span=(0, 1), match='1'>
pattern.search("---------------!@#!@$!$%#%%%#%%@$!$!---")
괄호 안에서 [ 바로 뒤에 ^ 을 쓰면 그 뒤에 오는 문자가 아닌 패턴을 찾음
- 문자를 결국 알파벳, 숫자, 특수문자, whitespace(스페이스, 탭, 엔터등) 로 분류할 수 있으므로
- [^ \t\n\r\f\v] 는 이중에서 whitespace 가 아닌 알파벳, 숫자, 특수문자를 지칭함
pattern = re.compile('[^a-zA-Z0-9]')
pattern.search("---------------!@#!@$!$%#%%%#%%@$!$!---")
=> <re.Match object; span=(0, 1), match='-'>
pattern = re.compile('[^ \\t\\n\\r\\f\\v]')
pattern.search("-")
=> <re.Match object; span=(0, 1), match='-'>
pattern.search(" ")
그러면 한글만? --> [가-힣]
pattern = re.compile('[가-힣]')
pattern.search("안")
=> <re.Match object; span=(0, 1), match='안'>
4. 조합해서 써보자
import re
pattern = re.compile('[a-zA-Z]+')
matched = pattern.search("Dave")
print(matched)
=> <re.Match object; span=(0, 4), match='Dave'>
5. 정규 표현식 라이브러리 함수 사용법
match 와 search 함수
- match : 문자열 처음부터 정규식과 매칭되는 패턴을 찾아서 리턴
- search : 문자열 전체를 검색해서 정규식과 매칭되는 패턴을 찾아서 리턴
import re
pattern = re.compile('^[a-z]+')
matched = pattern.match('Dave')
searched = pattern.search("Dave")
print (matched)
=> None
print(searched)
=> <re.Match object; span=(1, 4), match='ave'>
findall 함수: 정규표현식과 매칭되는 모든 문자열을 리스트 객체로 리턴함
import re
pattern = re.compile('[a-z]+')
findalled = pattern.findall('Game of Life in Python')
print (findalled)
=> ['ame', 'of', 'ife', 'in', 'ython']
pattern2 = re.compile('[A-Za-z]+')
findalled2 = pattern2.findall('Game of Life in Python')
print (findalled2)
=> ['Game', 'of', 'Life', 'in', 'Python']
findall 함수를 사용해서 정규표현식에 해당되는 문자열이 있는지 없는지 확인하기
import re
pattern = re.compile('[a-z]+')
findalled = pattern.findall('GAME')
if len(findalled) > 0:
print ("정규표현식에 맞는 문자열이 존재함")
else:
print ("정규표현식에 맞는 문자열이 존재하지 않음")
=> 정규표현식에 맞는 문자열이 존재하지 않음
→
import re
pattern = re.compile('[a-z]+')
findalled = pattern.findall('game')
if len(findalled) > 0:
print ("정규표현식에 맞는 문자열이 존재함")
else:
print ("정규표현식에 맞는 문자열이 존재하지 않음")
=> 정규표현식에 맞는 문자열이 존재함
- 대문자는 존재 X, 소문자 존재 O
split 함수: 찾은 정규표현식 패턴 문자열을 기준으로 문자열을 분리
(분리(분류)해준다.)
import re
pattern2 = re.compile(':')
splited = pattern2.split('python:java')
print (splited)
=> ['python', 'java']
콜론에 맞춰서 Python 과 Java가 분리되며, 리스트 형식으로 반환해준다.
프로그래밍 연습
' VS ' 로 문자열 앞뒤를 분리해보기
A부터 Z까지 숫자가 반복되며 반환하는코드
import re
pattern2 = re.compile(' [A-Z]{2} ')
splited = pattern2.split('python VS java')
print (splited)
=> ['python', 'java']
- ‘VS’가 소문자가 아닌, 대문자로 걸려야 작동한다.
sub 함수: 찾은 정규표현식 패턴 문자열을 다른 문자열로 변경
(특정 문자열이 나오면, 어떠한 것으로 바꿔준다)
import re
pattern2 = re.compile('-')
subed = pattern2.sub('*', '801210-1011323') # sub(바꿀문자열, 본래문자열)
print (subed)
=> 801210*1011323
subed = re.sub('-', '*', '801210-1011323') # sub(정규표현식, 바꿀문자열, 본래문자열)
print (subed)
=>801210*1011323
- 어떤 표현을 쓰는지에 대해 이해하고 있어야 한다.
주민등록번호 뒷자리를 일괄적으로 다른 형태로 표시하는 것을 해보자.
도전 과제
주민번호 뒷자리를 * 로 바꿔서 가려보기
re.sub('-------', '------', each_row[1].value) <--- 정규표현식, 바꿀문자열 을 넣어봅니다.
import openpyxl
work_book = openpyxl.load_workbook('data_kr.xlsx')
work_sheet = work_book.active
for each_row in work_sheet.rows:
print(re.sub('-[0-9]{7}', '-*******', each_row[1].value))
work_book.close()
=>
주민등록번호
800215-*******
821030-*******
841230-*******
790903-*******
800125-*******
820612-*******
→ ‘*’로 일괄 처리에 대한 코드
# 핵심 코드
for each_row in work_sheet.rows:
print(re.sub('-[0-9]{7}', '-*******', each_row[1].value))
응용 과제: 뒷 번호 1자리만 남겨두고 나머지는 변환
import openpyxl
work_book = openpyxl.load_workbook('data_kr.xlsx')
work_sheet = work_book.active
for each_row in work_sheet.rows:
print(re.sub('-[0-9]{7}', '-*******', each_row[1].value))
work_book.close()
=>
주민등록번호
800215-*******
821030-*******
841230-*******
790903-*******
800125-*******
820612-*******
import openpyxl
work_book = openpyxl.load_workbook('data_kr.xlsx')
work_sheet = work_book.active
for each_row in work_sheet.rows:
print(re.sub('[^가-힣].....$', '******', each_row[1].value))
work_book.close()
=>
주민등록번호
800215-2******
821030-1******
841230-2******
790903-1******
800125-1******
820612-2******
PyQt: GUI도 같이 사용할 수 있게 되었다.
→ 파이썬의 약점 보완
머신러닝을 배우게 되면, 함수들을 어떻게 사용할 것인가에 대한 정의를 잘 정리해둬야 한다.
(너무 얕지도, 깊지도 않게 사용해야 한다.)
오캄스 레이저
: 모든 조건이 동등했을 때, 단순한 게 정답이다.
→ 아무리 어려운 문제를 만나더라도, 단순하게 생각하자.
다차원 공간
- 머신러닝과 인공지능은 다차원 공간으로 확장된다.
일상적인 생활에 냄새가 들어가면 4차원
소리가 들어가면 5차원
내가 만약에 그랬었더라면
→ 내가 요리사가 되는 길이 있고, 중국인 요리사가 되는 길이 있고, 경영할 수 있는 길이 있었다.
(다차원 공간에서 사랑이라는 결론을 내린다.)
in my time: 인공지능도 다차원 공간에서 차원을 축소하고 오캄스 레이저로 가장 간단한 답이 나오면, 그것이 정답이다.
- 세상의 모든 원리는 비슷하다.
퀀텀 컴퓨터: 빛의 입자속도로 계산해준다.
→ 단순하게 문제를 풀어내자.
문자열 관련 함수 알아보기
문자열에 있는 특정 문자 갯수 세기 (count 함수)
data = 'Dave David'
data.count('v') # 문자열에 D 가 몇 번 나올까요? 대소문자도 구별함
문자열에 있는 특정 문자의 위치 알려주기
index 함수
string = 'Dave ID is dave'
string.index('i') # 맨 앞 자리부터 0, 1, ... 순으로 위치를 표시
=> 8
해당 문자가 문자열에 없을 때, 에러를 안낼 수는 없을까? --> find 함수를 사용하면 됨
- find 함수는 해당 문자가 문자열에 없으면 -1 을 리턴함 (에러는 내지 않음)
- 이외에는 index 함수와 동일
string = 'dave is david'
string.find('x')
string = 'Dave ID is dave'
string.find('D ') # 맨 앞 자리부터 0, 1, ... 순으로 위치를 표시
if string.find('x') == -1:
print ("x는 스트링에 없습니다.")
=> x는 스트링에 없습니다.
문자열 사이에 다른 문자 넣기
string = "12345"
comma = ','
comma.join(string) # 껴넣을 문자.join(문자열)
=> '1,2,3,4,5'
문자열 앞뒤에 공백 지우기
- 실제 현실 세계에 있는 문자열 데이터를 정리하다보면, 문자열 앞뒤에 공백 또는 기호가 있는 경우가 많음
strip( )함수: 지워주다, 제거하다.
data = " Dave "
data.strip() # 앞 뒤 공백을 다 지움
=> 'Dave'
string2 = " David "
string2.strip() # 앞 뒤 공백이 여러개 있어도 한번에 다 지움
=> 'David'
string2.lstrip() # 앞쪽(문자열 왼쪽)만 지우기 left strip 의 약자
=> 'David '
string2.rstrip() # 앞쪽(문자열 오른쪽)만 지우기 right strip 의 약자
=> ' David'
string = " 9999999999999999(Dave)888888888888888888 "
string.strip(" 98()") # 앞 뒤 괄호를 다 지움
=> 'Dave'
- 퍼테이션마크: 문자열을 지정하는 ‘ ‘를 의미
영문자 대소문자로 변환하기¶
- 대소문자를 구별하기 때문에, 대소문자 구별하지 않고 처리를 하기 위해 임의로 대문자 또는 소문자로 다 바꿀 때가 있음
소문자를 대문자로 바꾸기
string = 'Dave'
string.upper() # 본래 대문자는 놔두고, 소문자인 문자만 대문자로 변경
=> 'DAVE'
대문자를 소문자로 바꾸기
string = 'Dave'
string.lower() # 본래 소문자는 놔두고, 대문자인 문자만 대문자로 변경
=> 'dave'
문자열을 나누기
string = "Dave goes to Korea"
string.split() # split() 인자를 넣지 않으면 디폴트로 스페이스를 기준으로 분리
=> ['Dave', 'goes', 'to', 'Korea']
string = "Dave goes to Korea"
string.split()[3]
=> 'korea'
string.split(' ') # 명시적으로 스페이스를 기준으로 분리하겠다고 넣어줘도 됨
=> ['Dave', 'goes', 'to', 'Korea']
string = "Dave/goes/to/Korea"
string.split('/') # split() 인자를 넣으면 해당 인자를 기준으로 분리
=> ['Dave', 'goes', 'to', 'Korea']
프로그래밍 연습
string = "10,11,22,33,44" 를 컴마(,) 로 분리해서 리스트 변수를 만들어 각 값을 정수형 리스트 데이터로 넣기
int('11') 을 실행하면 숫자 11로 변환
string = "10,11,22,33,44"
string.split(',')
=> ['10', '11', '22', '33', '44']
string = "10,11,22,33,44"
listdata = string.split(',')
for index, listitem in enumerate(listdata):
listdata[index] = int(listitem)
print (listdata)
=> [10, 11, 22, 33, 44]
string = "10,11,22,33,44"
split_string = string.split(',')
for index, split_item in enumerate(split_string):
split_string[index] = int(split_item)
print (split_string)
=> [10, 11, 22, 33, 44]
문자열 중 일부를 다른 문자로 바꾸거나, 삭제하기
string = "David goes to Korea"
string.replace("David", "Dave") # David 를 Dave 로 바꾸기
=> 'Dave goes to Korea'
string2 = "(Dave)"
string2.replace("()", "") # 연결된 문자열은 해당 문자열이 동일하게 매칭이 되어야 함
=> '(Dave)'
string2.replace("(", "")
=> 'Dave)'
string2.replace(")", "")
=> '(Dave'
string2 = string2.replace("(", "") # ( 가 삭제된 문자열로 변수 값을 덮어 씌운 후에 다시 ) 를 삭제하면 됨
string2.replace(")", "")
=> 'Dave'
string2 = "(Dave)"
string2.replace("(", "").replace(")", "")
=> 'Dave'
프로그래밍 연습
string = "10,11,22,33,44" 에서 컴마(,) 를 / 으로 대체하기
string = "10,11,22,33,44"
string.replace(",", " ")
=> '10 11 22 33 44'=
- xml파일: HTML에서 시작과 끝을 알려주는 태그형식
→ 과거 정부에서는 csv파일보단, xml파일형식이 더 많았다.
- json파일: 딕셔너리 형식으로 제공되는 형식
특정 데이터 포맷을 사용하지 않는, 일반적인 텍스트를 Plain Text라고 한다.
1. 다양한 데이터 포멧 이해하기: Plain Text
- Plain Text: 특정 데이터 포멧을 사용하지 않는, 일반적인 텍스트를 의미함
- 주요 데이터 포멧
- csv, xml, json
- 참고: https://www.data.go.kr/search/index.do
통상적으로 데이터 처리에서 다루는 Plain Text 보다는 특정 데이터 포멧을 사용하는 경우가 많음
1.1 파일 오픈 (Plain Text)
- 프로그래밍에서 파일은 다음과 같은 3가지 명령의 순서로 처리할 수 있음
- 파일 오픈
- 파일 읽기 또는 쓰기
- 파일 닫기
- 파일디스크립터변수 = open(파일이름, 파일열기모드)
data_file = open('00_data/text_data.txt', 'r', encoding='utf-8-sig')
- 파일 디스크립터 (file descriptor) 변수: 오픈한 파일 객체를 가리키고 있는 변수
- 파일 이름 명시시, open 함수 실행 위치와 파일 이름이 저장된 위치를 파일 절대 경로 또는 상대 경로로 정확히 명시해야 함
- 파일 열기 모드
파일열기모드 설명
r | 읽기 모드: 파일을 읽기만 할 때 사용함 |
w | 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) |
a | 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함 |
컴퓨터를 끄지 않고 사용할 경우, 컴퓨터가 느려진다.
→ 메모리에 있는 명령어를 처리하는데 시간이 오래 걸린다.
(자잘한 문서들이 많이 쌓이면
Java: 객체 지향형 언어로, 객체들이 붕어빵 찍듯이 만들어낼 수 있다.
(단일 상속), 상속을 1번만 해준다.
인터페이스 상속이라고 어떻게 상속하는지
정기적으로 자기가 만들어낸 객체를 지워주는 가비지클리닝 기능이 들어있다.
시스템을 관리하는 측에서 컴퓨터를 매번 껏다 킬 필요가 없다.
→ 항상 최적의 상태를 유지할 수 있다.
필요없는 파일은 닫아두는 습관을 길들일 필요가 있다.
encoding: 아스키 코드를 표준규약에 맞춰 화면에 주는 하나의 규약
- 인코더와 디코더
인코더: 암호를 만든다.
디코더: 암호를 푼다.
딥러닝의 오토 인코더: 자동으로 인코딩을 해준다.
- 인코딩: 압축한다.
- 딥러닝의 비지도학습: 오토인코더
(데이터가 많이 없을 때 사용하는 방식)
공장을 돌릴 때, 비정상 데이터가 더 적다.
정상 데이터와 비정상 데이터의 수를 맞춰야 하므로 오토인코딩을 통해 가공으로 비정상 데이터를 만들어준다.
- 자연어 처리에서 핫한 트랜스포머
: 인코더와 디코더 부분을 따로 해준 것
인코더: 자연어 처리를 할 수 있는 바트
디코더: GPT
⇒ 트랜스포머
트랜스포머와 자연어 처리는 책이 없고, 논문밖에 없다.
→ 공부하고 싶어도 어렵다.
참고: 인코딩과 utf-8 과 utf-8-sig
인코딩이란?
utf-8 과 utf-8-sig
- 기존에는 영어 인코딩, 한국어 인코딩 방식이 달랐음. 이에 따라 각 국가에서 작성된 파일을 읽을 수 없는 경우가 발생
- 모든 언어를 지원하는 인코딩 방식을 통해 다른 언어 지원, 이를 유니코드 라고 함
- 각 인코딩 방식마다 이름이 존재 하며, 유니코드는 utf-8 이라는 이름을 사용함
- 각 인코딩 방식에 맞게, 데이터를 저장하고, 데이터를 읽을 때에는 해당 인코딩 방식을 명시해주어, 데이터를 알맞게 읽을 수 있음
- utf 방식도 세부적으로는 utf-8, utf-16, utf-32 등 다양한 방식이 있으며, 이를 구별하기 위해, 윈도우의 텍스트 편집기들은 데이터 저장시 앞부분에 특정 기호(signature)를 추가함
- 해당 기호(signature)를 Byte Order Mark(BOM) 이라고 부름
- 문제는 해당 기호(signature)를 맥 또는 리눅스등 다른 운영체제 환경에서는 지원하지 않아서 잘못 인식할 수 있음
- 근본적으로 윈도우를 개발한 MS사가 표준과 다른, 자기만의 signature를 넣는 방식을 썼다는 것이 문제임
- 그래서, 데이터 오픈시, BOM이 있다면, BOM 빼고, 데이터를 읽을 수 있도록 하여, 호환성 문제를 해결하는 방식이 utf-8-sig 임
- 파일 데이터 오픈시, 인코딩에 문제가 있어 보일 경우, 또는 기본적으로 encoding='utf-8-sig' 를 사용하면 큰 문제가 없음
참고: 파일 절대 경로와 상대 경로
- 절대 경로
- 최초의 시작점으로 경유한 경로를 전부 기입하는 방식
- 윈도우 예: 드라이브명부터 시작, C:\ 등
- C:\\Users\\UserID\\Desktop\\test.txt
- 맥 예: 최상단 디렉토리를 나타내는 / 부터 시작
- 맥: /Users/tae/test.txt
- 상대 경로
- 파일을 찾는 위치부터 상대적인 경로를 기입하는 방식
- 예
- 현재 폴더가 /Users/tae/code 인 상태에서 동일 폴더에 있는 testfile.txt 를 찾는 경우
- testfile.txt
- 현재 폴더가 /Users/tae/code 인 상태에서 하위 폴더인 /Users/tae/code/data 폴더에 있는 testfile.txt 를 찾는 경우
- 현재 폴더 안에 있는 폴더를 하위 폴더라고 함
- 하위 폴더명/파일명 과 같은 형태로 상대 경로를 작성하면 됨
data/testfile.txt
- 현재 폴더가 /Users/tae/code 인 상태에서 상위 폴더인 /Users/tae/ 폴더에 있는 testfile.txt 를 찾는 경우
- 현재 폴더를 포함하고 있는 상위에 있는 폴더를 상위 폴더라고 함
- 상위 폴더는 ../ 로 명시할 수 있음
../testfile.txt
리눅스와 윈도우 중, 리눅스 일처리가 더 빠르다.
리눅스는 30분에 설치가 다 된다.
쉽게 쉽게 컴퓨팅 환경 구성이 될 수 있다.
- 개발 환경 맞추는 것도 어렵다.
버전이 다를 경우, 맞춰야 한다.
→ 어떻게 환경을 꾸릴 것인가?
연습문제
- 다음 상황에서 파일 절대 경로와 상대 경로 작성하기
- 현재 폴더: /Users/tae/code
- 파일 위치: /Users/
- 파일 명: testfile.txt
- data/testfile.txt
- 상대 경로: ../../testfile.txt
- 다음 상황에서 파일 절대 경로와 상대 경로 작성하기
- 현재 폴더: /Users/tae/code
- 파일 위치: /Users/tae/code/program/data
- 파일 명: testfile.txt
- 파일디스크립터변수.close() 함수로 파일을 닫을 수 있음
- 항상 오픈한 파일은 닫아야 함 (파일을 오픈한 채로 놔두면, 컴퓨터에서 관련 자원을 계속 사용중인 상태가 될 수 있음)
data_file = open('text_data.txt', 'r', encoding='utf-8-sig') data_file.close()
- 자동으로 파일을 닫기 위해 with 구문을 사용활용할 수 있음
- with open() 명령 as 파일디스크립터:
- with 구문 안에서 동작할 코드를 탭으로 들여쓰기 해서 사용하면, with 구문이 모두 끝난 후, 자동으로 해당 파일을 닫아줌
1.3 파일 읽기with open('00_data/text_data.txt', 'r', encoding='utf-8-sig') as file_desc: print ('test') => test
- 오픈한 파일 디스크립터.readlines() 함수를 호출해서, 전체 데이터를 한줄씩 리스트타입으로 읽어올 수 있음
• 리스트 타입 변수는 항상 for 구문을 사용해서, 각 아이템을 가져오기readline() 함수 사용하기data_file = open('text_data.txt', 'r', encoding='utf-8-sig') data_lines = data_file.readlines() data_lines => ['안녕하세요. tae 입니다.\\n', '본 예제는 Plain Text 파일 예제입니다.\\n', '감사합니다.']
- 오픈한 파일 디스크립터.readline() 함수를 호출해서, 현재까지 읽은 파일 데이터의 다음 한 줄을 문자열 타입으로 읽을 수 있음
read() 함수 사용하기data_file = open('00_data/text_data.txt', 'r', encoding='utf-8-sig') data_line = data_file.readline() print (data_line) => 안녕하세요. tae 입니다. data_line = data_file.readline() print (data_line) => 본 예제는 Plain Text 파일 예제입니다. data_line = data_file.readline() print (data_line) => 감사합니다. data_file.close()
- 오픈한 파일 디스크립터.read() 함수를 호출해서, 전체 파일 데이터를 문자열 타입으로 읽을 수 있음
1.4 파일 쓰기data_file = open('00_data/text_data.txt', 'r', encoding='utf-8-sig') data = data_file.read() data => '안녕하세요. tae 입니다.\\n본 예제는 Plain Text 파일 예제입니다.\\n감사합니다.' data_file.close()
- open() 함수에 파일열기모드를 'w' 로 해서, 파일 쓰기
r 읽기 모드: 파일을 읽기만 할 때 사용함 w 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) a 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함 - open() 함수에 파일열기모드를 'a' 로 해서, 파일 쓰기
r 읽기 모드: 파일을 읽기만 할 때 사용함 w 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) a 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함
연습문제data_file = open('00_data/text_data_write.txt', 'a', encoding='utf-8-sig') data_file.write('본 파일은 임시 파일입니다.') data_file.close()
- 00_data/text_data_practice.txt 파일 만들고, 다음 내용 쓰기 (각 데이터별 라인을 바꿔주도록 저장)
- 00_data/text_data_practice.txt 파일에 다음 내용 추가하기
- 00_data/text_data_practice.txt 파일 읽고, 다음과 같이 출력되는지 확인하기
# Write to the text file with open('text_data_practice.txt', 'w') as file: file.write("유치원A\\n초등학교B\\n중학교C\\n고등학교D\\n") # Append to the text file with open('text_data_practice.txt', 'a') as file: file.write("대학교E\\n") # Read from the text file and print the content with open('text_data_practice.txt', 'r') as file: content = file.read() print(content) => 유치원A 초등학교B 중학교C 고등학교D 대학교E
2. 다양한 데이터 포멧 이해하기: CSV- 주요 데이터 포멧
- csv, xml, json, plain text
- 파일디스크립터변수 = open(파일이름, 파일열기모드)
data_file = open('00_data/USvideos.csv', 'r', encoding='utf-8-sig')
- 파일 디스크립터 (file descriptor) 변수: 오픈한 파일 객체를 가리키고 있는 변수
- 파일 이름 명시시, open 함수 실행 위치와 파일 이름이 저장된 위치를 파일 절대 경로 또는 상대 경로로 정확히 명시해야 함
- 파일 열기 모드
r 읽기 모드: 파일을 읽기만 할 때 사용함 w 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) a 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함 - encoding
- open(파일이름, 파일열기모드, encoding='utf-8-sig') 와 같이 끝에 encoding 구문 추가 가능 (옵션)
- 파일 오픈시, 해당 파일의 인코딩 방식을 명시해주는 것임
- # text_data_practice.txt 파일을 만들고, # 각 데이터 별 라인을 바꿔주도록 내용 적기 # 유치원A, 초등학교B, 중학교C, 고등학교D data_file = open('text_data_practice.txt', 'w', encoding='utf-8-sig') data_file.write('유치원A\\n') data_file.write('초등학교B\\n') data_file.write('중학교C\\n') data_file.write('고등학교D\\n') data_file.close() # 해당 파일에 '대학교E' 내용 추가하기 data_file = open('text_data_practice.txt', 'a', encoding='utf-8-sig') data_file.write('대학교E\\n') data_file.close() # 해당 파일을 읽고, 다음과 같이 출력되는지 확인하기 # 유치원A # 초등학교B # 중학교C # 고등학교D # 대학교E data_file = open('text_data_practice.txt', 'r', encoding='utf-8-sig') data = data_file.read() data => '유치원A\\n초등학교B\\n중학교C\\n고등학교D\\n대학교E\\n'
- 고등학교D
- 초등학교B
- 고등학교D
- 초등학교B
- data_file = open('text_data_write.txt', 'w', encoding='utf-8-sig') data_file.write('안녕하세요\\n') data_file.write('tae 입니다.\\n') data_file.close()
- data_file = open('text_data_write.txt', 'w', encoding='utf-8-sig') data_file.write('안녕하세요') data_file.write('tae 입니다.') data_file.close()
- write() 함수 사용하기
- for data_line in data_lines: print (data_line) data_file.close() => 안녕하세요. tae 입니다. 본 예제는 Plain Text 파일 예제입니다. 감사합니다.
- readlines() 함수 사용하기
- 상대 경로: program/data/testfile.txt
2.2. csv 파일 읽기
- CSV(Comma-Separated Values): 스프레드시트 데이터를 저장할 때 가장 널리 쓰이는 파일 형식
- 엑셀등 여러 응용프로그램에서도 지원
- CSV 형식 (각 열은 콤마로 구분, 각 행은 줄바꿈 문자로 구분)
- tae, taepark apple, 2 korea, japan, chian
- 파이썬에서 CSV 파일로 저장/읽기 방법
- csv 라이브러리 사용
csv 라이브러리
- anaconda 에 포함
- 만약 다음 코드 실행시 No module 에러 메세지가 나오면, csv 라이브러리 설치 후, 재실행
pip install csv
머신러닝을 배우게 되면 데이터가 tab 형식으로 나눠져 있다.
가장 많이 쓰이는 데이터 형식이 csv파일이다.
csv 파일을 join( 2개를 하나로 합쳐서)해서 사용하기도 한다.
시간별로 데이터를 분리해서 월 평균, 주 평균 등등을 만들어서
머신러닝과 딥러닝을 할 수 있는 하나의 피처로 만든다.
데이터에서 csv파일이 많은 이유가 뭘까?
xml파일에서 csv파일이 많아진 이유가 무엇일까?
ERP, CRM(고객 관계 관리), SCM(어떻게 물건을 공급해서 맞출 것인가?)
⇒ 이 3가지를 회사에선 SQL문으로 만든다.
모든 데이터들을 오라클에서 사용하는 SQL로 만든다.
기업체에서 만들어지는 데이터들은 csv파일로 만들어진다.
기업체에서는 각각의 테이블을 잘라두었다.
은행권에서 SQL을 사용한다고 하면,
2개의 테이블을 상관없는 것끼리 뭉친다.
→ SQL의 기본
csv파일에 대해서 SQL을 기본적으로 어떻게 다뤄야 하는지 알고 있어야 한다.
기업체에서 사용하는 모든 것들은 SQL로 만들어진다.
그래서, csv파일이 많을 수 밖에 없다.
import csv
- 분석 SQL을 배우는 것은 좋지만, 어렵다.
자연어 처리, 분석 SQL
→ 파이썬기반으로 처리할 수 있다.
csv.reader(오픈한 파일 디스크립터, delimiter=',')
- open 함수를 통해 오픈한 파일 디스크립터
- delimiter=데이터구분자: csv 파일 내에 데이터 구분자를 명시할 수 있음 (옵션)delimeter로 바꾸면 똑같은 csv 형식으로 불러올 수 있다.데이터 읽기
- 각 라인별 데이터를 읽기 위해, for 문을 사용하면 됨
- data_lines = csv.reader(data_file, delimiter=',') for data_line in data_lines: print (data_line)
- 대부분 ‘,’로 구분되어 있다.
- data_file = open('00_data/USvideos.csv', 'r', encoding='utf-8-sig') data_lines = csv.reader(data_file, delimiter=',')
파일 닫기 (close)
- 오픈한 파일은 반드시 닫아야 함, 닫지 않으면 파일이 오픈된 채로 남아있을 수 있음
data_file = open('00_data/USvideos.csv', 'r', encoding='utf-8-sig')
data_lines = csv.reader(data_file, delimiter=',')
for data_line in data_lines:
print (data_line)
data_file.close()
예 (한줄만 출력해봄)
import csv
data_file = open('USvideos.csv', 'r', encoding='utf-8-sig')
data_lines = csv.reader(data_file, delimiter=',')
for data_line in data_lines:
print (data_line)
break
data_file.close()
=> ['video_id', 'title', 'channel_title', 'category_id', 'tags', 'views', 'likes', 'dislikes', 'comment_total', 'thumbnail_link', 'date']
csv 파일 읽기 다른 기법
- with 문법을 사용해서, 파일 데이터를 읽은 후, with 내부 구문 실행 완료 후, 자동으로 파일을 닫을 수 있음
import csv
with open('00_data/USvideos.csv', 'r', encoding='utf-8-sig') as reader_csv:
reader = csv.reader(reader_csv, delimiter=',')
for row in reader:
print (row)
break
=> ['video_id', 'title', 'channel_title', 'category_id', 'tags', 'views', 'likes', 'dislikes', 'comment_total', 'thumbnail_link', 'date']
2.3 csv 파일 쓰기
- open 시 'w' 로 옵션을 설정
- open() 함수에 newline='' 를 넣어주는 이유는 윈도우의 경우에만 csv 모듈에서 데이타를 쓸 때 각 라인 뒤에 빈 라인이 추가되는 문제가 있기 때문
- 이를 없애기 위해 (파이썬 3 에서) 파일을 open 할 때 newline='' 와 같은 옵션을 지정
data_file = open('00_data/data.csv', 'w', encoding='utf-8-sig', newline='')
- csv.reader 대신, csv.writer 함수 사용
data_write = csv.writer(data_file, delimiter=',')
- writerow 함수에 리스트 형식으로 데이터를 넣으면, 한 라인씩 파일에 추가 됨
- 파일 close 는 파일 읽기와 동일함
import csv
data_file = open('tmp_csv.csv', 'w', encoding='utf-8-sig', newline='')
data_write = csv.writer(data_file, delimiter=',')
data_write.writerow(['1', '2', '3'])
data_file.close()
(pandas가 기본이다.)
csv 파일 쓰기 다른 기법 (with)
- with 문법을 사용해서, with 내부 구문 실행 완료 후, 자동으로 파일을 닫을 수 있음
쓰레기 데이터가 들어가면, 쓰레기가 나온다.
어떤 데이터는 평균이 0과 1사이이고 어떤 데이터는 평균이 100이면 outlyler라고 한다. 빈 데이터는 기존에 있던 평균값을 대체하는 식으로 빈 칸을 채워넣음을 통해 결과를 산출해야 한다.
데이터는 태국이나 방글라데시에서 만든다. (아웃소싱)
→ 데이터를 어떻게 사용하는가가 핵심이다.
import csv
with open('tmp_csv.csv', 'w', encoding='utf-8-sig', newline='') as writer_csv:
writer = csv.writer(writer_csv, delimiter=',')
writer.writerow(['love']*3 + ['banana']) # ['love', 'love', 'love', 'banana'] 와 동일
writer.writerow(['apple', 2]) # 문자열 외에도 다양한 타입 데이터 쓰기 가능
writer.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
csv 파일 쓰기 다른 기법 (사전 타입으로 파일 쓰기)
- csv.writer 함수 대신에, csv.DictWriter 함수 사용
- field 이름 선언 후, 데이터 넣기
import csv
with open('00_data/tmp_csv.csv', 'w', encoding='utf-8-sig', newline='') as writer_csv:
field_name_list =['First Name', 'Last Name'] # 필드명 정의
writer = csv.DictWriter(writer_csv, fieldnames=field_name_list) # 필드명을 미리 선언할 수 있음
writer.writeheader() # 보통 csv 파일 상단에는 필드명을 넣기 때문에, 선언된 필드명을 writerheader() 함수로 넣을 수 있음
writer.writerow({'First Name': 'tae', 'Last Name': 'park'}) # 각 데이터는 사전 타입으로 저장 가능
writer.writerow({'First Name': 'David', 'Last Name': 'Kim'})
writer.writerow({'First Name': 'Robin', 'Last Name': 'Park'})
• 사전 타입으로 읽기 가능
import csv
with open('tmp_csv.csv', 'r', encoding='utf-8-sig') as reader_csv:
reader = csv.DictReader(reader_csv)
for row in reader:
print(row['First Name'], row['Last Name'])
=>
tae park
David Kim
Robin Park
파이썬은 3총사를 데리고 있다.
- pandas, numpy (데이터 분석)
- matplib, seaborn (시각화)
3. 다양한 데이터 포멧 이해하기: XML
3.1. XML 포멧 이해하기
- XML(Extensible Markup Language)
- 특정 목적에 따라 데이터를 태그로 감싸서 마크업하는 범용적인 포멧
- 마크업 언어는 태그 등을 이용하여 데이터의 구조를 기술하는 언어의 한 가지
- 가장 친숙한 마크업 언어가 HTML
- XML은 HTML과 마찬가지로 데이터를 계층 구조로 표현
- XML 기본 구조
- <태그 속성="속성값">내용</태그>
- 태그와 속성은 특정 목적에 따라 임의로 이름을 정해서 사용
- <product id="M001" price="300000">32인치 LCD 모니터</product>
- 다른 요소와 그룹으로 묶을 수도 있음YAML (야물파일)서버를 일일히 100개를 구성해야 할 때,그래서 XML포맷은 절대 없어지지 않는다.xml언어는 태그를 만들어주면 된다. 태그가 시작되면 끝나는 태그를 만들어줘야 한 문장이 끝난다.
- html은 정해져있는 규칙들이 있다.
- YAML로 만들어서 올리면 자동으로 서버 100대가 만들어진다.
- 데이터포맷에 대해 어떻게 쓸 것인지
- <products type="전자제품"> <product id="M001" price="300000">32인치 LCD 모니터</product> <product id="M002" price="210000">24인치 LCD 모니터</product> </products>
3.2. XML 파일 읽고 데이터 추출하기
- open() 함수로 xml 데이터 읽기
- xml 데이터 파싱하기
- select() 로 원하는 데이터 태그 선택하기
- 리턴값은 리스트 타입
- 원하는 데이터가 하나일 경우에는 select_one() 함수 사용
- 실제 데이터는 각 아이템.text 로 추출가능
data_file = open('users.xml', 'r', encoding='utf-8-sig')
# 1. xml 데이터 읽기
soup = BeautifulSoup(data_file, 'xml')
# 2. xml 데이터 파싱하기
users = soup.select('user')
# 3. 원하는 데이터 관련 태그 선택하기
for user in users:
# 4. 리스트이므로 for 문으로 아이템 추출
print(user.text)
# 5. 각 아이템.text 로 원하는 데이터 출력
파싱 (parsing)과 데이터 추출 코드 이해
- 일종의 xml 데이터를 분석해서, 빠르게 원하는 데이터를 추출할 수 있도록 트리(tree) 형태로 만드는 것
- pip install bs4
from bs4 import BeautifulSoup
soup= BeautifulSoup(xml파일디스크립터, 'xml')
soup.select(원하는 데이터 태그)
트리 형식: 가장 높은 카테고리가 올라가고, 가장 낮은 카테고리가 내려가는 것
- 마크업 언어를 이용해 문서를 구성한다.
예제 코드
from bs4 import BeautifulSoup
data_file = open('users.xml', 'r', encoding='utf-8-sig')
soup = BeautifulSoup(data_file, 'lxml')
users = soup.select('user')
for user in users:
print(user.text)
=>
bigdata-python
30
tae park
21
이름과 나이 각각 추출하려면?
from bs4 import BeautifulSoup
data_file = open('users.xml', 'r', encoding='utf-8-sig')
soup = BeautifulSoup(data_file, 'lxml')
users = soup.select('user')
for user in users:
name = user.select_one('name')
print ('이름:', name.text)
age = user.select_one('age')
print ('나이:', age.text)
=>
이름: bigdata-python
나이: 30
이름: tae park
나이: 21
csv파일도 읽어 본 다음, 나에게 꼭 필요한 데이터만 파싱해서 사용하면 된다. → xml도 도메인에 대한 이해를 하고 들어가야 한다.
예제 코드 (연습 문제 풀이)
연습문제
- <http://suggestqueries.google.com/complete/search?output=toolbar&q=> 에 키워드를 추가하면 연관 검색어를 추출 가능
- XML 포멧으로 되어 있으므로, 태그과 속성값 추출 기술을 활용해서 추출 가능
원하는 데이터가 태그의 속성값에 있을 때에는 아이템[속성이름] 로 추출 가능
다음 셀에 다음 코드를 넣고 다음 마지막 문장을 입력하여 코드를 완성하시오
import requests
from bs4 import BeautifulSoup
keyword = '스마트폰'
google_related_keyword_api = '<http://suggestqueries.google.com/complete/search?output=toolbar&q=>' + keyword
response = requests.get(google_related_keyword_api)
# 파일이 아니라, 데이터를 Open API 에서 가져오기 위한 함수
soup = BeautifulSoup(response.content, 'xml')
# requests.get() 의 리턴값은 객체
# 객체.content 에 가져온 데이터가 있음
datas1 = [-------------------]
for item in datas1:
print(item['data'])
- 답변
import requests
from bs4 import BeautifulSoup
keyword = '아시안컵'
google_related_keyword_api = '<http://suggestqueries.google.com/complete/search?output=toolbar&q=>' + keyword
response = requests.get(google_related_keyword_api) # 파일이 아니라, 데이터를 Open API 에서 가져오기 위한 함수
soup = BeautifulSoup(response.content, 'xml') # requests.get() 의 리턴값은 객체
# 객체.content 에 가져온 데이터가 있음
datas1 = soup.select('suggestion')
for item in datas1:
print(item['data'])
=>
아시안컵
아시안컵 한국 일정
아시안컵 일정
아시안컵 순위
아시안컵 대진표
아시안컵 중계
아시안컵 경기
아시안컵 조별순위
아시안컵 조편성
아시안컵 경기일정
import requests
from bs4 import BeautifulSoup
keyword = '스마트폰'
google_related_keyword_api = '<http://suggestqueries.google.com/complete/search?output=toolbar&q=>' + keyword
response = requests.get(google_related_keyword_api) # 파일이 아니라, 데이터를 Open API 에서 가져오기 위한 함수
soup = BeautifulSoup(response.content, 'xml') # requests.get() 의 리턴값은 객체
# 객체.content 에 가져온 데이터가 있음
datas1 = soup.select('suggestion')
for item in datas1:
print(item['data'])
=>
스마트폰
스마트폰 갤러리
스마트폰 중독
스마트폰을 떨어뜨렸을 뿐인데
스마트폰 중독 테스트
스마트폰 찾기
스마트폰 중독 문제점
스마트폰 배경화면
스마트폰 tv 미러링
스마트폰갤
4. 다양한 데이터 포멧 이해하기: JSON
4.1. JSON 데이터 포멧 이해하기
- JavaScript Object Notation 줄임말
- JSON은 서버와 클라이언트 또는 컴퓨터/프로그램 사이에 데이터를 주고 받을 때 사용하는 데이터 포멧
- 키와 값을 괄호와 세미콜론과 같이 간단한 기호로 구성하여 표현할 수 있고, 언어나 운영체제에 구애받지 않기 때문에 많이 사용됨
- 특히 웹/앱 환경에서 Rest API를 사용하여, 서버와 클라이언트 사이에 데이터를 주고 받을때 많이 사용
- JSON 포멧 예{ "id":"01", "language": "Java", "edition": "third", "author": "Herbert Schildt" }
4.2. JSON 데이터 포멧 읽기
- json 라이브러리 제공
json.loads() 함수로 문자열로된 json 데이터를 사전처럼 다룰 수 있음
import json # pip install json
# 변수에 문자열로 된 JSON 포멧의 데이터가 있을 경우
data = '{ "id":"01", "language": "Java", "edition": "third", "author": "Herbert Schildt" }'
jsondata = json.loads(data)
print (jsondata['id'], jsondata['language'], jsondata['edition'], jsondata['author'], type(jsondata))
=> 01 Java third Herbert Schildt <class 'dict'>
json.dumps() 함수로 파이썬 사전 데이터를 JSON 문자열 데이터로 변환할 수 있음
import json
# 변수에 문자열로 된 JSON 포멧의 데이터가 있을 경우
data = { "id":"01", "language": {"Java":"basic", "Java":"advance"}, "edition": "third", "author": "Herbert Schildt" }
jsondata = json.dumps(data)
print (jsondata, type(jsondata))
jsondata = json.dumps(data, indent=2) # 들여쓰기
print (jsondata, type(jsondata))
=>
{"id": "01", "language": {"Java": "advance"}, "edition": "third", "author": "Herbert Schildt"} <class 'str'>
{
"id": "01",
"language": {
"Java": "advance"
},
"edition": "third",
"author": "Herbert Schildt"
} <class 'str'>
csv파일의 key 값: 가장 위 쪽 목록
→ 이것을 key와 value로 만든 것
json.load() 함수로 파일로된 json 데이터를 사전처럼 다룰 수 있음
- JSON 파일 예: 유투브 카테고리 (미국)
{
"kind": "youtube#videoCategoryListResponse",
"etag": "\\"m2yskBQFythfE4irbTIeOgYYfBU/S730Ilt-Fi-emsQJvJAAShlR6hM\\"",
"items": [
{
"kind": "youtube#videoCategory",
"etag": "\\"m2yskBQFythfE4irbTIeOgYYfBU/Xy1mB4_yLrHy_BmKmPBggty2mZQ\\"",
"id": "1",
"snippet": {
"channelId": "UCBR8-60-B28hp2BmDPdntcQ",
"title": "Film & Animation",
"assignable": true
}
},
{
"kind": "youtube#videoCategory",
"etag": "\\"m2yskBQFythfE4irbTIeOgYYfBU/UZ1oLIIz2dxIhO45ZTFR3a3NyTA\\"",
"id": "2",
"snippet": {
"channelId": "UCBR8-60-B28hp2BmDPdntcQ",
"title": "Autos & Vehicles",
"assignable": true
}
}
]
}
이렇게 데이터를 파싱해서 원하는 데이터를 얻어내야 한다.
items에서 kind, snippet, title을 불러오겠다.
import json
with open('US_category_id.json', 'r', encoding='utf-8-sig') as json_file:
json_data = json.load(json_file)
for item in json_data['items']:
print (item['kind'], item['snippet']['title'])
=>
youtube#videoCategory Film & Animation
youtube#videoCategory Autos & Vehicles
youtube#videoCategory Music
youtube#videoCategory Pets & Animals
youtube#videoCategory Sports
youtube#videoCategory Short Movies
youtube#videoCategory Travel & Events
youtube#videoCategory Gaming
youtube#videoCategory Videoblogging
youtube#videoCategory People & Blogs
youtube#videoCategory Comedy
youtube#videoCategory Entertainment
youtube#videoCategory News & Politics
youtube#videoCategory Howto & Style
youtube#videoCategory Education
youtube#videoCategory Science & Technology
youtube#videoCategory Nonprofits & Activism
youtube#videoCategory Movies
youtube#videoCategory Anime/Animation
youtube#videoCategory Action/Adventure
youtube#videoCategory Classics
youtube#videoCategory Comedy
youtube#videoCategory Documentary
youtube#videoCategory Drama
youtube#videoCategory Family
youtube#videoCategory Foreign
youtube#videoCategory Horror
youtube#videoCategory Sci-Fi/Fantasy
youtube#videoCategory Thriller
youtube#videoCategory Shorts
youtube#videoCategory Shows
youtube#videoCategory Trailers
빅데이터에서 자연어 처리 등의 대규모가 아닌 경우
로컬에서 CPU로 돌릴 수 있는 아나콘다와 주피터노트북을 활용하는 것이 좋다.
→ 로컬 환경에 있는 쥬피터노트북과 아나콘다를 사용하는 것이 좋다.
코랩: 구글에서 대규모 라이브러리를 설치해 두었다.
→ 자연스럽게 환경에 적응되어 있다.
2007년도 인터넷 연결 커넥션이 만들어졌다.
기본적인 표현, 데이터 처리 등을 강의
기본적인 데이터 입출력
PyQt로 미니 프로젝트 진행
1년차: 풀타임 강사
작년부터는 어려운 과목들을 받게 되었다.
기초 과목을 탄탄하게 다진 다음, 어려운 쪽으로 들어가게 되면
컨텐츠와 코드를 보고 어떻게 쓸 것인지 큰 그림을 보고 가야 한다.
나중에는 큰 그림만 그리고 코드를 쓸 줄 알면 된다.
CPU는 써도 기본적으로 메모리가 8기가 이상이다.
CPU와 메모리 쪽에서 누수없이 사용할 수 있다.
외국 쪽 엔지니어는 한 분야만 하기에 최적화 코드를 만들어낸다.
→ 깊이가 다르다.
애플 같은 경우, 상당히 견고하다.
한국 엔지니어가 만들면,
디버그 문제 발생 시, 어디가 문제인지 발견하지 못하는 경우가 많다.
→ 나의 수준을 100에서 4~60까지는 올려야 한다.
→ 어떻게 사용할 것인지는 나의 역량에 따라 다르다.
- 요구가 많으면, 공부할 수 밖에 없다.
파이썬이 강력한 이유
: 직관적이다, 자료를 떄려넣어도 통한다, 문자 숫자 정수 다 넣어도 다 인식할 수 있다.
ITK라는 라이브러리가 있다.
(Insight Toolkit)
컴퓨터 비전: 컴퓨터로 영상처리 하는 것
ITK: 의료영상을 처리하는 라이브러리
→ 파이썬이 들어온 뒤, 컴파일링 할 필요없이 바로 쓸 수 있게 되었다.
빅데이터를 가져올 때, 공공데이터센터(전국에 있는 지자체별)
→ 사람들이 한땀한땀 모은 것
내가 원하는 데이터를 내가 만들고 싶다면, 인터넷에서 사진이나 기사를 긁어와야 한다.
→ 크롤링 (특정 문서에서 원하는 데이터를 코드로 가져와서, 엑셀 파일 등으로 정리할 수 있다.)
용어를 잘 설명해야 한다.
re.sub('\\[0-9]+\\]','',item.get_text()))
→ 이 코드에 대해 쓸 수 있는 표현들을 알고 있으면 쉽게 일하고 집에 갈 수 있다.
정규표현식
age: 나이
Parch: 부모님와 아이
Embarked: 정차, 내리는가
빅데이터 처리를 할 때
어려운 점
: 해당 도메인에 대한 이해가 없으면 절대 접근할 수 없다.
금융, 보험, 의료 데이터 등에 대한 지식이 없으면 접근할 수 없다.
→ 어떻게 도메인을 이해할 것인가? (가장 어려운 부분)
빅데이터: 정량적을 보여주는 것도 있지만, 정성적으로 설득하기 위한 도구일 뿐이다.
→ 나만의 스토리텔링을 만들어서 다른 사람에게 설명할 수 있어야 한다.
가장 스토리를 잘 만든 사람에게 과제를 넘겨준다.
→ 이 스토리텔링을 하기 위해선, 내가 중심이 되어서 어떻게 이야기를 꾸며 나갈 것인가에 대한 생각이 있어야 한다.
- 기승전결로 매끄럽게 이어나가면 좋다.
- 중간에 뭔가 막히면 out이다.
스토리텔링을 잘 만들어나가면서 도메인을 이해해 나가면 된다.
import openpyxl
import re
regex = re.compile(' [A-Za-z]+\\.')
# 엑셀파일 열기
work_book = openpyxl.load_workbook('train.xlsx')
# 현재 Active Sheet 얻기
work_sheet = work_book.active
# work_sheet.rows는 해당 쉬트의 모든 행을 객체로 가지고 있음
for each_row in work_sheet.rows:
print (each_row[3].value)
print (regex.findall(each_row[3].value))
if len(regex.findall(each_row[3].value)) > 0:
if regex.findall(each_row[3].value)[0].strip() == "Mr.":
print ("남성")
work_book.close()
예제: 왜 정규표현식이 필요할까?
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
res = urlopen('<https://davelee-fun.github.io/blog/crawl_test_css.html>')
soup = BeautifulSoup(res, "html.parser")
data = soup.select('ul#dev_course_list li.course')
for item in data:
print (item.get_text())
(초급) - 강사가 실제 사용하는 자동 프로그램 소개 [2]
(초급) - 필요한 프로그램 설치 시연 [5]
(초급) - 데이터를 엑셀 파일로 만들기 [9]
(초급) - 엑셀 파일 이쁘게! 이쁘게! [8]
(초급) - 나대신 주기적으로 파이썬 프로그램 실행하기 [7]
(초급) - 파이썬으로 슬랙(slack) 메신저에 글쓰기 [40]
(초급) - 웹사이트 변경사항 주기적으로 체크해서, 메신저로 알람주기 [12]
(초급) - 네이버 API 사용해서, 블로그에 글쓰기 [42]
(중급) - 자동으로 쿠팡파트너스 API 로 가져온 상품 정보, 네이버 블로그/트위터에 홍보하기 [412]
바퀴를 새로 만들 필요가 없다.
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
res = urlopen('<https://davelee-fun.github.io/blog/crawl_test_css.html>')
soup = BeautifulSoup(res, "html.parser")
data = soup.select('ul#dev_course_list li.course')
for item in data:
print (re.sub('\\[[0-9]+\\]', '', item.get_text()) )
(초급) - 강사가 실제 사용하는 자동 프로그램 소개
(초급) - 필요한 프로그램 설치 시연
(초급) - 데이터를 엑셀 파일로 만들기
(초급) - 엑셀 파일 이쁘게! 이쁘게!
(초급) - 나대신 주기적으로 파이썬 프로그램 실행하기
(초급) - 파이썬으로 슬랙(slack) 메신저에 글쓰기
(초급) - 웹사이트 변경사항 주기적으로 체크해서, 메신저로 알람주기
(초급) - 네이버 API 사용해서, 블로그에 글쓰기
(중급) - 자동으로 쿠팡파트너스 API 로 가져온 상품 정보, 네이버 블로그/트위터에 홍보하기
정규표현식
프로그래밍 연습(생각만 해보기)
다음 코드를 실행해보고, 이름 정보를 통해 남자인지, 여자인지, 기타인지(남녀 구별 불가)를 확인할 수 있는 방법 생각해보기
세 라인의 코드를 추가하면 이름의 특징을 추출할 수 있음
import re
regex = re.compile('[A-Za-z]+\\.')
print ( regex.findall('찾을 문자열') )
pip install openpyxl
import openpyxl
import re
regex = re.compile(' [A-Za-z]+\\.')
# 엑셀파일 열기
work_book = openpyxl.load_workbook('train.xlsx')
# 현재 Active Sheet 얻기
work_sheet = work_book.active
# work_sheet.rows는 해당 쉬트의 모든 행을 객체로 가지고 있음
for each_row in work_sheet.rows:
print (each_row[3].value)
print (regex.findall(each_row[3].value))
work_book.close()
이름 데이터만 보고 성별관련 정보 알아내기
import openpyxl
import re
regex = re.compile(' [A-Za-z]+\\.')
# 엑셀파일 열기
work_book = openpyxl.load_workbook('train.xlsx')
# 현재 Active Sheet 얻기
work_sheet = work_book.active
# work_sheet.rows는 해당 쉬트의 모든 행을 객체로 가지고 있음
for each_row in work_sheet.rows:
print (each_row[3].value)
print (regex.findall(each_row[3].value))
if len(regex.findall(each_row[3].value)) > 0:
if regex.findall(each_row[3].value)[0].strip() == "Mr.":
print ("남성")
work_book.close()
' [A-Za-z]+.' --> regular expression 이라고 함
- 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식
예: 문자, 숫자가 아닌 데이터를 찾아서, '' 로 대체해라(삭제해라)
import re
string = "(Dave)"
re.sub('[^A-Za-z0-9]', '', string) # 문자, 숫자가 아닌 데이터를 찾아서, '' 로 대체해라(삭제해라)
string.replace("(", '').replace(")", '')
정규식에 대한 규칙을 알면 해당 내용들을 규칙별로 찾아낼 수 있다.
위 정규 표현식은 일정한 규칙을 가지고 작성됨, 필요한 패턴은 직접 만들 수도 있음
1. Dot .
- Dot . 메타 문자는 줄바꿈 문자인 \n를 제외한 모든 문자(한 개)를 의미함
- 예: D.A 는 D + 모든 문자(한 개) + A 를 의미
- DAA, DvA, D1A
# 정규 표현식 라이브러리 임포트하기
import re
# 정규 표현식 패턴 만들기
pattern = re.compile('D.A')
# 패턴에 매칭되는지 여부 확인하기 (실습)
pattern.search("DAA")
pattern.search("D1A")
pattern.search("D00A")
pattern.search("DA")
pattern.search("d0A")
pattern.search("d0A D1A 0111")
정말 Dot . 이 들어간 패턴을 찾으려면?
\\. 으로 표시하거나, [.] 으로 표시하면 됨
pattern = re.compile('D\\.A')
pattern.search("D.A")
pattern.search("DDA")
pattern = re.compile('D[.]A')
찾고 바꾸기 (특정 패턴이 매칭되는 것을 찾아서, 다른 문자열로 바꾸기)
string = "DDA D1A DDA DA"
# re.sub(패턴, 바꿀데이터, 원본데이터)
re.sub('D.A', 'Dave', string) # 문자, 숫자가 아닌 데이터를 찾아서, '' 로 대체해라(삭제해라)
2. 반복 ? , * , +
- ? 는 앞 문자가 0번 또는 1번 표시되는 패턴 (없어도 되고, 한번 있어도 되는 패턴)
- 는 앞 문자가 0번 또는 그 이상 반복되는 패턴
-
- 는 앞 문자가 1번 또는 그 이상 반복되는 패턴
# ?사용 예
pattern = re.compile('D?A') # 앞에 문자 D가 없거나, 여러번 반복되고 마지막이 A 인 문자열
pattern.search("A")
=> <re.Match object; span=(0, 1), match='A'>
pattern.search("DA")
=> <re.Match object; span=(0, 2), match='DA'>
pattern.search("DDDDDDA")
=> <re.Match object; span=(5, 7), match='DA'>
# *사용 예
pattern = re.compile('D*A') # 앞에 문자 D가 없거나, 여러번 반복되고 마지막이 A 인 문자열
pattern.search("A")
=> <re.Match object; span=(0, 1), match='A'>
pattern.search("DA")
=> <re.Match object; span=(0, 2), match='DA'>
pattern.search("DDDDDDDDDDDDDDDDDDDDDDDDDDDDA")
=> <re.Match object; span=(0, 29), match='DDDDDDDDDDDDDDDDDDDDDDDDDDDDA'>
pattern = re.compile('AD*A') # 앞에 문자 D가 없거나, 여러번 반복되고 마지막이 A 인 문자열
pattern.search("ADA")
=> <re.Match object; span=(0, 3), match='ADA'>
pattern.search("ADDDDDDDDDDDDDDDDDDA")
=> <re.Match object; span=(0, 20), match='ADDDDDDDDDDDDDDDDDDA'>
또다른 반복 표현: {n}, {m,n}
- {n} : 앞 문자가 n 번 반복되는 패턴
- {m, n} : 앞 문자가 m 번 반복되는 패턴부터 n 번 반복되는 패턴까지
# {n} 사용 예
pattern = re.compile('AD{2}A')
pattern.search("ADA")
pattern.search("ADDA")
=> <re.Match object; span=(0, 4), match='ADDA'>
pattern.search("ADDDA")
# {m,n} 사용 예
pattern = re.compile('AD{2,6}A') # {m,n} 은 붙여 써야 함 {m, n} 으로 쓰면 안됨(특이함)
pattern.search("ADDA")
=> <re.Match object; span=(0, 4), match='ADDA'>
pattern.search("ADDDA")
=> <re.Match object; span=(0, 5), match='ADDDA'>
pattern.search("ADDDDDDA")
=> <re.Match object; span=(0, 8), match='ADDDDDDA'>
3. 괄호 : 괄호 안에 들어가는 문자가 들어 있는 패턴
- 예: [abc] 는 a, b, c 중 하나가 들어 있는 패턴을 말함
pattern = re.compile('[abcdefgABCDEFG]')
pattern.search("a1234")
=> <re.Match object; span=(0, 1), match='a'>
pattern.search("z1234")
하이픈(-)을 이용하면 알파벳 전체를 나타낼 수 있음
- 예: [a-c] 는 a, b, c 중 하나가 들어 있는 패턴을 말함
pattern = re.compile('[a-z]')
pattern.search("k1234")
=> <re.Match object; span=(0, 1), match='k'>
pattern.search("Z1234")
=> <re.Match object; span=(0, 1), match='Z'>
[a-zA-Z] 으로 표기하면 대소문자를 모두 포함해서 알파벳 전체를 나타낼 수 있음
pattern = re.compile('[a-zA-Z]')
pattern.search("Z1234")
=> <re.Match object; span=(0, 1), match='Z'>
[a-zA-Z0-9] 로 표기하면 대소문자를 모두 포함해서 알파벳 전체와 함께 숫자 전체도 나타낼 수 있음
pattern = re.compile('[a-zA-Z0-9]')
pattern.search("1234---")
=> <re.Match object; span=(0, 1), match='1'>
pattern.search("---------------!@#!@$!$%#%%%#%%@$!$!---")
괄호 안에서 [ 바로 뒤에 ^ 을 쓰면 그 뒤에 오는 문자가 아닌 패턴을 찾음
- 문자를 결국 알파벳, 숫자, 특수문자, whitespace(스페이스, 탭, 엔터등) 로 분류할 수 있으므로
- [^ \t\n\r\f\v] 는 이중에서 whitespace 가 아닌 알파벳, 숫자, 특수문자를 지칭함
pattern = re.compile('[^a-zA-Z0-9]')
pattern.search("---------------!@#!@$!$%#%%%#%%@$!$!---")
=> <re.Match object; span=(0, 1), match='-'>
pattern = re.compile('[^ \\t\\n\\r\\f\\v]')
pattern.search("-")
=> <re.Match object; span=(0, 1), match='-'>
pattern.search(" ")
그러면 한글만? --> [가-힣]
pattern = re.compile('[가-힣]')
pattern.search("안")
=> <re.Match object; span=(0, 1), match='안'>
4. 조합해서 써보자
import re
pattern = re.compile('[a-zA-Z]+')
matched = pattern.search("Dave")
print(matched)
=> <re.Match object; span=(0, 4), match='Dave'>
5. 정규 표현식 라이브러리 함수 사용법
match 와 search 함수
- match : 문자열 처음부터 정규식과 매칭되는 패턴을 찾아서 리턴
- search : 문자열 전체를 검색해서 정규식과 매칭되는 패턴을 찾아서 리턴
import re
pattern = re.compile('^[a-z]+')
matched = pattern.match('Dave')
searched = pattern.search("Dave")
print (matched)
=> None
print(searched)
=> <re.Match object; span=(1, 4), match='ave'>
findall 함수: 정규표현식과 매칭되는 모든 문자열을 리스트 객체로 리턴함
import re
pattern = re.compile('[a-z]+')
findalled = pattern.findall('Game of Life in Python')
print (findalled)
=> ['ame', 'of', 'ife', 'in', 'ython']
pattern2 = re.compile('[A-Za-z]+')
findalled2 = pattern2.findall('Game of Life in Python')
print (findalled2)
=> ['Game', 'of', 'Life', 'in', 'Python']
findall 함수를 사용해서 정규표현식에 해당되는 문자열이 있는지 없는지 확인하기
import re
pattern = re.compile('[a-z]+')
findalled = pattern.findall('GAME')
if len(findalled) > 0:
print ("정규표현식에 맞는 문자열이 존재함")
else:
print ("정규표현식에 맞는 문자열이 존재하지 않음")
=> 정규표현식에 맞는 문자열이 존재하지 않음
→
import re
pattern = re.compile('[a-z]+')
findalled = pattern.findall('game')
if len(findalled) > 0:
print ("정규표현식에 맞는 문자열이 존재함")
else:
print ("정규표현식에 맞는 문자열이 존재하지 않음")
=> 정규표현식에 맞는 문자열이 존재함
- 대문자는 존재 X, 소문자 존재 O
split 함수: 찾은 정규표현식 패턴 문자열을 기준으로 문자열을 분리
(분리(분류)해준다.)
import re
pattern2 = re.compile(':')
splited = pattern2.split('python:java')
print (splited)
=> ['python', 'java']
콜론에 맞춰서 Python 과 Java가 분리되며, 리스트 형식으로 반환해준다.
프로그래밍 연습
' VS ' 로 문자열 앞뒤를 분리해보기
A부터 Z까지 숫자가 반복되며 반환하는코드
import re
pattern2 = re.compile(' [A-Z]{2} ')
splited = pattern2.split('python VS java')
print (splited)
=> ['python', 'java']
- ‘VS’가 소문자가 아닌, 대문자로 걸려야 작동한다.
sub 함수: 찾은 정규표현식 패턴 문자열을 다른 문자열로 변경
(특정 문자열이 나오면, 어떠한 것으로 바꿔준다)
import re
pattern2 = re.compile('-')
subed = pattern2.sub('*', '801210-1011323') # sub(바꿀문자열, 본래문자열)
print (subed)
=> 801210*1011323
subed = re.sub('-', '*', '801210-1011323') # sub(정규표현식, 바꿀문자열, 본래문자열)
print (subed)
=>801210*1011323
- 어떤 표현을 쓰는지에 대해 이해하고 있어야 한다.
주민등록번호 뒷자리를 일괄적으로 다른 형태로 표시하는 것을 해보자.
도전 과제
주민번호 뒷자리를 * 로 바꿔서 가려보기
re.sub('-------', '------', each_row[1].value) <--- 정규표현식, 바꿀문자열 을 넣어봅니다.
import openpyxl
work_book = openpyxl.load_workbook('data_kr.xlsx')
work_sheet = work_book.active
for each_row in work_sheet.rows:
print(re.sub('-[0-9]{7}', '-*******', each_row[1].value))
work_book.close()
=>
주민등록번호
800215-*******
821030-*******
841230-*******
790903-*******
800125-*******
820612-*******
→ ‘*’로 일괄 처리에 대한 코드
# 핵심 코드
for each_row in work_sheet.rows:
print(re.sub('-[0-9]{7}', '-*******', each_row[1].value))
응용 과제: 뒷 번호 1자리만 남겨두고 나머지는 변환
import openpyxl
work_book = openpyxl.load_workbook('data_kr.xlsx')
work_sheet = work_book.active
for each_row in work_sheet.rows:
print(re.sub('-[0-9]{7}', '-*******', each_row[1].value))
work_book.close()
=>
주민등록번호
800215-*******
821030-*******
841230-*******
790903-*******
800125-*******
820612-*******
import openpyxl
work_book = openpyxl.load_workbook('data_kr.xlsx')
work_sheet = work_book.active
for each_row in work_sheet.rows:
print(re.sub('[^가-힣].....$', '******', each_row[1].value))
work_book.close()
=>
주민등록번호
800215-2******
821030-1******
841230-2******
790903-1******
800125-1******
820612-2******
PyQt: GUI도 같이 사용할 수 있게 되었다.
→ 파이썬의 약점 보완
머신러닝을 배우게 되면, 함수들을 어떻게 사용할 것인가에 대한 정의를 잘 정리해둬야 한다.
(너무 얕지도, 깊지도 않게 사용해야 한다.)
오캄스 레이저
: 모든 조건이 동등했을 때, 단순한 게 정답이다.
→ 아무리 어려운 문제를 만나더라도, 단순하게 생각하자.
다차원 공간
- 머신러닝과 인공지능은 다차원 공간으로 확장된다.
일상적인 생활에 냄새가 들어가면 4차원
소리가 들어가면 5차원
내가 만약에 그랬었더라면
→ 내가 요리사가 되는 길이 있고, 중국인 요리사가 되는 길이 있고, 경영할 수 있는 길이 있었다.
(다차원 공간에서 사랑이라는 결론을 내린다.)
in my time: 인공지능도 다차원 공간에서 차원을 축소하고 오캄스 레이저로 가장 간단한 답이 나오면, 그것이 정답이다.
- 세상의 모든 원리는 비슷하다.
퀀텀 컴퓨터: 빛의 입자속도로 계산해준다.
→ 단순하게 문제를 풀어내자.
문자열 관련 함수 알아보기
문자열에 있는 특정 문자 갯수 세기 (count 함수)
data = 'Dave David'
data.count('v') # 문자열에 D 가 몇 번 나올까요? 대소문자도 구별함
문자열에 있는 특정 문자의 위치 알려주기
index 함수
string = 'Dave ID is dave'
string.index('i') # 맨 앞 자리부터 0, 1, ... 순으로 위치를 표시
=> 8
해당 문자가 문자열에 없을 때, 에러를 안낼 수는 없을까? --> find 함수를 사용하면 됨
- find 함수는 해당 문자가 문자열에 없으면 -1 을 리턴함 (에러는 내지 않음)
- 이외에는 index 함수와 동일
string = 'dave is david'
string.find('x')
string = 'Dave ID is dave'
string.find('D ') # 맨 앞 자리부터 0, 1, ... 순으로 위치를 표시
if string.find('x') == -1:
print ("x는 스트링에 없습니다.")
=> x는 스트링에 없습니다.
문자열 사이에 다른 문자 넣기
string = "12345"
comma = ','
comma.join(string) # 껴넣을 문자.join(문자열)
=> '1,2,3,4,5'
문자열 앞뒤에 공백 지우기
- 실제 현실 세계에 있는 문자열 데이터를 정리하다보면, 문자열 앞뒤에 공백 또는 기호가 있는 경우가 많음
strip( )함수: 지워주다, 제거하다.
data = " Dave "
data.strip() # 앞 뒤 공백을 다 지움
=> 'Dave'
string2 = " David "
string2.strip() # 앞 뒤 공백이 여러개 있어도 한번에 다 지움
=> 'David'
string2.lstrip() # 앞쪽(문자열 왼쪽)만 지우기 left strip 의 약자
=> 'David '
string2.rstrip() # 앞쪽(문자열 오른쪽)만 지우기 right strip 의 약자
=> ' David'
string = " 9999999999999999(Dave)888888888888888888 "
string.strip(" 98()") # 앞 뒤 괄호를 다 지움
=> 'Dave'
- 퍼테이션마크: 문자열을 지정하는 ‘ ‘를 의미
영문자 대소문자로 변환하기¶
- 대소문자를 구별하기 때문에, 대소문자 구별하지 않고 처리를 하기 위해 임의로 대문자 또는 소문자로 다 바꿀 때가 있음
소문자를 대문자로 바꾸기
string = 'Dave'
string.upper() # 본래 대문자는 놔두고, 소문자인 문자만 대문자로 변경
=> 'DAVE'
대문자를 소문자로 바꾸기
string = 'Dave'
string.lower() # 본래 소문자는 놔두고, 대문자인 문자만 대문자로 변경
=> 'dave'
문자열을 나누기
string = "Dave goes to Korea"
string.split() # split() 인자를 넣지 않으면 디폴트로 스페이스를 기준으로 분리
=> ['Dave', 'goes', 'to', 'Korea']
string = "Dave goes to Korea"
string.split()[3]
=> 'korea'
string.split(' ') # 명시적으로 스페이스를 기준으로 분리하겠다고 넣어줘도 됨
=> ['Dave', 'goes', 'to', 'Korea']
string = "Dave/goes/to/Korea"
string.split('/') # split() 인자를 넣으면 해당 인자를 기준으로 분리
=> ['Dave', 'goes', 'to', 'Korea']
프로그래밍 연습
string = "10,11,22,33,44" 를 컴마(,) 로 분리해서 리스트 변수를 만들어 각 값을 정수형 리스트 데이터로 넣기
int('11') 을 실행하면 숫자 11로 변환
string = "10,11,22,33,44"
string.split(',')
=> ['10', '11', '22', '33', '44']
string = "10,11,22,33,44"
listdata = string.split(',')
for index, listitem in enumerate(listdata):
listdata[index] = int(listitem)
print (listdata)
=> [10, 11, 22, 33, 44]
string = "10,11,22,33,44"
split_string = string.split(',')
for index, split_item in enumerate(split_string):
split_string[index] = int(split_item)
print (split_string)
=> [10, 11, 22, 33, 44]
문자열 중 일부를 다른 문자로 바꾸거나, 삭제하기
string = "David goes to Korea"
string.replace("David", "Dave") # David 를 Dave 로 바꾸기
=> 'Dave goes to Korea'
string2 = "(Dave)"
string2.replace("()", "") # 연결된 문자열은 해당 문자열이 동일하게 매칭이 되어야 함
=> '(Dave)'
string2.replace("(", "")
=> 'Dave)'
string2.replace(")", "")
=> '(Dave'
string2 = string2.replace("(", "") # ( 가 삭제된 문자열로 변수 값을 덮어 씌운 후에 다시 ) 를 삭제하면 됨
string2.replace(")", "")
=> 'Dave'
string2 = "(Dave)"
string2.replace("(", "").replace(")", "")
=> 'Dave'
프로그래밍 연습
string = "10,11,22,33,44" 에서 컴마(,) 를 / 으로 대체하기
string = "10,11,22,33,44"
string.replace(",", " ")
=> '10 11 22 33 44'=
- xml파일: HTML에서 시작과 끝을 알려주는 태그형식
→ 과거 정부에서는 csv파일보단, xml파일형식이 더 많았다.
- json파일: 딕셔너리 형식으로 제공되는 형식
특정 데이터 포맷을 사용하지 않는, 일반적인 텍스트를 Plain Text라고 한다.
1. 다양한 데이터 포멧 이해하기: Plain Text
- Plain Text: 특정 데이터 포멧을 사용하지 않는, 일반적인 텍스트를 의미함
- 주요 데이터 포멧
- csv, xml, json
- 참고: https://www.data.go.kr/search/index.do
통상적으로 데이터 처리에서 다루는 Plain Text 보다는 특정 데이터 포멧을 사용하는 경우가 많음
1.1 파일 오픈 (Plain Text)
- 프로그래밍에서 파일은 다음과 같은 3가지 명령의 순서로 처리할 수 있음
- 파일 오픈
- 파일 읽기 또는 쓰기
- 파일 닫기
- 파일디스크립터변수 = open(파일이름, 파일열기모드)
data_file = open('00_data/text_data.txt', 'r', encoding='utf-8-sig')
- 파일 디스크립터 (file descriptor) 변수: 오픈한 파일 객체를 가리키고 있는 변수
- 파일 이름 명시시, open 함수 실행 위치와 파일 이름이 저장된 위치를 파일 절대 경로 또는 상대 경로로 정확히 명시해야 함
- 파일 열기 모드
파일열기모드 설명
r | 읽기 모드: 파일을 읽기만 할 때 사용함 |
w | 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) |
a | 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함 |
컴퓨터를 끄지 않고 사용할 경우, 컴퓨터가 느려진다.
→ 메모리에 있는 명령어를 처리하는데 시간이 오래 걸린다.
(자잘한 문서들이 많이 쌓이면
Java: 객체 지향형 언어로, 객체들이 붕어빵 찍듯이 만들어낼 수 있다.
(단일 상속), 상속을 1번만 해준다.
인터페이스 상속이라고 어떻게 상속하는지
정기적으로 자기가 만들어낸 객체를 지워주는 가비지클리닝 기능이 들어있다.
시스템을 관리하는 측에서 컴퓨터를 매번 껏다 킬 필요가 없다.
→ 항상 최적의 상태를 유지할 수 있다.
필요없는 파일은 닫아두는 습관을 길들일 필요가 있다.
encoding: 아스키 코드를 표준규약에 맞춰 화면에 주는 하나의 규약
- 인코더와 디코더
인코더: 암호를 만든다.
디코더: 암호를 푼다.
딥러닝의 오토 인코더: 자동으로 인코딩을 해준다.
- 인코딩: 압축한다.
- 딥러닝의 비지도학습: 오토인코더
(데이터가 많이 없을 때 사용하는 방식)
공장을 돌릴 때, 비정상 데이터가 더 적다.
정상 데이터와 비정상 데이터의 수를 맞춰야 하므로 오토인코딩을 통해 가공으로 비정상 데이터를 만들어준다.
- 자연어 처리에서 핫한 트랜스포머
: 인코더와 디코더 부분을 따로 해준 것
인코더: 자연어 처리를 할 수 있는 바트
디코더: GPT
⇒ 트랜스포머
트랜스포머와 자연어 처리는 책이 없고, 논문밖에 없다.
→ 공부하고 싶어도 어렵다.
참고: 인코딩과 utf-8 과 utf-8-sig
인코딩이란?
utf-8 과 utf-8-sig
- 기존에는 영어 인코딩, 한국어 인코딩 방식이 달랐음. 이에 따라 각 국가에서 작성된 파일을 읽을 수 없는 경우가 발생
- 모든 언어를 지원하는 인코딩 방식을 통해 다른 언어 지원, 이를 유니코드 라고 함
- 각 인코딩 방식마다 이름이 존재 하며, 유니코드는 utf-8 이라는 이름을 사용함
- 각 인코딩 방식에 맞게, 데이터를 저장하고, 데이터를 읽을 때에는 해당 인코딩 방식을 명시해주어, 데이터를 알맞게 읽을 수 있음
- utf 방식도 세부적으로는 utf-8, utf-16, utf-32 등 다양한 방식이 있으며, 이를 구별하기 위해, 윈도우의 텍스트 편집기들은 데이터 저장시 앞부분에 특정 기호(signature)를 추가함
- 해당 기호(signature)를 Byte Order Mark(BOM) 이라고 부름
- 문제는 해당 기호(signature)를 맥 또는 리눅스등 다른 운영체제 환경에서는 지원하지 않아서 잘못 인식할 수 있음
- 근본적으로 윈도우를 개발한 MS사가 표준과 다른, 자기만의 signature를 넣는 방식을 썼다는 것이 문제임
- 그래서, 데이터 오픈시, BOM이 있다면, BOM 빼고, 데이터를 읽을 수 있도록 하여, 호환성 문제를 해결하는 방식이 utf-8-sig 임
- 파일 데이터 오픈시, 인코딩에 문제가 있어 보일 경우, 또는 기본적으로 encoding='utf-8-sig' 를 사용하면 큰 문제가 없음
참고: 파일 절대 경로와 상대 경로
- 절대 경로
- 최초의 시작점으로 경유한 경로를 전부 기입하는 방식
- 윈도우 예: 드라이브명부터 시작, C:\ 등
- C:\\Users\\UserID\\Desktop\\test.txt
- 맥 예: 최상단 디렉토리를 나타내는 / 부터 시작
- 맥: /Users/tae/test.txt
- 상대 경로
- 파일을 찾는 위치부터 상대적인 경로를 기입하는 방식
- 예
- 현재 폴더가 /Users/tae/code 인 상태에서 동일 폴더에 있는 testfile.txt 를 찾는 경우
- testfile.txt
- 현재 폴더가 /Users/tae/code 인 상태에서 하위 폴더인 /Users/tae/code/data 폴더에 있는 testfile.txt 를 찾는 경우
- 현재 폴더 안에 있는 폴더를 하위 폴더라고 함
- 하위 폴더명/파일명 과 같은 형태로 상대 경로를 작성하면 됨
data/testfile.txt
- 현재 폴더가 /Users/tae/code 인 상태에서 상위 폴더인 /Users/tae/ 폴더에 있는 testfile.txt 를 찾는 경우
- 현재 폴더를 포함하고 있는 상위에 있는 폴더를 상위 폴더라고 함
- 상위 폴더는 ../ 로 명시할 수 있음
../testfile.txt
리눅스와 윈도우 중, 리눅스 일처리가 더 빠르다.
리눅스는 30분에 설치가 다 된다.
쉽게 쉽게 컴퓨팅 환경 구성이 될 수 있다.
- 개발 환경 맞추는 것도 어렵다.
버전이 다를 경우, 맞춰야 한다.
→ 어떻게 환경을 꾸릴 것인가?
연습문제
- 다음 상황에서 파일 절대 경로와 상대 경로 작성하기
- 현재 폴더: /Users/tae/code
- 파일 위치: /Users/
- 파일 명: testfile.txt
- data/testfile.txt
- 상대 경로: ../../testfile.txt
- 다음 상황에서 파일 절대 경로와 상대 경로 작성하기
- 현재 폴더: /Users/tae/code
- 파일 위치: /Users/tae/code/program/data
- 파일 명: testfile.txt
- 파일디스크립터변수.close() 함수로 파일을 닫을 수 있음
- 항상 오픈한 파일은 닫아야 함 (파일을 오픈한 채로 놔두면, 컴퓨터에서 관련 자원을 계속 사용중인 상태가 될 수 있음)
data_file = open('text_data.txt', 'r', encoding='utf-8-sig') data_file.close()
- 자동으로 파일을 닫기 위해 with 구문을 사용활용할 수 있음
- with open() 명령 as 파일디스크립터:
- with 구문 안에서 동작할 코드를 탭으로 들여쓰기 해서 사용하면, with 구문이 모두 끝난 후, 자동으로 해당 파일을 닫아줌
1.3 파일 읽기with open('00_data/text_data.txt', 'r', encoding='utf-8-sig') as file_desc: print ('test') => test
- 오픈한 파일 디스크립터.readlines() 함수를 호출해서, 전체 데이터를 한줄씩 리스트타입으로 읽어올 수 있음
• 리스트 타입 변수는 항상 for 구문을 사용해서, 각 아이템을 가져오기readline() 함수 사용하기data_file = open('text_data.txt', 'r', encoding='utf-8-sig') data_lines = data_file.readlines() data_lines => ['안녕하세요. tae 입니다.\\n', '본 예제는 Plain Text 파일 예제입니다.\\n', '감사합니다.']
- 오픈한 파일 디스크립터.readline() 함수를 호출해서, 현재까지 읽은 파일 데이터의 다음 한 줄을 문자열 타입으로 읽을 수 있음
read() 함수 사용하기data_file = open('00_data/text_data.txt', 'r', encoding='utf-8-sig') data_line = data_file.readline() print (data_line) => 안녕하세요. tae 입니다. data_line = data_file.readline() print (data_line) => 본 예제는 Plain Text 파일 예제입니다. data_line = data_file.readline() print (data_line) => 감사합니다. data_file.close()
- 오픈한 파일 디스크립터.read() 함수를 호출해서, 전체 파일 데이터를 문자열 타입으로 읽을 수 있음
1.4 파일 쓰기data_file = open('00_data/text_data.txt', 'r', encoding='utf-8-sig') data = data_file.read() data => '안녕하세요. tae 입니다.\\n본 예제는 Plain Text 파일 예제입니다.\\n감사합니다.' data_file.close()
- open() 함수에 파일열기모드를 'w' 로 해서, 파일 쓰기
r 읽기 모드: 파일을 읽기만 할 때 사용함 w 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) a 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함 - open() 함수에 파일열기모드를 'a' 로 해서, 파일 쓰기
r 읽기 모드: 파일을 읽기만 할 때 사용함 w 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) a 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함
연습문제data_file = open('00_data/text_data_write.txt', 'a', encoding='utf-8-sig') data_file.write('본 파일은 임시 파일입니다.') data_file.close()
- 00_data/text_data_practice.txt 파일 만들고, 다음 내용 쓰기 (각 데이터별 라인을 바꿔주도록 저장)
- 00_data/text_data_practice.txt 파일에 다음 내용 추가하기
- 00_data/text_data_practice.txt 파일 읽고, 다음과 같이 출력되는지 확인하기
# Write to the text file with open('text_data_practice.txt', 'w') as file: file.write("유치원A\\n초등학교B\\n중학교C\\n고등학교D\\n") # Append to the text file with open('text_data_practice.txt', 'a') as file: file.write("대학교E\\n") # Read from the text file and print the content with open('text_data_practice.txt', 'r') as file: content = file.read() print(content) => 유치원A 초등학교B 중학교C 고등학교D 대학교E
2. 다양한 데이터 포멧 이해하기: CSV- 주요 데이터 포멧
- csv, xml, json, plain text
- 파일디스크립터변수 = open(파일이름, 파일열기모드)
data_file = open('00_data/USvideos.csv', 'r', encoding='utf-8-sig')
- 파일 디스크립터 (file descriptor) 변수: 오픈한 파일 객체를 가리키고 있는 변수
- 파일 이름 명시시, open 함수 실행 위치와 파일 이름이 저장된 위치를 파일 절대 경로 또는 상대 경로로 정확히 명시해야 함
- 파일 열기 모드
r 읽기 모드: 파일을 읽기만 할 때 사용함 w 쓰기 모드: 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨) a 추가 모드: 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함 - encoding
- open(파일이름, 파일열기모드, encoding='utf-8-sig') 와 같이 끝에 encoding 구문 추가 가능 (옵션)
- 파일 오픈시, 해당 파일의 인코딩 방식을 명시해주는 것임
- # text_data_practice.txt 파일을 만들고, # 각 데이터 별 라인을 바꿔주도록 내용 적기 # 유치원A, 초등학교B, 중학교C, 고등학교D data_file = open('text_data_practice.txt', 'w', encoding='utf-8-sig') data_file.write('유치원A\\n') data_file.write('초등학교B\\n') data_file.write('중학교C\\n') data_file.write('고등학교D\\n') data_file.close() # 해당 파일에 '대학교E' 내용 추가하기 data_file = open('text_data_practice.txt', 'a', encoding='utf-8-sig') data_file.write('대학교E\\n') data_file.close() # 해당 파일을 읽고, 다음과 같이 출력되는지 확인하기 # 유치원A # 초등학교B # 중학교C # 고등학교D # 대학교E data_file = open('text_data_practice.txt', 'r', encoding='utf-8-sig') data = data_file.read() data => '유치원A\\n초등학교B\\n중학교C\\n고등학교D\\n대학교E\\n'
- 고등학교D
- 초등학교B
- 고등학교D
- 초등학교B
- data_file = open('text_data_write.txt', 'w', encoding='utf-8-sig') data_file.write('안녕하세요\\n') data_file.write('tae 입니다.\\n') data_file.close()
- data_file = open('text_data_write.txt', 'w', encoding='utf-8-sig') data_file.write('안녕하세요') data_file.write('tae 입니다.') data_file.close()
- write() 함수 사용하기
- for data_line in data_lines: print (data_line) data_file.close() => 안녕하세요. tae 입니다. 본 예제는 Plain Text 파일 예제입니다. 감사합니다.
- readlines() 함수 사용하기
- 상대 경로: program/data/testfile.txt
2.2. csv 파일 읽기
- CSV(Comma-Separated Values): 스프레드시트 데이터를 저장할 때 가장 널리 쓰이는 파일 형식
- 엑셀등 여러 응용프로그램에서도 지원
- CSV 형식 (각 열은 콤마로 구분, 각 행은 줄바꿈 문자로 구분)
- tae, taepark apple, 2 korea, japan, chian
- 파이썬에서 CSV 파일로 저장/읽기 방법
- csv 라이브러리 사용
csv 라이브러리
- anaconda 에 포함
- 만약 다음 코드 실행시 No module 에러 메세지가 나오면, csv 라이브러리 설치 후, 재실행
pip install csv
머신러닝을 배우게 되면 데이터가 tab 형식으로 나눠져 있다.
가장 많이 쓰이는 데이터 형식이 csv파일이다.
csv 파일을 join( 2개를 하나로 합쳐서)해서 사용하기도 한다.
시간별로 데이터를 분리해서 월 평균, 주 평균 등등을 만들어서
머신러닝과 딥러닝을 할 수 있는 하나의 피처로 만든다.
데이터에서 csv파일이 많은 이유가 뭘까?
xml파일에서 csv파일이 많아진 이유가 무엇일까?
ERP, CRM(고객 관계 관리), SCM(어떻게 물건을 공급해서 맞출 것인가?)
⇒ 이 3가지를 회사에선 SQL문으로 만든다.
모든 데이터들을 오라클에서 사용하는 SQL로 만든다.
기업체에서 만들어지는 데이터들은 csv파일로 만들어진다.
기업체에서는 각각의 테이블을 잘라두었다.
은행권에서 SQL을 사용한다고 하면,
2개의 테이블을 상관없는 것끼리 뭉친다.
→ SQL의 기본
csv파일에 대해서 SQL을 기본적으로 어떻게 다뤄야 하는지 알고 있어야 한다.
기업체에서 사용하는 모든 것들은 SQL로 만들어진다.
그래서, csv파일이 많을 수 밖에 없다.
import csv
- 분석 SQL을 배우는 것은 좋지만, 어렵다.
자연어 처리, 분석 SQL
→ 파이썬기반으로 처리할 수 있다.
csv.reader(오픈한 파일 디스크립터, delimiter=',')
- open 함수를 통해 오픈한 파일 디스크립터
- delimiter=데이터구분자: csv 파일 내에 데이터 구분자를 명시할 수 있음 (옵션)delimeter로 바꾸면 똑같은 csv 형식으로 불러올 수 있다.데이터 읽기
- 각 라인별 데이터를 읽기 위해, for 문을 사용하면 됨
- data_lines = csv.reader(data_file, delimiter=',') for data_line in data_lines: print (data_line)
- 대부분 ‘,’로 구분되어 있다.
- data_file = open('00_data/USvideos.csv', 'r', encoding='utf-8-sig') data_lines = csv.reader(data_file, delimiter=',')
파일 닫기 (close)
- 오픈한 파일은 반드시 닫아야 함, 닫지 않으면 파일이 오픈된 채로 남아있을 수 있음
data_file = open('00_data/USvideos.csv', 'r', encoding='utf-8-sig')
data_lines = csv.reader(data_file, delimiter=',')
for data_line in data_lines:
print (data_line)
data_file.close()
예 (한줄만 출력해봄)
import csv
data_file = open('USvideos.csv', 'r', encoding='utf-8-sig')
data_lines = csv.reader(data_file, delimiter=',')
for data_line in data_lines:
print (data_line)
break
data_file.close()
=> ['video_id', 'title', 'channel_title', 'category_id', 'tags', 'views', 'likes', 'dislikes', 'comment_total', 'thumbnail_link', 'date']
csv 파일 읽기 다른 기법
- with 문법을 사용해서, 파일 데이터를 읽은 후, with 내부 구문 실행 완료 후, 자동으로 파일을 닫을 수 있음
import csv
with open('00_data/USvideos.csv', 'r', encoding='utf-8-sig') as reader_csv:
reader = csv.reader(reader_csv, delimiter=',')
for row in reader:
print (row)
break
=> ['video_id', 'title', 'channel_title', 'category_id', 'tags', 'views', 'likes', 'dislikes', 'comment_total', 'thumbnail_link', 'date']
2.3 csv 파일 쓰기
- open 시 'w' 로 옵션을 설정
- open() 함수에 newline='' 를 넣어주는 이유는 윈도우의 경우에만 csv 모듈에서 데이타를 쓸 때 각 라인 뒤에 빈 라인이 추가되는 문제가 있기 때문
- 이를 없애기 위해 (파이썬 3 에서) 파일을 open 할 때 newline='' 와 같은 옵션을 지정
data_file = open('00_data/data.csv', 'w', encoding='utf-8-sig', newline='')
- csv.reader 대신, csv.writer 함수 사용
data_write = csv.writer(data_file, delimiter=',')
- writerow 함수에 리스트 형식으로 데이터를 넣으면, 한 라인씩 파일에 추가 됨
- 파일 close 는 파일 읽기와 동일함
import csv
data_file = open('tmp_csv.csv', 'w', encoding='utf-8-sig', newline='')
data_write = csv.writer(data_file, delimiter=',')
data_write.writerow(['1', '2', '3'])
data_file.close()
(pandas가 기본이다.)
csv 파일 쓰기 다른 기법 (with)
- with 문법을 사용해서, with 내부 구문 실행 완료 후, 자동으로 파일을 닫을 수 있음
쓰레기 데이터가 들어가면, 쓰레기가 나온다.
어떤 데이터는 평균이 0과 1사이이고 어떤 데이터는 평균이 100이면 outlyler라고 한다. 빈 데이터는 기존에 있던 평균값을 대체하는 식으로 빈 칸을 채워넣음을 통해 결과를 산출해야 한다.
데이터는 태국이나 방글라데시에서 만든다. (아웃소싱)
→ 데이터를 어떻게 사용하는가가 핵심이다.
import csv
with open('tmp_csv.csv', 'w', encoding='utf-8-sig', newline='') as writer_csv:
writer = csv.writer(writer_csv, delimiter=',')
writer.writerow(['love']*3 + ['banana']) # ['love', 'love', 'love', 'banana'] 와 동일
writer.writerow(['apple', 2]) # 문자열 외에도 다양한 타입 데이터 쓰기 가능
writer.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
csv 파일 쓰기 다른 기법 (사전 타입으로 파일 쓰기)
- csv.writer 함수 대신에, csv.DictWriter 함수 사용
- field 이름 선언 후, 데이터 넣기
import csv
with open('00_data/tmp_csv.csv', 'w', encoding='utf-8-sig', newline='') as writer_csv:
field_name_list =['First Name', 'Last Name'] # 필드명 정의
writer = csv.DictWriter(writer_csv, fieldnames=field_name_list) # 필드명을 미리 선언할 수 있음
writer.writeheader() # 보통 csv 파일 상단에는 필드명을 넣기 때문에, 선언된 필드명을 writerheader() 함수로 넣을 수 있음
writer.writerow({'First Name': 'tae', 'Last Name': 'park'}) # 각 데이터는 사전 타입으로 저장 가능
writer.writerow({'First Name': 'David', 'Last Name': 'Kim'})
writer.writerow({'First Name': 'Robin', 'Last Name': 'Park'})
• 사전 타입으로 읽기 가능
import csv
with open('tmp_csv.csv', 'r', encoding='utf-8-sig') as reader_csv:
reader = csv.DictReader(reader_csv)
for row in reader:
print(row['First Name'], row['Last Name'])
=>
tae park
David Kim
Robin Park
파이썬은 3총사를 데리고 있다.
- pandas, numpy (데이터 분석)
- matplib, seaborn (시각화)
3. 다양한 데이터 포멧 이해하기: XML
3.1. XML 포멧 이해하기
- XML(Extensible Markup Language)
- 특정 목적에 따라 데이터를 태그로 감싸서 마크업하는 범용적인 포멧
- 마크업 언어는 태그 등을 이용하여 데이터의 구조를 기술하는 언어의 한 가지
- 가장 친숙한 마크업 언어가 HTML
- XML은 HTML과 마찬가지로 데이터를 계층 구조로 표현
- XML 기본 구조
- <태그 속성="속성값">내용</태그>
- 태그와 속성은 특정 목적에 따라 임의로 이름을 정해서 사용
- <product id="M001" price="300000">32인치 LCD 모니터</product>
- 다른 요소와 그룹으로 묶을 수도 있음YAML (야물파일)서버를 일일히 100개를 구성해야 할 때,그래서 XML포맷은 절대 없어지지 않는다.xml언어는 태그를 만들어주면 된다. 태그가 시작되면 끝나는 태그를 만들어줘야 한 문장이 끝난다.
- html은 정해져있는 규칙들이 있다.
- YAML로 만들어서 올리면 자동으로 서버 100대가 만들어진다.
- 데이터포맷에 대해 어떻게 쓸 것인지
- <products type="전자제품"> <product id="M001" price="300000">32인치 LCD 모니터</product> <product id="M002" price="210000">24인치 LCD 모니터</product> </products>
3.2. XML 파일 읽고 데이터 추출하기
- open() 함수로 xml 데이터 읽기
- xml 데이터 파싱하기
- select() 로 원하는 데이터 태그 선택하기
- 리턴값은 리스트 타입
- 원하는 데이터가 하나일 경우에는 select_one() 함수 사용
- 실제 데이터는 각 아이템.text 로 추출가능
data_file = open('users.xml', 'r', encoding='utf-8-sig')
# 1. xml 데이터 읽기
soup = BeautifulSoup(data_file, 'xml')
# 2. xml 데이터 파싱하기
users = soup.select('user')
# 3. 원하는 데이터 관련 태그 선택하기
for user in users:
# 4. 리스트이므로 for 문으로 아이템 추출
print(user.text)
# 5. 각 아이템.text 로 원하는 데이터 출력
파싱 (parsing)과 데이터 추출 코드 이해
- 일종의 xml 데이터를 분석해서, 빠르게 원하는 데이터를 추출할 수 있도록 트리(tree) 형태로 만드는 것
- pip install bs4
from bs4 import BeautifulSoup
soup= BeautifulSoup(xml파일디스크립터, 'xml')
soup.select(원하는 데이터 태그)
트리 형식: 가장 높은 카테고리가 올라가고, 가장 낮은 카테고리가 내려가는 것
- 마크업 언어를 이용해 문서를 구성한다.
예제 코드
from bs4 import BeautifulSoup
data_file = open('users.xml', 'r', encoding='utf-8-sig')
soup = BeautifulSoup(data_file, 'lxml')
users = soup.select('user')
for user in users:
print(user.text)
=>
bigdata-python
30
tae park
21
이름과 나이 각각 추출하려면?
from bs4 import BeautifulSoup
data_file = open('users.xml', 'r', encoding='utf-8-sig')
soup = BeautifulSoup(data_file, 'lxml')
users = soup.select('user')
for user in users:
name = user.select_one('name')
print ('이름:', name.text)
age = user.select_one('age')
print ('나이:', age.text)
=>
이름: bigdata-python
나이: 30
이름: tae park
나이: 21
csv파일도 읽어 본 다음, 나에게 꼭 필요한 데이터만 파싱해서 사용하면 된다. → xml도 도메인에 대한 이해를 하고 들어가야 한다.
예제 코드 (연습 문제 풀이)
연습문제
- <http://suggestqueries.google.com/complete/search?output=toolbar&q=> 에 키워드를 추가하면 연관 검색어를 추출 가능
- XML 포멧으로 되어 있으므로, 태그과 속성값 추출 기술을 활용해서 추출 가능
원하는 데이터가 태그의 속성값에 있을 때에는 아이템[속성이름] 로 추출 가능
다음 셀에 다음 코드를 넣고 다음 마지막 문장을 입력하여 코드를 완성하시오
import requests
from bs4 import BeautifulSoup
keyword = '스마트폰'
google_related_keyword_api = '<http://suggestqueries.google.com/complete/search?output=toolbar&q=>' + keyword
response = requests.get(google_related_keyword_api)
# 파일이 아니라, 데이터를 Open API 에서 가져오기 위한 함수
soup = BeautifulSoup(response.content, 'xml')
# requests.get() 의 리턴값은 객체
# 객체.content 에 가져온 데이터가 있음
datas1 = [-------------------]
for item in datas1:
print(item['data'])
- 답변
import requests
from bs4 import BeautifulSoup
keyword = '아시안컵'
google_related_keyword_api = '<http://suggestqueries.google.com/complete/search?output=toolbar&q=>' + keyword
response = requests.get(google_related_keyword_api) # 파일이 아니라, 데이터를 Open API 에서 가져오기 위한 함수
soup = BeautifulSoup(response.content, 'xml') # requests.get() 의 리턴값은 객체
# 객체.content 에 가져온 데이터가 있음
datas1 = soup.select('suggestion')
for item in datas1:
print(item['data'])
=>
아시안컵
아시안컵 한국 일정
아시안컵 일정
아시안컵 순위
아시안컵 대진표
아시안컵 중계
아시안컵 경기
아시안컵 조별순위
아시안컵 조편성
아시안컵 경기일정
import requests
from bs4 import BeautifulSoup
keyword = '스마트폰'
google_related_keyword_api = '<http://suggestqueries.google.com/complete/search?output=toolbar&q=>' + keyword
response = requests.get(google_related_keyword_api) # 파일이 아니라, 데이터를 Open API 에서 가져오기 위한 함수
soup = BeautifulSoup(response.content, 'xml') # requests.get() 의 리턴값은 객체
# 객체.content 에 가져온 데이터가 있음
datas1 = soup.select('suggestion')
for item in datas1:
print(item['data'])
=>
스마트폰
스마트폰 갤러리
스마트폰 중독
스마트폰을 떨어뜨렸을 뿐인데
스마트폰 중독 테스트
스마트폰 찾기
스마트폰 중독 문제점
스마트폰 배경화면
스마트폰 tv 미러링
스마트폰갤
4. 다양한 데이터 포멧 이해하기: JSON
4.1. JSON 데이터 포멧 이해하기
- JavaScript Object Notation 줄임말
- JSON은 서버와 클라이언트 또는 컴퓨터/프로그램 사이에 데이터를 주고 받을 때 사용하는 데이터 포멧
- 키와 값을 괄호와 세미콜론과 같이 간단한 기호로 구성하여 표현할 수 있고, 언어나 운영체제에 구애받지 않기 때문에 많이 사용됨
- 특히 웹/앱 환경에서 Rest API를 사용하여, 서버와 클라이언트 사이에 데이터를 주고 받을때 많이 사용
- JSON 포멧 예{ "id":"01", "language": "Java", "edition": "third", "author": "Herbert Schildt" }
4.2. JSON 데이터 포멧 읽기
- json 라이브러리 제공
json.loads() 함수로 문자열로된 json 데이터를 사전처럼 다룰 수 있음
import json # pip install json
# 변수에 문자열로 된 JSON 포멧의 데이터가 있을 경우
data = '{ "id":"01", "language": "Java", "edition": "third", "author": "Herbert Schildt" }'
jsondata = json.loads(data)
print (jsondata['id'], jsondata['language'], jsondata['edition'], jsondata['author'], type(jsondata))
=> 01 Java third Herbert Schildt <class 'dict'>
json.dumps() 함수로 파이썬 사전 데이터를 JSON 문자열 데이터로 변환할 수 있음
import json
# 변수에 문자열로 된 JSON 포멧의 데이터가 있을 경우
data = { "id":"01", "language": {"Java":"basic", "Java":"advance"}, "edition": "third", "author": "Herbert Schildt" }
jsondata = json.dumps(data)
print (jsondata, type(jsondata))
jsondata = json.dumps(data, indent=2) # 들여쓰기
print (jsondata, type(jsondata))
=>
{"id": "01", "language": {"Java": "advance"}, "edition": "third", "author": "Herbert Schildt"} <class 'str'>
{
"id": "01",
"language": {
"Java": "advance"
},
"edition": "third",
"author": "Herbert Schildt"
} <class 'str'>
csv파일의 key 값: 가장 위 쪽 목록
→ 이것을 key와 value로 만든 것
json.load() 함수로 파일로된 json 데이터를 사전처럼 다룰 수 있음
- JSON 파일 예: 유투브 카테고리 (미국)
{
"kind": "youtube#videoCategoryListResponse",
"etag": "\\"m2yskBQFythfE4irbTIeOgYYfBU/S730Ilt-Fi-emsQJvJAAShlR6hM\\"",
"items": [
{
"kind": "youtube#videoCategory",
"etag": "\\"m2yskBQFythfE4irbTIeOgYYfBU/Xy1mB4_yLrHy_BmKmPBggty2mZQ\\"",
"id": "1",
"snippet": {
"channelId": "UCBR8-60-B28hp2BmDPdntcQ",
"title": "Film & Animation",
"assignable": true
}
},
{
"kind": "youtube#videoCategory",
"etag": "\\"m2yskBQFythfE4irbTIeOgYYfBU/UZ1oLIIz2dxIhO45ZTFR3a3NyTA\\"",
"id": "2",
"snippet": {
"channelId": "UCBR8-60-B28hp2BmDPdntcQ",
"title": "Autos & Vehicles",
"assignable": true
}
}
]
}
이렇게 데이터를 파싱해서 원하는 데이터를 얻어내야 한다.
items에서 kind, snippet, title을 불러오겠다.
import json
with open('US_category_id.json', 'r', encoding='utf-8-sig') as json_file:
json_data = json.load(json_file)
for item in json_data['items']:
print (item['kind'], item['snippet']['title'])
=>
youtube#videoCategory Film & Animation
youtube#videoCategory Autos & Vehicles
youtube#videoCategory Music
youtube#videoCategory Pets & Animals
youtube#videoCategory Sports
youtube#videoCategory Short Movies
youtube#videoCategory Travel & Events
youtube#videoCategory Gaming
youtube#videoCategory Videoblogging
youtube#videoCategory People & Blogs
youtube#videoCategory Comedy
youtube#videoCategory Entertainment
youtube#videoCategory News & Politics
youtube#videoCategory Howto & Style
youtube#videoCategory Education
youtube#videoCategory Science & Technology
youtube#videoCategory Nonprofits & Activism
youtube#videoCategory Movies
youtube#videoCategory Anime/Animation
youtube#videoCategory Action/Adventure
youtube#videoCategory Classics
youtube#videoCategory Comedy
youtube#videoCategory Documentary
youtube#videoCategory Drama
youtube#videoCategory Family
youtube#videoCategory Foreign
youtube#videoCategory Horror
youtube#videoCategory Sci-Fi/Fantasy
youtube#videoCategory Thriller
youtube#videoCategory Shorts
youtube#videoCategory Shows
youtube#videoCategory Trailers