220916 Day16

유예지·2022년 9월 16일

(4) 예제

>>> import urllib.request as req
    import re
    
>>> req.urlopen("http://daum.net")   #urlopen() : url 접속
>>> req.urlopen("http://daum.net").read()   #url 코드를 가져온다

>>> data = req.urlopen("http://daum.net").read().decode("utf-8")
	data   #data 전체를 '한 문장' 취급한다
    
#'https'로 시작해서 'js'로 끝나는 것만 출력
>>> p = re.compile("https://\S+[.]js")
	li = p.findall(data)
	for i in li:
    	print(i)

>>> p = re.compile("https[:./\w]*[.]js")
    li = p.findall(data)
    for i in li:
        print(i)
#[:./\w] : [] 안에 들어가면 메타 문자의 특성을 갖지 않는다
#':', '.', '/', '\w' 하나하나로 인식한다

>>> webp = '''<div class="faZHB"><a href="#" target="_self" role="button" aria-expanded="true" class="M_704" style="display: block;"><span class="WoYOw">이른 아침 문을 여는 빵집입니다. 아침식사로 빵을 사러 가기엔 좋지만 매장안에서 드실 공간은 없어요. 이 빵집은 특이하게도 물 또는 커피를 무료로 텀블러에 담아갈수 있습니다.  가볍게 아침을 해결하고자 하는 여행자나 현지인은 들러보면 좋을 장소입니다.  참고로, 식빵 나오는 시간은 오전11시~12시 입니다. 빵 가격은 가성비 괜찮은 편이고 맛은 무난합니다. </span></a></div><div class="faZHB"><a href="#" target="_self" role="button" aria-expanded="false" class="M_704" style="display: block;"><span class="WoYOw">우연히 들어갔는데 사장님이 따뜻하고 친절하셔서 제주도 이미지마저 좋게 느껴졌어요. 그리고 무엇보다 빵이 정말 맛있어요. 제주도에서 원탑입니다!!! 여기보다 두배는 ...</span><span class="_3_09q"><svg xmlns="
http://www.w3.org/2000/svg
" viewBox="0 0 12 7" class="_3Dnsh" aria-hidden="true"><path d="M11.47.52a.74.74 0 0 0-1.04 0l-4.4 4.45v.01L1.57.52A.74.74 0 1 0 .53 1.57l5.12 5.08a.5.5 0 0 0 .7 0l5.12-5.08a.74.74 0 0 0 0-1.05z"></path></svg><span class="place_blind">내용 더보기</span></span></a></div><div class="faZHB"><a href="#" target="_self" role="button" aria-expanded="false" class="M_704" style="display: block;"><span class="WoYOw">맛집검색하다가 스쳐지나갔는데 숙소근처에 있길래 들렸어요!!  시식하는빵도 있고  빵구매하는데 서비스로 흰색찹살떡??도 주시고 친절하세요! 인절미빵 강추입니다!  ...</span><span class="_3_09q"><svg xmlns="
http://www.w3.org/2000/svg
" viewBox="0 0 12 7" class="_3Dnsh" aria-hidden="true"><path d="M11.47.52a.74.74 0 0 0-1.04 0l-4.4 4.45v.01L1.57.52A.74.74 0 1 0 .53 1.57l5.12 5.08a.5.5 0 0 0 .7 0l5.12-5.08a.74.74 0 0 0 0-1.05z"></path></svg><span class="place_blind">내용 더보기</span></span></a></div><div class="faZHB"><a href="#" target="_self" role="button" aria-expanded="false" class="M_704" style="display: block;"><span class="WoYOw">인절미빵. 먹물치즈빵? 제일 맛있었고 대파빵은 삼겹살을 부르는 꽤 매운 맛이었어요! 빵이 대체로 다~~~~맛있고 친절하십니다 주차는 근처 공영주차장에 하면 됩니다 다...</span><span class="_3_09q"><svg xmlns="
http://www.w3.org/2000/svg
" viewBox="0 0 12 7" class="_3Dnsh" aria-hidden="true"><path d="M11.47.52a.74.74 0 0 0-1.04 0l-4.4 4.45v.01L1.57.52A.74.74 0 1 0 .53 1.57l5.12 5.08a.5.5 0 0 0 .7 0l5.12-5.08a.74.74 0 0 0 0-1.05z"></path></svg><span class="place_blind">내용 더보기</span></span></a></div><div class="faZHB"><a href="#" target="_self" role="button" aria-expanded="false" class="M_704" style="display: block;"><span class="WoYOw">사진을 제대로 못찍엇는데 뒤에 비닐로 싸진 빵들이에요 ㅋㅋㅋ  여기 진짜 촤고에요 보니 동네찐로컬맛집같아요 빵종류도 많고 각 빵마다 시식빵이 있는데 크기가 넘 커서...</span><span class="_3_09q"><svg xmlns="
http://www.w3.org/2000/svg
" viewBox="0 0 12 7" class="_3Dnsh" aria-hidden="true"><path d="M11.47.52a.74.74 0 0 0-1.04 0l-4.4 4.45v.01L1.57.52A.74.74 0 1 0 .53 1.57l5.12 5.08a.5.5 0 0 0 .7 0l5.12-5.08a.74.74 0 0 0 0-1.05z"></path></svg><span class="place_blind">내용 더보기</span></span></a></div><div class="faZHB"><a href="#" target="_self" role="button" aria-expanded="false" class="M_704" style="display: block;"><span class="WoYOw">성산 여행하는 동안 두번이나 방문했어요 빵도 특색있고 하나하나 다 맛있고 사장님도 직원분도 친절하시고  커피도 무료로 먹을수 있게 해주시고 살때마다 서비스빵을 주...</span><span class="_3_09q"><svg xmlns="
http://www.w3.org/2000/svg
" viewBox="0 0 12 7" class="_3Dnsh" aria-hidden="true"><path d="M11.47.52a.74.74 0 0 0-1.04 0l-4.4 4.45v.01L1.57.52A.74.74 0 1 0 .53 1.57l5.12 5.08a.5.5 0 0 0 .7 0l5.12-5.08a.74.74 0 0 0 0-1.05z"></path></svg><span class="place_blind">내용 더보기</span></span></a></div><div class="faZHB"><a href="#" target="_self" role="button" aria-expanded="false" class="M_704" style="display: block;"><span class="WoYOw">사장님 너무 친절하시고 빵이 진짜 맛있어요.. 미친 맛,,,,🥹가격이 타 빵집보다 훠얼씬 저렴한데  맛이 훠얼씬 맛있네요,,,??!?! 저희 동네에 있었음 매일 가고싶네요ㅠㅠㅠ …</span><span class="_3_09q"><svg xmlns="
http://www.w3.org/2000/svg
" viewBox="0 0 12 7" class="_3Dnsh" aria-hidden="true"><path d="M11.47.52a.74.74 0 0 0-1.04 0l-4.4 4.45v.01L1.57.52A.74.74 0 1 0 .53 1.57l5.12 5.08a.5.5 0 0 0 .7 0l5.12-5.08a.74.74 0 0 0 0-1.05z"></path></svg><span class="place_blind">내용 더보기</span></span></a></div><div class="faZHB"><a href="#" target="_self" role="button" aria-expanded="false" class="M_704" style="display: block;"><span class="WoYOw">재료를 아끼지 않으세요 눚은시간 방문했는데도 손님들이 꽤 왔어요 마늘바게트에는 소스를 아끼지 않았고 다른빵들도 크림이 듬뿍 들어 있었어요 서비스도 주시고 시식…</span><span class="_3_09q"><svg xmlns="
http://www.w3.org/2000/svg
" viewBox="0 0 12 7" class="_3Dnsh" aria-hidden="true"><path d="M11.47.52a.74.74 0 0 0-1.04 0l-4.4 4.45v.01L1.57.52A.74.74 0 1 0 .53 1.57l5.12 5.08a.5.5 0 0 0 .7 0l5.12-5.08a.74.74 0 0 0 0-1.05z"></path></svg><span class="place_blind">내용 더보기</span></span></a></div>'''

#영어 빼고 한글만 출력
>>> p = re.compile("[가-힣].+[가-힣]")   #한글로 시작해서 한글로 끝나는 것 (중간은 뭐가 있어도 상관없다)
    li = p.findall(webp)
    li
    
>>> p = re.compile("[^가-힣0-9\s.~]")
    e = p.sub("", webp)
    e    

>>> re.sub("\s\d+[.]\d+", "", e)

>>> p = re.compile("[가-힣\s.~!]+")
    li = p.findall(webp)
    for i in li:
        if i != '': 
            print(i)

  • 전화번호의 정규 표현식
"010[-]\d{4}[-]\d{4}"

"\d{2,3}[-]\d{4}[-]\d{4}"
  • 이메일의 정규 표현식
#prince@naver.com
#hello@daum.net
#morning@company.co.kr

"[A-z0-9]+@[A-z0-9]+[.][a-z.]+"

".+@[a-z0-9]+[.][a-z]+"
  • 주민번호의 정규 표현식
"\d{6}-\d{7}"

"\d{6}-[1-6]\d{6}"

* 컴파일 옵션

  • re.DOTALL (또는 re.S)
    '.' 메타 문자는 \n를 제외한 모든 문자와 매치된다
    만약 \n문자도 포함하여 매치하고 싶다면 re.DOTALL (또는 re.S) 옵션을 사용하여 정규식을 컴파일 한다
>>> p = re.compile('a.b', re.DOTALL)
    m = p.match('a\nb')
    print(m)
<re.Match object; span=(0, 3), match='a\nb'>
  • re.MULTILINE (또는 re.M)
    ^, $ 메타 문자를 문자열의 각 줄마다 적용해준다
>>> import re
>>> p = re.compile("^python\s\w+", re.MULTILINE)

    data = """python one
    life is too short
    python two
    you need python
    python three"""

    print(p.findall(data))
['python one', 'python two', 'python three']

④ 전방, 후방 탐색

>>> text1 = '''
    http://www.google.com/

    https://mail.google.com/

    ftp://ftp.google.com/

    '''

#['http:', 'https:', 'ftp:']
>>> p = re.compile(".+:")
    p.findall(text1)
['http:', 'https:', 'ftp:']   #먼저 ['http:', 'https:', 'ftp:']를 출력한 후

#['http', 'https', 'ftp']
>>> p = re.compile(".+(?=:)")
    p.findall(text1)
['http', 'https', 'ftp']    #전방 탐색을 해서 ':'를 제거한다


>>> text2 = '''apple: $50.24
    banana: $35.25
    pizza: $100
    '''
    
#['50.24', '35.25', '100']
>>> p = re.compile("[$].+")    #[$] 는 \$ 로 표기할 수도 있다
    p.findall(text2)
['$50.24', '$35.25', '$100']   #먼저 $숫자 부분을 출력한 후

>>> p = re.compile("(?<=[$]).+")   #후방 탐색을 해서 '$'를 제거한다
	p.findall(text2)


text3 = '''<p>이른 아침 문을 여는 빵집입니다</p>
<h1>아침식사로 빵을 사러 가기엔 좋지만 매장안에서 드실 공간은 없어요</h1>
<h5>이 빵집은 특이하게도 물 또는 커피를 무료로 텀블러에 담아갈수 있습니다</h5>
<p>가볍게 아침을 해결하고자 하는 여행자나 현지인은 들러보면 좋을 장소입니다</p>
<p>참고로 식빵 나오는 시간은 오전9시 입니다</p>
'''

#<p></p> 사이의 글
>>> p = re.compile("(?<=<p>).+(?=</p>)")
    p.findall(text3)   #<p> 뒤를 후방탐색, </p> 앞을 전방탐색 -> 한번에
['이른 아침 문을 여는 빵집입니다',
 '가볍게 아침을 해결하고자 하는 여행자나 현지인은 들러보면 좋을 장소입니다',
 '참고로 식빵 나오는 시간은 오전9시 입니다']

Numpy (Numerical Python)

-"the core library"
-"a high performance"

-2차원에서
axis 0 : x축
axis 1 : y축

-3차원에서
axis 0 : z축
axis 1 : y축
axis 2 : x축

* Numpy 의 특징과 장점

강력한 N차원 배열 객체, List 보다 빠르다 (파이썬은 느리다)
빠른 이유
-python 코드가 아니라 C코드로 작성되어 있어서
-메모리 저장구조가 달라서
-반복문을 사용하지 않고, 배열을 통해 바로 계산되어서
-벡터라이즈와 브로드캐스팅을 사용해서

* ndarray : n차원의 축

각 차원을 축(axis)라고 한다
배열의 차원은 'shape'라고 하고, tuple로 표시한다 -> (3, ), (2, 3)
shape 안의 숫자는 각 차원에 있는 원소의 개수
전체 원소의 개수는 'size'

  • array vs matrix
    -matrix : 행렬, 2차원까지만 가능
    -연산법이 다르다

1. 배열이란 : np.array()

-array 함수는 np 라이브러리에 들어있다
-입력값으로 '리스트' 가 들어간다
-동일한 데이터형 이어야 한다

(1) 배열 만들기

>>> import numpy as np

>>> a = np.array([0,1,2,3])   #입력값으로 리스트가 들어간다
	a
array([0, 1, 2, 3])

>>> print(a)
[0 1 2 3]   #array가 아닌 리스트로 착각할 수 있다

>>> print(a.shape)   #각 차원에 있는 원소의 개수
    print(a.size)    #전체 원소의 개수
    print(a.dtype)
    print(a.ndim)
(4,)
4
int32
1
  • 리스트를 array로 바꾸기
    리스트를 입력값으로 넣어주기만 하면 된다
>>> li = [0,1,2,3]
	np.array(li)
array([0, 1, 2, 3])

* array 의 속성 : dtype, shape, size ...

>>> a= np.array([1, 2, 3, 4])
	a.dtype
dtype(‘int64')

>>> a = np.array([0,1,2,3,4.3])
	a.dtype
dtype('float64')    #8 bit = 1 byte => 64bit = 8byte
#데이터형은 자동으로 할당된다

>>> a = np.array([0,1,2,3,4.3], dtype = 'int')
	a.dtype
dtype('int32')
>>> a
array([0, 1, 2, 3, 4])

>>> a = np.array([0,1,2,3], dtype ='float')
	a
array([0., 1., 2., 3.])
>>> a.dtype
dtype('float64')

>>> a = np.array([0,1,2,3], dtype ='float32')
	a.dtype
dtype('float32')
>>> a = np.array([0,1,2,3], dtype ='float16')
	a.dtype
dtype('float16')
>>> a = np.array([0,1,2,3], dtype ='float8')
	a.dtype
TypeError: data type 'float8' not understood

>>> a = np.array([0,1,2,3], dtype ='int8')   #int8 : byte (-128 to 127)
	a.dtype
dtype('int8')    
  • python과 numpy의 데이터형
    python : int, float, str, boolean, complex number, list, tuple, set, dict
    numpy : int, uint, float, bool, complex_

(2) python과 numpy의 계산 속도 비교

* [2,4,6,8] 출력

>>> list1 = [1,2,3,4]
    list2 = [1,2,3,4]
    list1 + list2
[1, 2, 3, 4, 1, 2, 3, 4]

#python
>>> list1 = [1,2,3,4]
    list2 = [1,2,3,4]

    list3 = []
    for i in range(4):
        list3.append(list1[i] + list2[i])
    list3
[2, 4, 6, 8]

#numpy
>>> array1 = np.array([1,2,3,4])
    array2 = np.array([1,2,3,4])

    array3 = array1 + array2
    array3
array([2, 4, 6, 8])

* 일반화

#python
>>> def add_list(n):
        li1 = list(range(1, n+1))
        li2 = list(range(1, n+1))
        li3 = []
        for i in range(n):
            li3.append(li1[i] + li2[i])

        return li3

>>> add_list(10)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

#numpy
>>> def add_array(n):
        ar1 = np.array(range(1, n+1))
        ar2 = np.array(range(1, n+1))
        ar3 = ar1 + ar2

        return ar3
        
>>> add_array(10)
array([ 2,  4,  6,  8, 10, 12, 14, 16, 18, 20])
>>> def add_list():
        li1 = list(range(1, 101))
        li2 = list(range(1, 101))

        li3 = []
        for i in range(100):
            li3.append(li1[i] + li2[i])

        return li3
>>> add_list()

>>> def add_array():
        ar1 = np.array(range(1, 101))
        ar2 = np.array(range(1, 101))
        ar3 = ar1 + ar2

        return ar3
>>> add_array()

* 계산 속도 비교

>>> import timeit

>>> li1 = list(range(10000))
	li2 = list(range(10000))
    
    def add_list():
    li3 = []
    for i in range(10000):
        li3.append(li1[i] + li2[i])
    
    return li3
    
>>> print(timeit.timeit(add_list, number=10000))    

>>> ar1 = np.array(range(10000))
	ar2 = np.array(range(10000))
    
    def add_array():
        ar3 = ar1 + ar2
    
    	return ar3
    
>>> print(timeit.timeit(add_array, number=10000))    

(3) 2차원, 3차원 배열 만들기

-np.array( )함수를 써서 만들기
-arange( )와 reshape( )를 써서 만들기

* 2차원 배열 만들기

>>> np.array([[1,2,3,4], [5,6,7,8]])   #대괄호 2개(중첩리스트) -> 2차원
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])
       
>>> np.arange(10)       
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.arange(10).reshape((2, 5))   
#arange(10) -> 1행 10열 (1X10)
#.reshape(2, 5) -> 2행 5열로 변경 (2*5 = 10)
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

>>> np.arange(12).reshape(3, 4)
>>> np.arange(12).reshape(3, -1)
#'-1' -> 3이 입력되어있기 때문에 4를 입력하지 않아도 자동으로 처리해준다

* 3차원 배열 만들기

>>> np.arange(24).reshape(2,3,4)   #3행 4열이 2장 나온다 (z, y, x)
>>> np.arange(24).reshape(3,4,2)
>>> np.arange(36).reshape(3,4,3)

(4) 배열의 연산

리스트의 연산과 비슷하지만, 약간 다르다
numpy 함수를 쓰는 것보다 '객체.함수( )' 가 편리하다
Numpy의 연산은 원소들끼리 이루어진다 -> "element wise"
array의 형태(shape)가 안 맞으면, 자동으로 맞추어 주기도 한다 -> "broadcasting"

* element wise : Numpy의 연산은 원소들끼리 이루어진다

>>> a = np.array([[1,2], [3,4]])
    b = np.array([[5,6], [7,8]])

>>> a + b
[[ 6  8]
 [10 12]]

>>> a ** b   #거듭제곱도 가능하다
[[    1    64]
 [ 2187 65536]]    

* broadcasting : array의 형태(shape)가 안 맞으면, 자동으로 맞추어 주기도 한다

-브로드캐스팅(Broadcasting) 이란
차원(dimension)이 다른 두 배열의 연산에서
낮은 차원의 배열이 차원을 맞추어 주도록 변화한다
데이터의 복사를 하지 않으므로 빠르다
적어도 행과 열 중에 어느 한쪽의 형태는 같아야 한다

>>> a = np.array([[1,2], [3,4]])
	c = np.array([5,6])

>>> a + c    
array([[ 6,  8],
       [ 8, 10]])
       
>>> d = np.array([5])
	a + d       
array([[6, 7],
       [8, 9]])
       
>>> a + 6
array([[ 7,  8],
       [ 9, 10]])
       
>>> e = np.array([5,6,7])
	a + e       
ValueError: operands could not be broadcast together with shapes (2,2) (3,)

>>> a = np.array([[1,2,3], [4,5,6]])
    c = np.array([5,6])
    a + c
ValueError: operands could not be broadcast together with shapes (2,3) (2,)

>>> a = np.array([[1,2,3,4], [5,6,7,8]])
    c = np.array([5,6])
    a + c
ValueError: operands could not be broadcast together with shapes (2,4) (2,)

>>> a = np.array([[1,2], [3,4], [5,6],[7,8]])
    c = np.array([5,6])
    a + c
array([[ 6,  8],
       [ 8, 10],
       [10, 12],
       [12, 14]])
>>> a = np.arange(25).reshape(5, 5)
	a

#array([20, 21, 22, 23, 24]) 출력
>>> a[4,:]

>>> a[:,(1,3)]
>>> a[(1,3),(0,2)]
>>> a = np.array([1,2,3,4])
    a + np.array([1,2])   #불가능
ValueError: operands could not be broadcast together with shapes (4,) (2,)

>>> np.array([[1],[2]])
array([[1],
       [2]])
>>> a + np.array([[1],[2]])   #가능
array([[2, 3, 4, 5],
       [3, 4, 5, 6]])

0개의 댓글