numpy 모듈

: 데이터 분석 시 과학적 계산을 위한 핵심 라이브러리
: ndarray 지원. 다차원 배열 객체.

: 선형대수 계산
: 파이썬 데이터 분석 핵심.

함수명 기능
import numpy as np
np.sum(x)
np.mean(x) 평균
np.var(x) 분산
np.std(x) 표준편차(√분산)
np.array(x, dtype=) np.narray타입으로 변경. dtype : 내부 요소 타입 변경가능.
type(x) 타입 반환
x.dtype 데이터 타입 반환
x.shape 행 열 수 반환 (튜플)
x.ndim 차원 수 반환
x.size 원소 수 반환
np.zeros((행 수, 열 수)) 0으로 채워진 (행 X 열)의 배열 생성
np.ones((행 수, 열 수)) 1으로 채워진 (행 X 열)의 배열 생성
np.full((행 수, 열 수), x) x로 채워진 (행 X 열)의 배열 생성
np.eye(x) x행 x열의 단위 행열 생성. (대각선으로 1 채워진 행열)
 np.random.rand(x) x개의 균등분포 난수 생성.
 np.random.randn(x) x개의 정규분포 난수 생성.(평균 : 0, 표준편차 : 1)
 np.random.randint(x, size(차원, 행, 열) 0 ~ x-1까지 난수를 가진 행 X 열 X 차원의 배열 생성
x.copy() 배열을 복사. (복사된 배열 수정 시 원본배열 변경사항 없음)
np.arange(x, y) x에서 y-1까지 array 생성.
x.reshape(행, 열) 배열을 행 수 X 열 수로 변경.
x.astype(y) x를 y타입으로 변경
np.add(x, y) 배열 x, y 더하기
np.substract(x, y) 배열 x, y 빼기
np.multiply(x, y) 배열 x, y 곱하기
np.div(x, y) 배열 x, y 나누기
np.dot(x, y) x배열 y배열 내적
np.cumsum(x) 누적 합
np.cumprod(x) 누적 곱
 np.unique(x) 배열의 중복된 값 제거
 np.instersect1d(x, y, assume_unique=True) x와 y의 교집합 (assume_unique=True : 중복허용)
 np.union1d(x, y) x와 y의 합집합
x.transpose()
행렬 위치 변경(전치)
x.T 전치
x.swapaxes(a, b) a차원과 b차원 위치 변경(전치)
np.c_[x, y] x 배열에 y 열 추가
np.r_[x, y] x 배열에 y 행 추가
np.append(x, y) x 배열에 y 열 추가
np.insert(x, a, y) x 배열에 a번째에 y 열에  추가
np.insert(x, a, y, axis=1) x 배열에 a번째에 y 행에  추가
np.delete(x, a) x배열에서 a 열 삭제
np.delete(x, a, axis=1) x배열에서 a 행 삭제
np.where(조건배열, x, y) 각 배열 index마다 조건이 True면 x값 출력, False면 y값 출력
np.concatenate([x, y])  x, y배열 결합
y1, y2, ... = np.split(x, n) x배열을 n개로 나눠 n개의 배열 리턴
y1, y2, ... = np.hsplit(x, n) x배열을 열로 나눠 n개의 배열 리턴
y1, y2, ... = np.vsplit(x, n) x배열을 행으로 나눠 n개의 배열 리턴
import random
random.randint(n) 0에서 n-1까지의 난수 1개 복원 추출
random.randint(start, end) start에서 end-1까지 난수 1개의 복원 추출
random.rand(n) 0에서 1 사이의 표준정규분포를 따르는 n개의 난수 추출.
random.rand(m, n) 0에서 1 사이의 표준정규분포를 따르는 m x n의 난수 추출.
random.randn(n) 평균 0, 표준편차 1인 가우시안 정규분포의 n개 난수 추출.
random.randn(m, n) 평균 0, 표준편차 1인 가우시안 정규분포의 m x n개 난수 추출.
random.sample(리스트, k=n) 리스트에서 n개의 난수 비복원 추출
np.random.choice(배열, n) 배열에서 n개의 복원 추출
np.random.choice(배열, n, replace=False) 배열에서 n개의 비복원 추출
np.random.choice(배열, n, replace=False, p=[0.1, 0.9]) 배열에서 n개의 비복원 추출. p는 n개의 원소를 가지고 총합이 1이어야함. p의 값에 따른 가중치 부여

 * numpy1

 - 기본 통계 함수를 직접 작성 후 함수와 결과 비교

grades = [1, 3, -2, 4]

print(grades)

def show_grades(grades):
  for g in grades:
    print(g, end = ' ')

show_grades(grades)
[1, 3, -2, 4]
1 3 -2 4 
grades = [1, 3, -2, 4]
def grades_sum(grades): # 합
  tot = 0
  for g in grades:
    tot += 9
  return tot

def grades_ave(grades): # 평균
  tot = greads_sum(grades)
  ave = tot / len(grades)
  return ave

def greades_variance(grades): # 분산
  ave = grades_ave(grades)
  vari = 0
  for su in grades:
    vari += (su - ave) ** 2
  return vari / len(grades)
  #return vari / (len(grades) - 1)

def grades_std(grades):  # 표준편차
    return greades_variance(grades) ** 0.5

print('합은 ', grades_sum(grades))
print('평균은 ', grades_ave(grades))
print('분산은 ', greades_variance(grades))
print('표준편차는 ', greades_variance(grades))

 

 - numpy 함수를 사용

import numpy as np
print('합은 ', np.sum(grades))
print('평균은 ', np.mean(grades))
print('분산은 ', np.var(grades))
print('표준편차는 ', np.std(grades))
합은  36
평균은  9.0
분산은  61.5
표준편차는  61.5

합은  6
평균은  1.5
분산은  5.25
표준편차는  2.29128784747792
함수명 기능
import numpy as np  
np.sum(x)
np.mean(x) 평균
np.var(x) 분산
np.std(x) 표준편차(√분산)

 

 * numpy2

import numpy as np

ss = ['tom', 'james', 'oscar']
print(ss, ' ', type(ss))
# ['tom', 'james', 'oscar']   <class 'list'>

ss2 = np.array(ss)
print(ss, ' ', type(ss2))
# ['tom', 'james', 'oscar']   <class 'numpy.ndarray'>
# 메모리 비교
li = list(range(1,10))
print(li)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

print(li[0], li[1], ' ', id(li[0]), id(li[1]))
# 1 2   10914496 10914528

print(li * 10)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print('-' * 10)
# ----------

# li 각 요소와 10 곱하기
for l in li:
    print(l * 10, end=' ')
# 10 20 30 40 50 60 70 80 90 
# ndarray
num_arr = np.array(li)
print(id(num_arr), id(num_arr[0]), id(num_arr[1]))
# 140361351910064 140361354499656 140361354499656

print(num_arr * 10)
# [10 20 30 40 50 60 70 80 90]

 => list의 각 요소는 각각 memory를 할당받아 메모리 소모가 크다.

      * 연산 시 전체 값을 반복한다.

 

 => array의 각 요소는 동일한 메모리를 할당 받아 메모리 소모가 작다.

      * 연산 시 각 요소에 연산된다.

 

# 배열의 속성은 모두 동일. 우선순위에 따라 data type이 변경됨.
a = np.array([1, 2, 3.2]) # 우선순위 int -> float -> complex -> str
a = np.array([1, 2, 3], dtype='float32') 

print(a, type(a), a.dtype, a.shape, a.ndim, a.size)
# [1. 2. 3.] <class 'numpy.ndarray'> float32 (3,) 1 3

print(a[0]) # 1.0

a[0] = 8
print(a[0]) # 8.0

b = np.array([[1,2,4], [4,5,6]])
print(b, b.shape)
'''
[[1 2 4]
 [4 5 6]] (2, 3)
'''

print(b[0,0]) # 1
print(b[0], b[[0]]) # 1차원, 2차원
# [1 2 4] [[1 2 4]]

 => 배열의 속성은 모두 동일. 우선순위에 따라 data type이 변경됨.

      우선순위 int -> float -> complex -> str

함수명 기능
np.array(x, dtype=) np.narray타입으로 변경. dtype : 내부 요소 타입 변경가능.
type(x) 타입 반환
x.dtype 데이터 타입 반환
x.shape 행 열 수 반환 (튜플)
x.ndim 차원 수 반환
x.size 원소 수 반환

 

c = np.zeros((2, 2)) # 2행 2열의 0으로 채워진 배열 생성
print(c)
[[0. 0.]
 [0. 0.]]

d = np.ones((2, 2)) # 2행 2열의 1으로 채워진 배열 생성
print(d)
[[1. 1.]
 [1. 1.]]

e = np.full((2, 2), 7) # 2행 2열의 7으로 채워진 배열 생성
print(e)
[[7 7]
 [7 7]]

f = np.eye(3) # 3행 3열의 단위행렬
print(f)
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
함수명 기능
np.zeros((행 수, 열 수)) 0으로 채워진 (행 X 열)의 배열 생성
np.ones((행 수, 열 수)) 1으로 채워진 (행 X 열)의 배열 생성
np.full((행 수, 열 수), x) x로 채워진 (행 X 열)의 배열 생성
np.eye(x) x행 x열의 단위 행열 생성. (대각선으로 1 채워진 행열)

 

print(np.random.rand(5)) # 균등분포
[0.20323807 0.81989097 0.84142846 0.46991121 0.21930122]

print(np.mean(np.random.rand(5)))
0.4230689697221274

print(np.random.randn(5)) # 정규분포
[-1.52232689 -0.31403199 -0.81191411  1.16482644 -0.23161658]

print(np.mean(np.random.randn(5)))
0.6515764623112837

x1 = np.random.randint(10, size=6)
[8 3 5 4 3 7]

x2 = np.random.randint(10, size=(3,4))
[[8 9 0 6]
 [5 9 0 2]
 [0 4 7 0]]

x3 = np.random.randint(10, size=(3,4,4))
print(x1)
[[[8 1 9 1]
  [4 9 3 7]
  [8 8 4 0]
  [7 9 8 1]]

print(x2)
 [[0 9 1 5]
  [7 8 4 0]
  [4 6 4 2]
  [9 8 9 2]]

print(x3)
 [[3 5 9 5]
  [7 3 5 4]
  [1 0 5 7]
  [2 2 2 2]]]

print(x3.ndim, x3.shape)
3 (3, 4, 4)
함수명 기능
 np.random.rand(x) x개의 균등분포 난수 생성.
 np.random.randn(x) x개의 정규분포 난수 생성.(평균 : 0, 표준편차 : 1)
 np.random.randint(x, size(차원, 행, 열) 0 ~ x-1까지 난수를 가진 행 X 열 X 차원의 배열 생성

 

# 슬라이싱
a = np.array([1,2,3,4,5])
print(a, a[1], a[1:5:2], a[1:], a[1:5])
[1 2 3 4 5] 2 [2 4] [2 3 4 5] [2 3 4 5]

a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
print(a[:])
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

print(a[0], a[0][0], a[[0]])
[1 2 3 4] 1 [[1 2 3 4]]

print(a[1:])
[[ 5  6  7  8]
 [ 9 10 11 12]]

 => a[x:y:z] : index x에서 y-1까지 z간격의 슬라이싱

 => a    =    a[:]

 => a[x][y] : x행, y열의 값

 

print(a[1:, 0:2])
[[ 5  6]
 [ 9 10]]

print(a)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

b = a[:2, 1:3] # 서브 배열
print(b)
[[2 3]
 [6 7]]

b[0,0] = 77
print(b)
[[77  3]
 [ 6  7]]

print(a)
[[ 1 77  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
aa = np.array([1,2,3])
print(aa)
[1 2 3]

bb = aa[1:3]
print(bb)
[2 3]

bb[0] = 100
print(aa)
[  1 100   3]

print(bb)
[100   3]

aa[1] = 50
print(aa)
[ 1 50  3]

print(bb)
[50  3]

 => a[x:y, b:c] : index x에서 y-1 각 행에서 index b에서 c-1까지의 열 데이터.

 => 서브배열을 수정하면 원본의 데이터도 수정된다.

 

cc = aa[1:3].copy() # 배열 복사본 작성
print(cc)
[50  3]

cc[0] = 99
print(cc)
[99  3]

print(aa)
[ 1 50  3]

 => copy()를 이용하여 복사 시 서브배열을 수정하여도 원본 데이터는 변경 되지않는다.

함수명 기능
x.copy() 배열을 복사. (복사된 배열 수정 시 원본배열 변경사항 없음)

 

 * numpy3

# 배열 연산
import numpy as np

x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.arange(5, 9).reshape((2,2)) # 배열 변경
y = y.astype(np.float32) # 타입 변경
print(x)
[[1. 2.]
 [3. 4.]]

print(y)
[[5. 6.]
 [7. 8.]]
함수명 기능
np.arange(x, y) x에서 y-1까지 array 생성.
x.reshape(행, 열) 배열을 행 수 X 열 수로 변경.
x.astype(y) x를 y타입으로 변경

 

print(x + y)
[[ 6.  8.]
 [10. 12.]]
 
print(np.add(x, y)) # numpy 유니버셜 함수
[[ 6.  8.]
 [10. 12.]]

print(x - y) # np.substract()
[[-4. -4.]
 [-4. -4.]]

print(x * y) # np.multiply()
[[ 5. 12.]
 [21. 32.]]

print(x / y) # np.divid()
[[0.2        0.33333333]
 [0.42857143 0.5       ]]
함수명 기능
np.add(x, y) 배열 x, y 더하기
np.substract(x, y) 배열 x, y 빼기
np.multiply(x, y) 배열 x, y 곱하기
np.div(x, y) 배열 x, y 나누기

 

# python 함수보다 numpy 지원 함수가 계산 속도가 빠름

big_arr = np.random.rand(1000000) # 난수 발생

%timeit sum(big_arr) # python 함수

# 10 loops, best of 3: 155 ms per loop
%timeit np.sum(big_arr) # numpy 함수
# The slowest run took 23.08 times longer than the fastest. This could mean that 
# an intermediate result is being cached. 1000 loops, best of 3: 538 µs per loop

 

# 내적
v = np.array([9, 10])
w = np.array([11, 12])
print(v * w)
[ 99 120]


print(v.dot(w))    # 219
print(np.dot(v,w)) # 219

print(x)
[[1. 2.]
 [3. 4.]]
 
print(np.dot(x, y))
[[19. 22.]
 [43. 50.]]
print(sum(x), np.sum(x))
[4. 6.] 10.0

print(np.cumsum(x)) # 누적 합
[ 1.  3.  6. 10.]

print(np.cumprod(x)) # 누적 곱
[ 1.  2.  6. 24.]

names = np.array(['tom', 'james', 'tom', 'oscar'])
names2 = np.array(['tom', 'page', 'john'])
print(np.unique(names)) # 중복 제거
['james' 'oscar' 'tom']

print(np.intersect1d(names, names2)) # 중복 제거
['tom']

print(np.intersect1d(names, names2, assume_unique=True)) # 중복 허용
['tom' 'tom']

print(np.union1d(names, names2))
['james' 'john' 'oscar' 'page' 'tom']
함수명 기능
np.dot(x, y) x배열 y배열 내적
np.cumsum(x) 누적 합
np.cumprod(x) 누적 곱
 np.unique(x) 배열의 중복된 값 제거
 np.instersect1d(x, y, assume_unique=True) x와 y의 교집합 (assume_unique=True : 중복허용)
 np.union1d(x, y) x와 y의 합집합

 

# 전치 : 행렬 위치 변경
print(x)
[[1. 2.]
 [3. 4.]]
 
print(x.T)
[[1. 3.]
 [2. 4.]]

print(x.transpose())
[[1. 3.]
 [2. 4.]]

print(x.swapaxes(0, 1))
[[1. 3.]
 [2. 4.]]
함수명 기능
x.transpose()
행렬 위치 변경(전치)
x.T 전치
x.swapaxes(a, b) a차원과 b차원 위치 변경(전치)

 

# Broadcasting : 크기가 다른 배열 간의 연산.
x = np.arange(1, 10).reshape(3, 3)
y = np.array([1, 0 , 1])
print(x)
[[1 2 3]
 [4 5 6]
 [7 8 9]]

print(y)
[1 0 1]

print(x + y)
[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]]

 

# 배열에 행, 또는 열 추가
aa = np.eye(3)
print(aa)
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

bb = np.c_[aa, aa[2]] # 2 열과 동일한 열 추가
print(bb)
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 1.]]

cc = np.r_[aa, [aa[2]]] # 2 행과 동일한 행 추가
print(cc)
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]
 [0. 0. 1.]]

a = np.array([1,2,3])
b = np.append(a, [4, 5]) # 열 방향 추가
print(b)
[1 2 3 4 5]

c = np.insert(a, 0, [6, 7]) # axis = 0, 열 방향 삽입
print(c)
[6 7 1 2 3]

d = np.delete(a, 1)
print(d)
[1 3]

# 2차원도 가능.. # axis = 0 열 방향,  axis = 1 행 방향
함수명 기능
np.c_[x, y] x 배열에 y 열 추가
np.r_[x, y] x 배열에 y 행 추가
np.append(x, y) x 배열에 y 열 추가
np.insert(x, a, y) x 배열에 a번째에 y 열에  추가
np.insert(x, a, y, axis=1) x 배열에 a번째에 y 행에  추가
np.delete(x, a) x배열에서 a 열 삭제
np.delete(x, a, axis=1) x배열에서 a 행 삭제

 

# where 조건 연산
x = np.array([1,2,3])
y = np.array([4,5,6])
conditionData = np.array([True, False, True])
print(np.where(conditionData, x, y))
[1 5 3]

aa = np.where(x >= 2)
print(aa) #(array([1, 2]),)

print(x[aa])
[2 3]

print(np.where(x >= 2, 'T', 'F'))
['F' 'T' 'T']

print(np.where(x >= 2, x, x + 200))
[201   2   3]
함수명 기능
np.where(조건배열, x, y) 각 배열 index마다 조건이 True면 x값 출력, False면 y값 출력

 

# 배열 결합
kbs = np.concatenate([x, y])
print(kbs)
[1 2 3 4 5 6]

x1, x2 = np.split(kbs, 2)
print(x1)
[1 2 3]

print(x2)
[4 5 6]

a = np.arange(1, 17).reshape((4, 4))
print(a)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]
 [13 14 15 16]]

x1, x2 = np.hsplit(a, 2)
print(x1)
[[ 1  2]
 [ 5  6]
 [ 9 10]
 [13 14]]

print(x2)
[[ 3  4]
 [ 7  8]
 [11 12]
 [15 16]]

print(np.vsplit(a, 2))
[array([[1, 2, 3, 4],
       [5, 6, 7, 8]]), array([[ 9, 10, 11, 12],
       [13, 14, 15, 16]])]
함수명 기능
np.concatenate([x, y])  x, y배열 결합
y1, y2, ... = np.split(x, n) x배열을 n개로 나눠 n개의 배열 리턴
y1, y2, ... = np.hsplit(x, n) x배열을 열로 나눠 n개의 배열 리턴
y1, y2, ... = np.vsplit(x, n) x배열을 행으로 나눠 n개의 배열 리턴

 

 * numpy4

# 복원/ 비복원 추출 - 데이터 집합으로 부터 무작위로 일부 자료 선택
# 복원 - 추출된 데이터가 다시 추출가능한 추출.
import numpy as np
import random

li = np.array([1,2,3,4,5,6,7])
# 복원 추출
for _ in range(5): # 5개의 난수 추출(복원)
    print(li[random.randint(0, len(li) - 1)], end = ' ')
6 1 6 5 2 

# 비복원 추출
print(random.sample(list(li), k = 5)) # 5개의 난수 추출(비복원). list 타입만 가능. list 출력.
[3, 7, 2, 5, 6]

print(random.sample(range(1, 46), k = 6)) # 로또 번호 추출
[40, 29, 15, 24, 38, 7]
# choice
print(list(np.random.choice(range(1, 46), 6))) # 복원 추출. 1 ~ 46 까지 6개 추출.
[16, 24, 35, 34, 26, 35]

print(list(np.random.choice(range(1, 46), 6, replace=True))) # 복원 추출.
[1, 33, 13, 15, 42, 35]

print(list(np.random.choice(range(1, 46), 6, replace=False))) # 비복원 추출.
[39, 4, 1, 11, 27, 28]

# 가중치를 부여한 랜덤 추출
ar = 'air book cat desk, egg, fox, god'
ar = ar.split(' ') # ' '을 기준으로 분해.
print(ar)
['air', 'book', 'cat', 'desk,', 'egg,', 'fox,', 'god']

print(np.random.choice(ar, 3, p = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.4]))
['god' 'desk,' 'god']
# p의 합은 1로 클 수록 추출될 확률이 증가한다.
함수명 기능
import random  
random.randint(n) 0에서 n-1까지의 난수 1개 복원 추출
random.randint(start, end) start에서 end-1까지 난수 1개의 복원 추출
random.rand(n) 0에서 1 사이의 표준정규분포를 따르는 n개의 난수 추출.
random.rand(m, n) 0에서 1 사이의 표준정규분포를 따르는 m x n의 난수 추출.
random.randn(n) 평균 0, 표준편차 1인 가우시안 정규분포의 n개 난수 추출.
random.randn(m, n) 평균 0, 표준편차 1인 가우시안 정규분포의 m x n개 난수 추출.
random.sample(리스트, k=n) 리스트에서 n개의 난수 비복원 추출
np.random.choice(배열, n) 배열에서 n개의 복원 추출
np.random.choice(배열, n, replace=False) 배열에서 n개의 비복원 추출
np.random.choice(배열, n, replace=False, p=[0.1, 0.9]) 배열에서 n개의 비복원 추출. p는 n개의 원소를 가지고 총합이 1이어야함. p의 값에 따른 가중치 부여

 

 

11. Ajax

12. Ajax + DB

13. Join

 


11. Ajax

 : ajax 송부한 데이터에 문자열 더하여 수신 받기.

 : ajax 요청하여 수신 받은 데이터 출력하기.

 

 = django_test10_ajax

 * settings

INSTALLED_APPS = [
    
    ...
    
    'myajaxapp',
]

 => application 연결

 

 * urls

from django.contrib import admin
from django.urls import path
from myajaxapp import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.indexFunc),
    path('startajax', views.func1),
    path('goajax', views.func2),
]

 => url -> function 연결

     url '' -> indexFunc

     url 'startajax' -> func1

     url 'goajax' -> func2

 

 

 * views

from django.shortcuts import render
import json
from django.http.response import HttpResponse

lan = {
    'id':111,
    'name':'파이썬',
    'history':[
        {'date':'2021-2-12','exam':'basic'},
        {'date':'2021-2-22','exam':'django'},
    ]
}

def test(): # json encoding/decoding
    print(type(lan)) # dict
    jsonString  = json.dumps(lan)
    jsonString  = json.dumps(lan, indent = 4) # 들어쓰기
    print(jsonString)
    #{"id": 111, "name": "\ud30c\uc774\uc36c", 
    #"history": [{"date": "2021-2-12", "exam": "basic"}, {"date": "2021-2-22", "exam": "django"}]}
    print(type(jsonString)) # str
    
    print('----------------------------------------------------------')
    
    dic = json.loads(jsonString)
    print(dic)
    print(type(dic)) # dict
    print(dic['name'])
    for h in dic['history']:
        print(h['date'], h['exam'])
    #2021-2-12 basic
    #2021-2-22 django
    
def indexFunc(request):
    test()
    return render(request,'abc.html')
	
    ...

 => import jason

 => json.dumps(data, indent = 들여쓰기) : json encoding. python object(Dict, List, Tuple..)를 문자열로 변경하는 작업

 => json.loads(data) : json decoding. 문자열을 python object(Dict, List, Tuple..)로 변경하는 작업

 => indexFunc() -> abc.html

 

 * abc.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$(document).ready(function(){
	$("#btn1").click(function(){
		let msg = $("#txtMsg").val()
		$("#showData").empty();
		$.ajax({
			url:'startajax',
			type:'get',
			data:{'msg':msg}, /* msg=msg */
			dataType:'json',
			success:function(data){
				let str = '';
				for(let k in data){
					let str = k + '<br>' + data[k];
				}
				str += "<br><b>"+data['key']+"</b>";
				$("#showData").html(str);
			},
			error:function(){
				$("#showData").text("에러");
			}
		});
	});
	
	$("#btn2").click(function(){
		//$("#showData2").text("<i>1</i>"); // <i> 그대로 출력
		$("#showData2").html("<i>1</i>");
		$.ajax({
			url:'goajax',
			type:'get',
			dataType:'json',
			success:function(data){
				//alert(data);
				let str = '';
				$.each(data, function(ind, entry){ //jquery 반복문
					str += entry['name'] + ', ' + entry['age'] + '<br>';
				});
				$("#showData2").html(str);
			},
			error:function(){
				$("#showData2").text("에러");
			}
		});
	});
});
</script>
</head>
<body>
<h2>Ajax test</h2>
자료입력 : <input type="text" id="txtMsg" value="홍길동">
<button id="btn1">버튼1 클릭</button>
<br>
<div id="showData">실습결과1</div>
<hr>
<button id="btn2">버튼2 클릭</button>
<br>
<div id="showData2">실습결과2</div>
</body>
</html>

$.ajax({

    url:'요청명',

    type:'get/post',

    dataType:'json',

    success:function(x){

        // 성공 시 실행문

    }

    error:function(){

        // 에러 발생 시 실행문

    }

});

=> ajax 처리

 

$.each(x, function(idx, entry){

    // for entry in x: 과 동일

    // 반복문

});

 => json 반복문

 * views

...

import time
def func1(request):
    msg = request.GET['msg']
    #print(msg) # 홍길동
    time.sleep(1);
    context = {'key':msg + ' ajax 요청 처리'} # dict - 홍길동 ajax 요청 처리
    return HttpResponse(json.dumps(context), content_type="application/json") # dict -> str

def func2(request):
    datas = [
        {'name' : '고길동', 'age':25},
        {'name' : '김길동', 'age':27},
        {'name' : '나길동', 'age':28},
    ]
    return HttpResponse(json.dumps(datas), content_type="application/json")

 => request.GET['msg'] : 요청의 'msg' key의 값을 get.

 => HttpResponse(json.dumps(context), content_type="application/json") : context를 dict 타입에서 str로 변환 후

       json형식의 str을 send.


12. Ajax + DB

 : ajax 요청 시 DB의 직원 테이블 data 조회하여 출력하기.

 

 = django_test11_ajax

 => create application - myajax

 

 * settings

...

INSTALLED_APPS = [
    
    ...
    
    'myajax',
]

...

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'test',                # DB명 : db는 미리 작성되어 있어야 함.       
        'USER': 'root',                # 계정명 
        'PASSWORD': '123',             # 계정 암호           
        'HOST': '127.0.0.1',           # DB가 설치된 컴의 ip          
        'PORT': '3306',                # DBMS의 port 번호     
    }
}

...

 => application 연결.

 => DB 설정

 

 

 * anaconda prompt

cd C:\work\psou\django_test11_ajax
python manage.py inspectdb > aaa.py

 

 

 * models

from django.db import models

# Create your models here.
class Sangdata(models.Model):
    code = models.IntegerField(primary_key=True)
    sang = models.CharField(max_length=20, blank=True, null=True)
    su = models.IntegerField(blank=True, null=True)
    dan = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'sangdata'

 => aaa.py의 사용할 table을 models.py에 복사 붙여넣기. (제작된 Table을 Django 형식으로 자동 생성)

 

 Make migrations - myajax

 Migrate

 

 

 * urls

from django.contrib import admin
from django.urls import path
from myajax import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.MainFunc),
    path('list', views.ListFunc),
    path('calldb', views.ListDbFunc),
]

 => url -> function 연결.

 => url '' -> MainFunc()

 => url 'list' -> ListFunc()

 => url 'calldb' -> ListDbFunc()

 

 

 * views

from django.shortcuts import render
from myajax.models import Sangdata
from django.http.response import HttpResponse
import json

# Create your views here.
def MainFunc(request):
    return render(request, 'main.html')

def ListFunc(request):
    return render(request, 'list.html')

def ListDbFunc(request):
    sdata = Sangdata.objects.all() # db sangdata 전체 읽기
    datas = []
    for s in sdata:
        #print(s.code)
        dict ={'code':s.code, 'sang':s.sang, 'su':s.su,'dan':s.dan}
        datas.append(dict)
    #print(datas)
    #[{'code': 1, 'sang': '장갑', 'su': 3, 'dan': 10000},
    # {'code': 2, 'sang': '벙어리장갑', 'su': 2, 'dan': 12000},
    # {'code': 3, 'sang': '가죽장갑', 'su': 10, 'dan': 50000}, 
    # {'code': 4, 'sang': '가죽점퍼', 'su': 5, 'dan': 650000}, 
    # {'code': 6, 'sang': '신상', 'su': 11, 'dan': 3000}, 
    # {'code': 7, 'sang': '아메리카노', 'su': 2, 'dan': 1}, 
    # {'code': 8, 'sang': '가방', 'su': 22, 'dan': 300}]
    return HttpResponse(json.dumps(datas), content_type='application/json')

 => MainFunc() -> main.html

 => ListFunc() -> list.html

 => ListDbFunc() : db data 읽은 후 json data send.(dict -> list -> str로 변환)

 

 

 * main.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>메인</h2>
<a href="/list">상품 보기</a>
</body>
</html>

 

 * list.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-latest.js"></script>

<script type="text/javascript">
$(document).ready(function(){
	$("#btnOk").click(function(){
		$("#showData").empty();
		
		$.ajax({
			url:'calldb',
			type:'get',
			dataType:'json',
			success:function(data){
				//alert(data);
				let str = "<table border='1'>";
				str += "<tr><th>코드</th><th>상품명</th><th>수량</th><th>단가</th></tr>";
				let count = 0;
				$.each(data, function(ind, entry){
					str += "<tr>";
					str += "<td>" + entry['code'] + "</td>";
					str += "<td>" + entry['sang'] + "</td>";
					str += "<td>" + entry['su'] + "</td>";
					str += "<td>" + entry['dan'] + "</td>";
					str += "</tr>";
					count += 1;
				});
				
				str += "</table>";
				$("#showData").append(str);
				$("#showData").append("건수 : "+count);
			},
			errorLfunction(){
				$("#showData").text("로딩 실패");
			}
		});
	});
});
</script>

</head>
<body>
<h2>상품 목록</h2>
<button id="btnOk">상품자료 출력(Ajax)</button><br><br>
<div id="showData"></div>
<hr>
</body>
</html>

 => button click 시 ajax로 'calldb' 요청명 send 후 성공 시 table 형태로 조회된 DB 데이터 출력.


13. Join

 * views

SearchJikwonFunc(request):
    jikwon_jik = request.GET["jikwon_jik"]
    jikwonList = Jikwon.objects.extra(select={'buser_name':'buser_name'}, tables=['Buser'],
    where =['Buser.buser_no=Jikwon.buser_num']).filter(jikwon_jik = jikwon_jik)
    data = []
    for j in jikwonList:
        dict ={}
        dict['jikwon_no'] = j.jikwon_no
        dict['jikwon_name'] = j.jikwon_name
        dict['buser_name'] = j.buser_name
        data.append(dict)
    print(data)
    return HttpResponse(json.dumps(data), content_type = "application/json")

5. sqlite

6. where, group by

7. 원격 DB

8. DB - ForeignKey

9. DB - CRUD, 페이징

10. 게시판


5. sqlite

: 장고의 ORM(Object Relational Mapping) 사용하여 내장 함수로 DB의 DML, DDL .. 등을 실행.

 

 = django_test04_sqlite

 * settings

INSTALLED_APPS = [
	...
    'sqlapp',
]

 

 * url

from django.contrib import admin
from django.urls import path
from sqlapp import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.Main),
    path('show/', views.DbTestFunc),
]

path('admin/', admin.site.urls) : admin 요청명 admin.py와 연결

 

 * models : db table 작성

from django.db import models

# Create your models here.
# ORM
# 논리적인 테이블 설정
class Article(models.Model):
    code = models.CharField(max_length=10)
    name = models.CharField(max_length=20)
    price = models.IntegerField()
    pub_date = models.DateTimeField()

class 테이블명(models.Model) : 테이블 생성

column명 = models.CharField(maxlength= ) : 문자타입 칼럼 생성.

column명 = models.IntegerField() : 숫자타입 칼럼 생성.

column명 = models.DateTimeField() : 날짜타입 칼럼 생성.

 

explore 창 - 프로젝트 오른쪽 클릭 - Django - Make Migrations - sqlapp

explore 창 - 프로젝트 오른쪽 클릭 - Django - Migrate

 

 

 * admin계정 id 생성
 - anconda prompt 창 실행

cd C:\work\psou\django_test04_sqlite
python manage.py createsuperuser
=> id / e-mail / password 설정

 - http://127.0.0.1/admin/ 접속 후 login

 - table data 입력

 

 

 * admin

from django.contrib import admin
from sqlapp.models import Article

# Register your models here.
class ArticleAdmin(admin.ModelAdmin):
    list_display = ('id', 'code', 'name', 'price', 'pub_date')

admin.site.register(Article, ArticleAdmin)

class 클래스명(admin.ModelAdmin):

     list_display = ('칼럼명1', ... )

admin.site.register(테이블명, 클래스명)

 => 테이블과 admin계정 연결

 

 

 * views

from django.shortcuts import render
from sqlapp.models import Article

# Create your views here.
def Main(request):
    return render(request, "main.html")

def DbTestFunc(request):
    datas = Article.objects.all() # 장고의 ORM. select * from Article 이 내부적으로 수행. list 타입으로 리턴.
    #print(datas) # <QuerySet [<Article: Article object (1)>, <Article: Article object (2)>, <Article: Article object (3)>]>
    #print(datas[0].name) # 아아
    return render(request, 'list.html',{'articles':datas}) # QuerySet을 전달.

models.py의 클래스명.objects.all() : select * from 테이블명(클래스명)

 

 

 * main.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>메인</h2>
<a href="show/">자료 보기</a>
</body>
</html>

 

 * list.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>


Article 자료 보기 - Djang template language 사용 <br>
{% if articles.count %}
	{% for a in articles %}
		<b>{{a.code}}</b> {{a.name}} {{a.price}} {{a.pub_date}}<br>
	{% endfor %}
{% else %}
	<p>자료가 없습니다.</p>
{% endif %}
</body>
</html>

{% if 조건 %}

{% else %}

{% endif %}

=> if 문

 

{% for 변수 in 자료 %}

{% endfor %}

=> for 문

 

6. where, group by

 * settings

INSTALLED_APPS = [
    ...
    'sql_app',
]

 => application연결

 

 

 * models

from django.db import models

# Create your models here.
class Profile(models.Model):
    name = models.CharField(max_length = 10)
    age = models.IntegerField()
    

 => DB 테이블 생성

 

 - explore 창 - 프로젝트 오른쪽 클릭 - Django - Create application - sqlapp

 - explore 창 - 프로젝트 오른쪽 클릭 - Django - Make Migrations - sqlapp

 - explore 창 - 프로젝트 오른쪽 클릭 - Django - Migrate

 

해당 프로젝트 cmd 창 : python manage.py createsuperuser 

 

 * admin

from django.contrib import admin
from sql_app.models import Profile

# Register your models here.
class ProfileAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'age')

admin.site.register(Profile, ProfileAdmin)

 => 테이블과 admin 계정 연결.

 

 - http://127.0.0.1/admin/ 접속 후 login

 - table data 입력

 

 

 * urls

from django.contrib import admin
from django.urls import path
from sql_app import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.IndexFunc),
    path('calldata/', views.CallFunc),
]

 => url과 views 연결

 

 

 * views

from django.shortcuts import render
from sql_app.models import Profile
from django.db.models.aggregates import Avg, Count, Max, Min, Sum

# Create your views here.
def IndexFunc(request):
    return render(request, 'index.html')

def CallFunc(request):
    profile_list = Profile.objects.all() # 전체 자료 list로 리턴
    
    for row in profile_list.values_list(): # 리스트의 값들 리턴
        print(row)
        
    print(Profile.objects.aggregate(Avg('age')))  # select avg(age) from Profile
    print(Profile.objects.aggregate(Max('age')))
    print(Profile.objects.aggregate(Sum('age')))
    print(Profile.objects.aggregate(Count('age')))
    print(len(profile_list))
    print(Profile.objects.filter(name = '홍길동').aggregate(Avg('age'))) # where 조건
    qs = Profile.objects.values('name').annotate(Avg('age')) # group 별 작업
    
    for r in qs:
        print(r)
        
    pro_list = []
    
    for pro in profile_list:
        pro_dict ={}
        pro_dict['name'] = pro.name
        pro_dict['age'] = pro.age
        pro_list.append(pro_dict)
        print(pro_list)
        # [{'key1':value1, 'key2':value2, ... }, {'key1':value1, 'key2':value2, ... }, ... ]
    
    context = {'pro_list':pro_list}
        
    return render(request, 'list.html', context)

QuerySet 타입.values_list() : value list 리턴

테이블명.objects.aggregate(Avg('칼럼명')) : select avg(칼럼명) from 테이블명

테이블명.objects.aggregate(Max('칼럼명')) : select max(칼럼명) from 테이블명

테이블명.objects.aggregate(Sum('칼럼명')) : select sum(칼럼명) from 테이블명

테이블명.objects.aggregate(Count('칼럼명')) : select count(칼럼명) from 테이블명

테이블명.objects.filter(칼럼명=값) : select * from 테이블명 where 칼럼명 = 값

테이블명.objects.values('칼럼명').annotate(Avg('칼럼명')) : select avg(칼럼명) from 테이블명 group by 칼럼명

 

 

 * index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
메인(QuerySet Test)<br>
<a href="calldata/">db 자료를 읽어 dict type으로 출력</a>
<br>
<a href="admin/">장고가 지원하는 관리자 창</a>
</body>
</html>

 

 

 

 * list.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
자료 보기</p>
{{pro_list}}
</body>
</html>

7. 원격 DB

 = django_test06_mariadb

DB 접속하여 DataBase 생성

explore 창 - 프로젝트 오른쪽 클릭 - Django - Create application - myguset

 

 

 * settings

INSTALLED_APPS = [

    ...
    
    'myguest',
]

...

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'yourdb',                     # DB명 : db는 미리 작성되어 있어야 함.       
        'USER': 'root',                       # 계정명 
        'PASSWORD': '123',                    # 계정 암호           
        'HOST': '127.0.0.1',                  # DB가 설치된 컴의 ip          
        'PORT': '3306',                       # DBMS의 port 번호     
    }
}

DATABASES = {
    'default': {

        django.db.backends.mysql',

        'NAME': 'database명',                     # DB명 : db는 미리 작성되어 있어야 함.       
        'USER': 'root',                          # 계정명 
        'PASSWORD': '123',                  # 계정 암호           
        'HOST': '127.0.0.1',                   # DB가 설치된 pc의 ip          
        'PORT': '3306',                        # DBMS의 port 번호     
    }
}

 => remote DB 연결 정보.

 

 

 * models

from django.db import models

# Create your models here.
class Guest(models.Model):
    myno = models.AutoField(auto_created = True, primary_key = True)
    title = models.CharField(max_length=50)
    content = models.TextField()
    regdate = models.DateTimeField()
    
    def __str__(self):
        return self.title
    
    class Meta:
        ordering = ('-title', 'id') # title이 같으면 id로 정렬
        ordering = ('-id',) # tuple 타입만 가능. 

칼럼명 = models.AutoField(auto_created = True, primary_key = True) : 자동 증가하는 index 기본키 생성.

칼럼명 = models.TextField() : text타입 칼럼 생성

 

class Meta:

ordering = ('-칼럼명1', '칼럼명2')

 => 칼럼명1 기준 desc 정렬 후 데이터가 같은 정보에 대해 칼럼명2 기준 asc정렬.

 

 

 - explore 창 - 프로젝트 오른쪽 클릭 - Django - Make Migrations - myguset

 - explore 창 - 프로젝트 오른쪽 클릭 - Django - Migrate

 

 

 * admin

from django.contrib import admin
from myguest.models import Guest

# Register your models here.
class GuestAdmin(admin.ModelAdmin):
    list_display = ('id', 'title', 'content', 'regdate')

admin.site.register(Guest, GuestAdmin)

 => 테이블과 admin계정 연결.

 

 

 * admin계정 id 생성 및 table data 입력

 

 

 * urls(django_test06_mariadb)

from django.contrib import admin
from django.urls import path
from myguest import views
from django.urls.conf import include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.MainFunc),
    path('guest/', include("myguest.urls")),
]

 => url과 views 연결

 

 

 * urls(myguest)

from django.urls import path
from myguest import views

urlpatterns = [
    path('', views.ListFunc),
    path('insert', views.InsertFunc),
    path('insertok/', views.InsertOkFunc),
]

 => url과 views 연결

 

 

 * views

from django.shortcuts import render
from myguest.models import Guest
from datetime import datetime
from django.http.response import HttpResponseRedirect

# Create your views here.
def MainFunc(request):
    return render(request, 'main.html')

def ListFunc(request):
    gdata = Guest.objects.all()                       # 전체 자료 읽기
    gdata = Guest.objects.all().order_by('title')    # order_by ascending
    gdata = Guest.objects.all().order_by('-title')   # order_by descending
    gdata = Guest.objects.all().order_by('-id')[0:2] # 정렬 후 슬라이싱
    print('gdata type : ', type(gdata))               # <class 'django.db.models.query.QuerySet'>
    return render(request, 'list.html', {'gdatas' : gdata})

def InsertFunc(request):
    return render(request, 'insert.html')

def InsertOkFunc(request):
    if request.method =='POST':
        print(request.POST.get('title'))
        print(request.POST['title'])
        # 입력자료로 테이블에 저장 : ORM
        Guest(
            title = request.POST.get('title'),
            content = request.POST.get('content'),
            regdate = datetime.now()
        ).save()
    return HttpResponseRedirect('/guest') # 추가후 목록 보기
'''
# 수정
g = Guest.objects.get(id=1)
g.title = "하하"
g.content = '하하하'
g.save()

# 삭제
g = Guest.objects.get(id=1)
g.delete
'''

테이블명.objects.all().order_by('칼럼명') : order by 칼럼명 asc

테이블명.objects.all().order_by('-칼럼명') : order by 칼럼명 desc

 

 - insert

테이블명(

    변수명 = request.POST.get('칼럼명'),

     ...

    변수명 = datetime.now()

).save()

 

 - update

temp = 테이블명.objects.get(조건)

temp.칼럼명 = "수정값"

temp.save()

 

 - delete

temp = 테이블명.objects.get(조건)

temp.delete()

 

 

 * main.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>메인</h2>
<a href="guest/">미니 방명록 보기</a>
</body>
</html>

 

 * list.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>글 목록</h2>

<a href="/guest/insert">자료 추가</a>
<table border="1">
	<tr>
		<th>아이디</th><th>제목</th><th>내용</th><th>등록일</th>
	</tr>
	{% if gdatas %}
	{% for g in gdatas %}
	<tr>
		<td>{{g.id}}</td>
		<td>{{g.title}}</td>
		<td>{{g.content}}</td>
		<td>{{g.regdate}}</td>
	</tr> 
	{% endfor %}
	{% else %}
	<tr>
		<td colspan ="4">자료가 없습니다.</td>
	</tr>
	{% endif %}
</table>
</body>
</html>

 

 * insert.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>방명록 글 입력</h2>
<form action="/guest/insertok/" method="post">{% csrf_token %}
<table>
	<tr>
		<td>제목</td>
		<td><input type="text" name="title" size="48"/></td>
	</tr>
	<tr>
		<td>내용</td>
		<td><textarea rows="5" cols="50" name="content"></textarea></td>
	</tr>
	<tr>
		<td colspan="2" style="text-align: center;"><input type="submit" value="등록" /></td>
	</tr>

</table>
</form>
</body>
</html>

8. DB - ForeignKey

 = django_test07

Django - create application - sangpumapp

 

 * settings

INSTALLED_APPS = [
    ...
    'sangpumapp',
]

...

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'sanpumdb',            # DB명 : db는 미리 작성되어 있어야 함.       
        'USER': 'root',                # 계정명 
        'PASSWORD': '123',             # 계정 암호           
        'HOST': '127.0.0.1',           # DB가 설치된 컴의 ip          
        'PORT': '3306',                # DBMS의 port 번호     
    }
}

 => application 연결 및 dataBase 연결 설정.

 

 

 * models

from django.db import models

# Create your models here.
class Maker(models.Model):
    mname = models.CharField(max_length=10)
    tel = models.CharField(max_length=20)
    addr = models.CharField(max_length=50)
    
    class Meta:
        ordering = ('-id',)
        
    def __str__(self):
        return self.mname
    
class Product(models.Model):
    pname = models.CharField(max_length=50)
    price = models.IntegerField()
    maker_name = models.ForeignKey(Maker, on_delete = models.CASCADE) # Maker table의 id와 연결

칼럼명 = models.ForeignKey(연결할 테이블명, on_delete = models.CASCADE) : 다른 테이블의 id를 Foreign Key로 사용

 

 

Django - make migrations - sangpumapp

Django - migrate

 

anaconda 접속 - cd C:\work\psou\django_test07 - python manage.py createsuperuser

 

 * admin

from django.contrib import admin
from sangpumapp.models import Maker, Product

# Register your models here.
class MakerAdmin(admin.ModelAdmin):
    list_display =('id', 'mname', 'tel', 'addr')
admin.site.register(Maker, MakerAdmin)

class ProductAdmin(admin.ModelAdmin):
    list_display =('id', 'pname', 'price', 'maker_name')
admin.site.register(Product, ProductAdmin)

 => 테이블에 admin 계정 연결.

 

http://127.0.0.1/admin/ 접속

Maker/Product table에 data 추가

 

 * urls

from django.contrib import admin
from django.urls import path
from sangpumapp import views

urlpatterns = [
    path('admin/', admin.site.urls),
    
    path('', views.Main),
    path('list1', views.List1), # maker
    path('list2', views.List2), # product
    path('list3', views.List3), # list1 -> list2
]

 => url과 views 연결.

 

 

 * views

from django.shortcuts import render
from sangpumapp.models import Maker, Product

# Create your views here.
def Main(request):
    return render(request, 'main.html')
    
def List1(request):
    makers = Maker.objects.all() # select
    return render(request, 'list1.html', {'makers':makers})
    
def List2(request):
    products = Product.objects.all() # select
    pcount = len(products)
    return render(request, 'list2.html', {'products':products, 'pcount':pcount})
    
def List3(request):
    mid = request.GET.get("id")
    products = Product.objects.all().filter(maker_name = mid)
    pcount = len(products)
    return render(request, 'list2.html',{'products':products, 'pcount':pcount})

변수1 = request.GET.get("key값")

테이블1.objects.all().filter(칼럼1 = 변수1) : 테이블1의 칼럼1에서 key의 value와 동일값의 list 출력.

 

 

 * main.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>메인화면</h2>
<ul>
	<li><a href="list1">상품 제조사 보기</a></li>
	<li><a href="list2">상품 목록 보기</a></li>
	<li>묻고 답하기</li>
</ul>
</body>
</html>

 * list1.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>제조사 목록</h2>
	<table border="1">
		<tr>
			<th>아이디</th><th>제조사</th><th>전화번호</th><th>주소</th>
		</tr>
		{% if makers %}
		{% for m in makers %}
		<tr>
			<td>{{m.id}}</td>
			<td><a href="list3?id={{m.id}}">{{m.mname}}</a></td>
			<td>{{m.tel}}</td>
			<td>{{m.addr}}</td>
		</tr>
		{% endfor %}
		{% else %}
		<tr>
			<td colspan="4">자료가 없습니다.</td>
		</tr>
		{% endif %}
	</table>
</body>
</html>

 

 * list2.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>상품 목록</h2>
	<table border="1">
		<tr>
			<th>아이디</th><th>상품명</th><th>가격</th><th>제조사</th>
		</tr>
		{% if products %}
		{% for p in products %}
		<tr>
			<td>{{p.id}}</td>
			<td>{{p.pname}}</td>
			<td>{{p.price}}</td>
			<td>{{p.maker_name}}</td>
		</tr>
		{% endfor %}
		<tr>
			<td colspan="4">건수{{pcount}}</td>
		<tr>
		{% else %}
		<tr>
			<td colspan="4">자료가 없습니다.</td>
		</tr>
		{% endif %}
	</table>
</body>
</html>


9. DB - CRUD, 페이징

① 메인 페이지

 = django_test08_sangdata

 * settings

...

INSTALLED_APPS = [

    ...
    
    'mysangpum',
]

...

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'test',                # DB명 : db는 미리 작성되어 있어야 함.       
        'USER': 'root',                # 계정명 
        'PASSWORD': '123',             # 계정 암호           
        'HOST': '127.0.0.1',           # DB가 설치된 컴의 ip          
        'PORT': '3306',                # DBMS의 port 번호     
    }
}

...

TIME_ZONE = 'Asia/Seoul'
USE_TZ = False

TIME_ZONE = 'Asia/Seoul'
USE_TZ = False

 => admin 페이지에 표시되는 시간은 기본적으로 UTC(UTC+9)이므로, 입력을 해도 9시간 전으로 표시된다.
      이에 표시되는 시간과 실제 DB에 입력되는 시간을 모두 Local시간(UTC)으로 맞춰 주어야 한다

 

 

 * remote DB의 데이터를 Django 형식으로 불러오기

anconda 접속

cd C:\work\psou\django_test08_sangdata
python manage.py inspectdb > abc.py

 => 이미 생성되어 있는 DB를 django 형식으로 abc.py에 코드 자동 작성.

 

 

 * models

from django.db import models

# Create your models here.
class Sangdata(models.Model):
    code = models.IntegerField(primary_key=True)
    sang = models.CharField(max_length=20, blank=True, null=True)
    su = models.IntegerField(blank=True, null=True)
    dan = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'sangdata'

 => abc.py의 sangdata table 내용 입력

 

 

 - Django - Make migrations - mysangpum

 - Django - Migrate

 

 

 * urls(django_test08_sangdata)

from django.contrib import admin
from django.urls import path
from mysangpum import views
from django.urls.conf import include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.MainFunc),
    path('sangpum/', include('mysangpum.urls')), # 요청 위임
]

 => url과 views 연결.

 

 

 * views

def MainFunc(request):
    return render(request, 'main.html')

 

 

 * main.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>메인</h2>
<a href="sangpum/list">상품보기(MariaDB)</a>
</body>
</html>

 

 

② list 출력

 

 * urls(mysangpum)

from django.urls import path
from mysangpum import views

urlpatterns = [
    path('list', views.ListFunc),
    path('insert', views.InsertFunc),
    path('insertok', views.InsertokFunc),
    path('update', views.UpdateFunc),
    path('updateok', views.UpdateokFunc),
    path('delete', views.DeleteFunc),
]

 => url, views 연결

 

 

 * views

def ListFunc(request):
    
    #SQL 직접사용해 보기
    conn = MySQLdb.connect(**config)
    sql = 'select * from sangdata'
    cursor = conn.cursor()
    cursor.execute(sql)
    datas = cursor.fetchall()
    print(type(datas)) # tuple
    
    
    # Django ORM
    datas = Sangdata.objects.all()
    return render(request, 'list.html', {'sangpums':datas})
    
    ...

 

 

* list.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h2>상품자료</h2>
<div style="width:80%; text-align:right;">
	<a href="/sangpum/insert">상품 추가</a>
</div>
<table class="table" style="width:80%;">
	<tr>
		<th>code</th><th>상품</th><th>수량</th><th>단가</th><th>기타</th>
	</tr>
	{% if sangpums %}
	{% for s in sangpums%}
	<tr>
		<!-- <td>{{s.0}}</td> -->
		<td>{{s.code}}</td>
		<td>{{s.sang}}</td>
		<td>{{s.su}}</td>
		<td>{{s.dan}}</td>
		<td>
			<a href="/sangpum/update?code={{s.code}}">수정</a> /
			<a href="/sangpum/delete?code={{s.code}}">삭제</a>
			</td>
	</tr>
	{% endfor%}
	{% else %}
	<tr>
		<td colspan="5">자료가 없습니다.</td>
	</tr>
	{% endif%}
</table>
</body>
</html>

 

 

③ 페이징 처리

 

 * views

def ListFunc(request):
    ...
    # 페이지 나누기 처리 - Paginator 클래스
    datas = Sangdata.objects.all().order_by('-code') # order by code desc
    paginator = Paginator(datas, 3) # 페이지당 출력 행수를 생성자로 전달
    try:
        page = request.GET.get('page') # page 값을 read
    except:
        page = 1 # page 값이 없을 경우 1 page 출력
    
    try:
        data = paginator.page(page)
    except PageNotAnInteger: # page가 숫자가 아닐 경우
        data = paginator.page(1)
    except EmptyPage:
        data = paginator.page(paginator.num_pages()) # 현재 페이지 출력
    
    # 클라이언트 화면에 개별 페이지 번호 표시용
    allPage = range(paginator.num_pages + 1)
    #print('allPage : ', allPage) # range(0, 5)
    return render(request, 'list2.html', {'sangpums':data, 'allPage':allPage}) 

paginator = Paginator(데이터, 출력행수) : 객체 생성. 페이지당 출력 행수를 생성자로 전달

paginator.page(출력페이지) : 나눠진 페이지에서 출력할 페이지 입력.

paginator.num_pages : 총페이지 수

 

* list2.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
	function func(){
		//alert("aa");
		let result = confirm("정말 삭제 할까요?")
		if(result){
			frm.submit();
		}
	}
</script>
</head>
<body>
<h2>상품자료</h2>
<div style="width:80%; text-align:right;">
	<a href="/sangpum/insert">상품 추가</a>
</div>
<table class="table" style="width:80%;">
	<tr>
		<th>code</th><th>상품</th><th>수량</th><th>단가</th><th>기타</th>
	</tr>
	{% if sangpums %}
	{% for s in sangpums%}
	<tr>
		<!-- <td>{{s.0}}</td> -->
		<td>{{s.code}}</td>
		<td>{{s.sang}}</td>
		<td>{{s.su}}</td>
		<td>{{s.dan}}</td>
		<td>
			<a href="/sangpum/update?code={{s.code}}">수정</a> /
			<!-- 삭제 전에 묻는 작업이 필요 -->
			<form action="/sangpum/delete" name="frm" method="get" style="display:inline;">
				<input type="hidden" name="code" value="{{s.code}}">
				<a href="javascript:void(0); onclick=func()">삭제</a>
			</form>
			</td>
	</tr>
	{% endfor%}
	<!-- paging -->
	<tr>
		<td colspan="5">
		{% if sangpums.paginator.num_pages > 1 %}
			<ul class="pager">
				{% if sangpums.has_previous %}
					<li class="previous"><a href="/sangpum/list?page={{sangpums.previous_page_number}}">Previous</a></li>
					<!-- <li><a href="/sangpum/list?page={{sangpums.previous_page_number}}">&laquo;이전</a></li> -->
				{% endif %}
				
				{% if sangpums.has_next %}
					<li class="next"><a href="/sangpum/list?page={{sangpums.next_page_number}}">Next</a></li>
					<!-- <li><a href="/sangpum/list?page={{sangpums.next_page_number}}">다음&raquo;</a></li> -->
				{% endif %}
				&nbsp; &nbsp;
				<li>(페이지 : {{sangpums.number}} / {{sangpums.paginator.num_pages}})</li>
			</ul>
			<hr>
			
			{% for p in allPage%}
				{% if p > 0 %}
					{% if p == sangpums.number %}
						[{{p}}]
					{% elif p != sangpums.number %}
						<a href="/sangpum/list?page={{p}}]"> {{p}} </a>
					{% endif %}
				{% endif %}
			{% endfor%}
		{% endif %}
		</td>
	</tr>
	{% else %}
	<tr>
		<td colspan="5">자료가 없습니다.</td>
	</tr>
	{% endif%}
</table>
</body>
</html>

data.number : 현재페이지

data.paginator.num_pages : 총 페이지

 

④ 게시물 추가

 * views

def InsertFunc(request):
    return render(request, 'insert.html')

def InsertokFunc(request):
    if request.method == 'POST':
        code = request.POST.get("code")
        #print('code : ', code)
        # 새로운 상품 code 유무 검증 작업 후 insert 진행
        try:
            Sangdata.objects.get(code=code) # where
            #print('code 있음')
            return render(request, 'insert.html', {'msg':'이미 등록된 번호입니다.'})
        except Exception as e:
            #print('code 없음')
            Sangdata(
                code = request.POST.get("code"),
                sang = request.POST.get("sang"),
                su = request.POST.get("su"),
                dan = request.POST.get("dan"),
                ).save()
            return HttpResponseRedirect('/sangpum/list') # 추가 후 목록 보기

 

 * insert.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
	window.onload = function(){
		document.getElementById("btnSummit").onclick = function(){
			chkData()
		}
	}
	function chkData(){
		//alert('a');
		if(frm.code.value === "" | frm.sang.value === ""){ // 입력자료 오류 검사
			alert("입력자료를 모두 채우시오.")
			return;
		}
		frm.submit();
	}
</script>

</head>
<body>
<h2>상품 추가</h2>
<form action="/sangpum/insertok" method="post" name="frm">{% csrf_token %}
	<table class="table" style="width:80%;">
		<tr>
			<td>코드 : </td>
			<td><input class="form-control" type="text" name="code"/>{{msg}}</td>
		</tr>
		<tr>
			<td>품명 : </td>
			<td><input class="form-control" type="text" name="sang"/></td>
		</tr>
		<tr>
			<td>수량 : </td>
			<td><input class="form-control" type="text" name="su"/></td>
		</tr>
		<tr>
			<td>단가 : </td>
			<td><input class="form-control" type="text" name="dan"/></td>
		</tr>
		<tr>
			<td colspan="4">
				<input class="btn-primary" type="button" value="저장" id="btnSummit">
			</td>
		</tr>
	</table>
</form>
</body>
</html>

 

⑤ 게시물 수정

 

 * views

def UpdateFunc(request):
    data = Sangdata.objects.get(code = request.GET.get('code'))
    return render(request, 'update.html', {'sang_one':data})

def UpdateokFunc(request):
    if request.method == 'POST':
        upRec = Sangdata.objects.get(code=request.POST.get('code'))
        upRec.code = request.POST.get('code')
        upRec.sang = request.POST.get('sang')
        upRec.su = request.POST.get('su')
        upRec.dan = request.POST.get('dan')
        upRec.save()
    return HttpResponseRedirect('/sangpum/list') # 수정 후 목록 보기

 

 * update.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h2>상품 수정</h2>
<form action="/sangpum/updateok" method="post">{% csrf_token %}
	<table class="table" style="width:80%;">
		<tr>
			<td>코드 : </td>
			<td>
				{{sang_one.code}}
				<input class="form-control" type="hidden" name="code" value="{{sang_one.code}}"/>
			</td>
		</tr>
		<tr>
			<td>품명 : </td>
			<td><input class="form-control" type="text" name="sang" value="{{sang_one.sang}}"/></td>
		</tr>
		<tr>
			<td>수량 : </td>
			<td><input class="form-control" type="text" name="su" value="{{sang_one.su}}"/></td>
		</tr>
		<tr>
			<td>단가 : </td>
			<td><input class="form-control" type="text" name="dan" value="{{sang_one.dan}}"/></td>
		</tr>
		<tr>
			<td colspan="4">
				<input class="btn-primary" type="submit" value="수정">
				<input type="button" value="이전화면" onclick="history.back()">
			</td>
		</tr>
	</table>
</form>
</body>
</html>

 

⑥ 게시물 삭제

 * views

def DeleteFunc(request):
    delRec = Sangdata.objects.get(code=request.GET.get('code'))
    delRec.delete()
    return HttpResponseRedirect('/sangpum/list') # 삭제 후 목록 보기

10. 게시판

 = django_test09_board

 

 

0. Django

1. 환경구축

2. 외부파일 사용하기

3. url 연결

4. session


0. Django : 파이썬 웹 제작 프레임워크

model, template, view Pattern의 프로그램 작성

(model, view, controller과 대응)

 

1. 환경구축

Django 설치

 anaconda prompt 접속 후 명령어 입력

pip install Django==3.1.6

 

Django 프로젝트 생성

① 명령어 창 사용

anaconda prompt 접속 후 명령어 입력

cd C:\work\psou
django-admin startproject django_ex

explorer창 - import - General - Existing Projects into Workspace - [Brows] 경로 설정, [Copy projects into workspace] Check

 

서버 실행

cd C:\work\psou\django_ex
python manage.py migrate
type db.sqlite3
python manage.py runserver

서버실행(ip, port설정)

cd C:\work\psou\django_test1
python manage.py runserver 7777
python manage.py runserver 192.168.0.3:7777

 

server port 변경

C:\anaconda3\Lib\site-packages\django\core\management\commands\runserver.py

default_port = '80'
=> port 번호 변경

서버 종료 : ctrl + c 두번

 

 

② 이클립스 사용

 - [File] - [New] - [other] - [PyDev Project] - name입력, 3.8 선택, python 선택 - finish
 - explorer창 - project 오른쪽 클릭 - Django - Migrate

 - explorer창 - project 오른쪽 클릭 - Django - Create application - myapp
 - explorer창 - project 오른쪽 클릭 - Run as - PyDev
 - http://127.0.0.1:8000/ 접속


2. 외부파일 사용하기

 = django_test1

 * settings.py : 설정

...

ALLOWED_HOSTS = ['*']

...

INSTALLED_APPS = [
	...
    
    'myapp',
]

...

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

STATICFILES_DIRS = (   os.path.join(BASE_DIR, 'static'), ) : base경로의 static folder의 외부파일 불러올 수 있도록 연결.

 

 * urls.py : 모든 클라이언트의 요청을 받음

from django.contrib import admin
from django.urls import path
from myapp import views

urlpatterns = [
    path('admin/', admin.site.urls),
    
    path('', views.index),
    path('hello', views.hello_func),
    path('hello_tem', views.hello_template),
    path('world', views.world_func)
]

 path('url명', views.메소드명) : 요청명 연결

 

 * views.py : 요청에 대한 기능 구현

from django.shortcuts import render
from django.http.response import HttpResponse

# Create your views here.
def index(request):
    return HttpResponse("기본요청 처리")

def hello_func(request):
    msg = '장고 '
    ss = "<html><body>장고프로젝트 작성 메세지 : %s</body></html>"%msg
    return HttpResponse(ss)

def hello_template(request):
    mymsg = '홍길동'
    return render(request, 'show.html',{'msg':mymsg})

def world_func(request):
    return render(request, 'disp.html')

HttpResponse(응답 메시지) : Http 응답 메시지 send.

render(request, '연결페이지.html', {'key':value, ... }, ... ) : 연결페이지에 dict타입 정보 send

 * show.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
hi {{msg}} &lt;- 장고의 template 변수 태그
<br>
<a href="world">world 문서</a>
</body>
</html>

 {{key}} : dict타입 key의 value 값 출력

 * disp.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel='stylesheet' type='text/css' href='/static/css/test.css'>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="/static/js/test.js"></script>
<script type="text/javascript">
/*
window.onload = function(){
	alert("good");
}
 */
$(document).ready(function(){
	//alert("nice");
	$("#myImg").click(function(){
		abc();
	});
});

 
</script>
</head>
<body>
<span style="color: #ff0000; font-size: 24px;">성공</span>
<br>
<b>자원관리는 static</b><strong>폴더 </strong>사용
<br>
<img src = "/static/images/pic.png" id="myImg" />
</body>
</html>

 * test.js

function abc(){
	alert("test");
	history.back();
}

history.back() : 뒤로가기 수행


3. url 연결

 - Function views 방법
 - Class-base views 방법
 - Including another URL conf 방법

 

 = django_test2

 * settings.py

INSTALLED_APPS = [
    'gpapp',
]

 

 * urls.py(django_test2)

from django.contrib import admin
from django.urls import path
from gpapp import views
from gpapp.views import CallView
from django.urls.conf import include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.MainFunc, name='MainFunc'), # Function views 방법
    path('gpapp/callget', CallView.as_view()), # Class-base views 방법
    path('sangpum/', include('gpapp.urls')),   # Including another URLconf 방법
    
]

path('url명', views.메소드명) : 해당 url이 수신 시 view.py의 해당 메소드 실행.

path('url명', 클래스명.as_view()) : 해당 url 수신 시 해당 클래스 실행.

path('url명', include('application명.urls')) : 해당 url이 포함됨 url 수신 시 해당 application의 urls 파일에서 나머지 url 연결하여 실행. 

 

 * views

from django.shortcuts import render
from django.views.generic.base import TemplateView

# Create your views here.
def MainFunc(request):
    return render(request, 'index.html')

class CallView(TemplateView):
    template_name = "callget.html"
    
def InsertFunc(request):
    #return render(request, "insert.html") # get/post 모두 처리
    if request.method == 'GET':
        print('GET 요청')
        return render(request, "insert.html")
    elif request.method == 'POST':
        print('POST 요청')
        name = request.POST.get("name")
        name = request.POST.["name"]
        return render(request,"list.html", {"name":name})
    else:
        print('요청 에러')

def SelectFunc(request):
    pass

def UpdateFunc(request):
    pass

request.method : 요청의 method를 get한다. ('GET', 'POST', ... )

request.GET.get('key값') : GET 요청에서 key의 value를 get한다.

request.POST.get('key값') : POST 요청에서 key의 value를 get한다.

 

 * index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
두번째 프로젝트 메인화면
<p/>
GET/POST 연습<br>
<a href="/gpapp/callget">callget 파일 요청 (get 방식)</a>
</body>
</html>

 

 * callget.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
GET/POST 연습<br>
<a href="/sangpum/insert">자료입력</a><br>
<a href="/sangpum/select">자료보기</a><br>
<a href="/sangpum/update">자료수정</a><br>
</body>
</html>

 

 * urls.py(gpapp)

# 메인 urls가 각 app에 처리 위임
from django.urls import path
from gpapp import views

urlpatterns = [
    path('insert', views.InsertFunc),
    path('select', views.SelectFunc),
    path('update', views.UpdateFunc),
]

 urls.py(django_test2)  ->  urls.py(gpapp)  -> views.py  -> insert.html  -> urls.py(django_test2)  ->  urls.py(gpapp)  -> views.py  ->list.html

 

 * insert.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
자료입력<p/>
<form action="/sangpum/insert" method="post">{% csrf_token %}<!-- 해킹 방지 -->
이름 : <input type="text" name="name">
<input type="submit" value="등록 확인">
</form>
</body>
</html>

{% csrf_token %} : 해킹방지 코드

 

 * list.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
결과 출력 : {{name}} {{123}} {{'문자열'}} {#주석#}
</body>
</html>


4. session

 = django_test3_session

 * settings

INSTALLED_APPS = [
    ...
    'sessionapp'
]

 

 * urls

from django.contrib import admin
from django.urls import path
from sessionapp import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.mainFunc),       # 1
    path('setos', views.setosFunc), # 2
    path('shows', views.showsFunc), # 3
]

 

 * views

from django.shortcuts import render
from django.http.response import HttpResponseRedirect

# Create your views here.
def mainFunc(request):  # 1
    return render(request, 'main.html')

def setosFunc(request): # 2
    if "favorite_os" in request.GET:
        print(request.GET['favorite_os'])
        request.session['f_os'] = request.GET["favorite_os"] # f_os 라는 키로 세션에 저장
        return HttpResponseRedirect('/shows') # 클라이언트를 통해서 shows 요청을 발생
    else:
        print('a')
        return render(request, 'setos.html')
    
def showsFunc(request): # 3
    context = {} # dict type 변수 생성
    
    if "f_os" in request.session:
        context['f_os'] = request.session['f_os'] # request.session.get('f_os')
        context['message'] = "선택된 운영체제 %s"%request.session['f_os']
    else:
        context['f_os'] = None
        context['message'] = "운영체제를 선택하지않았습니다."
        
    request.session.set_expiry(5); # session 유효 기간 5초 설정 
    
    return render(request, 'show.html', context)

 

HttpResponseRedirect('url명') : 클라이언트를 통해서 url요청명을 send.

 => session

request.session['key'] = value : session에 key값에 value값 set.

value = request.session.get('key값') : session에 key값에 value값 get.

value = request.session['key값'] : session에 key값에 value값 get.

request.session.set_expiry(초) : session 유효 시간 초 단위로 설정.

 

 * main.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
메인화면<p/>
session 연습 : 세션이란 일정시간 동안 같은 사용자로 부터 들어오는 여러 가지 요구들을 하나의 상태를 보고 그 상태를 일정하게 유지 시킨 기술.
클라이언트와 서버 사이의 연결이 유지되는 것 처럼 하기 위해 클라이언트의 정보를 서버 컴퓨터의 일정 공간을 확보해 정보를 기억시킬 수 있다.
<br>
<a href="/setos/">운영체제 선택하기</a>
</body>
</html>

 

 * setos.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>2. 세션 이해하기</h2>
<p>운영체제 선택</p>
<a href="/setos?favorite_os=window">윈도우</a><br>
<a href="/setos?favorite_os=mac">mac</a><br>
<a href="/setos?favorite_os=linux">리눅스</a><br>
</body>
</html>

=> url : setos, key : favorite_os, value : window, mac, linux

 

 * show.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>3. 세션 결과보기</h2>
<p>반환된 context의 message : {{message}}</p>
<p>반환된 context의 f_os : {{f_os}}</p>
<p>session의 f_os 값 직접 출력: {{request.session.f_os}}</p>
<a href="/setos">운영체제 다시 선택</a>
<a href="/">main page</a>
</body>
</html>

 

24. 연관분석 : 항목간의 연관 규칙을 발견하는 클러스터링 알고리즘의 일종

install.packages("arules")
library(arules)

 

 - arules가 원하는 transaction format 작성 연습

d_list <- list(c('a', 'b'), c('a', 'c'), c('a', 'e'), c('b', 'c', 'e'))
d_list
names(d_list) <- paste0('tr', c(1:4))
d_list
# $tr1
# [1] "a" "b"
# 
# $tr2
# [1] "a" "c"
# 
# $tr3
# [1] "a" "e"
# 
# $tr4
# [1] "b" "c" "e"
tran <- as(d_list, 'transactions')
tran
inspect(tran)
# items   transactionID
# [1] {a,b}   tr1          
# [2] {a,c}   tr2          
# [3] {a,e}   tr3          
# [4] {b,c,e} tr4

cust <- read.csv("testdata/priori_data2.csv", stringsAsFactors = F)
cust
str(cust)

cust$sangpum[cust$irum=='홍길동']

cust_list <- split(cust$sangpum, cust$irum)
cust_list
# $강감찬
# [1] "감자깡" "새우깡"
# 
# $공기밥
# [1] "자갈치" "맛동산"
# 
# $신기해
# [1] "코코넛" "맛동산"
# 
# $한국인
# [1] "짱구"   "감자깡"
# 
# $홍길동
# [1] "새우깡" "맥주"

cust_tran <- as(cust_list, 'transactions')
cust_tran
inspect(cust_tran)
# items           transactionID
# [1] {감자깡,새우깡} 강감찬       
# [2] {맛동산,자갈치} 공기밥       
# [3] {맛동산,코코넛} 신기해       
# [4] {감자깡,짱구}   한국인       
# [5] {맥주,새우깡}   홍길동  

# 연관규칙 생성
cust_rules <- apriori(cust_tran)
# confidence minval smax arem  aval originalSupport maxtime support minlen maxlen target  ext
# 0.8    0.1    1 none FALSE            TRUE       5     0.1      1     10  rules TRUE

summary(cust_tran)
inspect(cust_rules)
#       lhs         rhs      support confidence coverage lift count
# [1] {자갈치} => {맛동산} 0.2     1          0.2      2.5  1    
# [2] {코코넛} => {맛동산} 0.2     1          0.2      2.5  1    
# [3] {짱구}   => {감자깡} 0.2     1          0.2      2.5  1    
# [4] {맥주}   => {새우깡} 0.2     1          0.2      2.5  1  

customer <- read.csv("testdata/priori_data.csv", stringsAsFactors = F)
customer
#    bunho   irum    sangpum
# 1      1 홍길동     새우깡
# 2      2 홍길동     맛동산
# 3      3 홍길동       맥주
# 4      4 사오정       짱구

customer$sangpum[customer$irum == '홍길동']


customer_list <- split(customer$sangpum, customer$irum)
customer_list

customer_list <- sapply(customer_list, unique) # 중복 제거
customer_tran <- as(customer_list, 'transactions')
customer_tran
summary(customer_tran)

 

 - 정보 획득

itemFrequency(customer_tran) # 구매 빈도 출력
#    감자깡     맛동산       맥주     새우깡     자갈치       짱구 초코칩쿠키 크라운산도     포카칩 
# 0.5000000  0.6666667  0.3333333  0.3333333  0.3333333  0.5000000  0.1666667  0.1666667  0.1666667 
itemFrequency(customer_tran[, 1:3])
itemFrequencyPlot(customer_tran)
itemFrequencyPlot(customer_tran, support = 0.3)
itemFrequencyPlot(customer_tran, topN = 3)

 

 - 연관규칙

customer_rules <- apriori(customer_tran)
summary(customer_rules)

inspect(customer_rules)
inspect(sort(customer_rules, by = "lift")[1:5])
#     lhs                    rhs          support   confidence coverage  lift count
# [1] {크라운산도}        => {포카칩}     0.1666667 1          0.1666667 6    1    
# [2] {포카칩}            => {크라운산도} 0.1666667 1          0.1666667 6    1    
# [3] {맥주,크라운산도}   => {포카칩}     0.1666667 1          0.1666667 6    1    
# [4] {맥주,포카칩}       => {크라운산도} 0.1666667 1          0.1666667 6    1    
# [5] {새우깡,크라운산도} => {포카칩}     0.1666667 1          0.1666667 6    1    
inspect(sort(customer_rules, by = "lift", decreasing = FALSE)[1:5])
inspect(sort(customer_rules, by = "support", decreasing = FALSE)[1:5]) # 지지도

rule_subset <- subset(customer_rules, items %in% c('맛동산', '짱구'))
inspect(rule_subset)
inspect(rule_subset[1:5])
#     lhs                    rhs      support   confidence coverage  lift count
# [1] {초코칩쿠키}        => {맛동산} 0.1666667 1          0.1666667 1.5  1    
# [2] {자갈치}            => {맛동산} 0.3333333 1          0.3333333 1.5  2    
# [3] {자갈치,초코칩쿠키} => {맛동산} 0.1666667 1          0.1666667 1.5  1    
# [4] {맛동산,초코칩쿠키} => {자갈치} 0.1666667 1          0.1666667 3.0  1    
# [5] {자갈치,짱구}       => {맛동산} 0.1666667 1          0.1666667 1.5  1    

 

 - 시각화

install.packages("arulesViz")
library(arulesViz)
plot(customer_rules)
plot(customer_rules, method = "grouped")
plot(customer_rules, method = "graph") # 원 : 연관관계, 원의 크기 : support, 색상진하기 : lift
plot(customer_rules, method = "graph", control = list(type="items"))
plot(customer_rules, method = "graph", engine = 'interactive')

 


# 미국 식료품 매장의 판매자료

data("Groceries")
str(Groceries)
Groceries

gdf <- as(Groceries, 'data.frame')
head(gdf)

library(arules)
rules <- apriori(Groceries, parameter = list(supp=0.001, conf=0.8))
inspect(rules)
plot(rules, method="grouped")

rules <- apriori(Groceries, parameter = list(supp=0.001, conf=0.8, maxlen = 3))
inspect(rules)

rules <- sort(rules, decreasing = T, by='confidence')
inspect(rules)

library(arulesViz)
plot(rules, method = 'graph', control = list(type ='items'))

wmilk <- subset(rules, rhs %in% 'whole milk')
inspect(wmilk)
plot(wmilk, method = 'graph')

oveg <- subset(rules, rhs %in% 'other vegetables')
inspect(oveg)
plot(oveg, method = 'graph')

b_y <- subset(rules, lhs %in% c('butter', 'yogurt'))
inspect(b_y)
plot(b_y, method = 'graph')

23. 계층적 분집분석 : k-means

 

 - data load

data <- read.csv("testdata/exam.csv", sep = " ")
data
#     bun kor mat eng sci
# 1    1  98  95  95  90
# 2    2  65  90  60  88
# 3    3  85  53  48  50
# 4    4  65  92  62  90
# 5    5  68  72  88  73
# 6    6  90  92  90  96
# 7    7  65  70  76  80
# 8    8  60  91  62  90
# 9    9  65  70  86  76
# 10  10 100  98  97 100

 

 -  거리계산

d_data <- dist(data, method = "euclidean")
d_data
#            1         2         3         4         5         6         7         8         9
# 2  48.414874                                                                                
# 3  75.802375 57.948253                                                                      
# 4  46.861498  4.000000 60.975405                                                            
# 5  42.225585 36.755952 52.754147 37.080992                                                  
# 6  12.609520 40.112342 73.722452 38.065733 37.656341                                        
# 7  47.021272 27.294688 48.877398 28.089144 14.491377 39.522146                              
# 8  50.970580  8.366600 62.369865  6.480741 37.403208 41.533119 27.622455                    
# 9  45.332108 35.623026 53.338541 35.791060  6.480741 39.166312 10.954451 35.199432          
# 10 14.071247 53.535035 84.852814 51.205468 50.348784 14.730920 53.469618 54.571055 52.028838

 

 - 다차원 척도법

gra_data <- cmdscale(d_data)
gra_data
plot(gra_data, type = "n") # 그래프 분석 시 4개의 군집 확인 가능
text(gra_data, as.character(1:10)) # 그래프에 text 출력

data$avg <- apply(data[, 2:5], 1, mean) # 참고용 avg - data에 행으로 mean() 함수 수행
data
#    bun kor mat eng sci   avg
# 1    1  98  95  95  90 94.50
# 2    2  65  90  60  88 75.75
# 3    3  85  53  48  50 59.00
# 4    4  65  92  62  90 77.25
# 5    5  68  72  88  73 75.25
# 6    6  90  92  90  96 92.00
# 7    7  65  70  76  80 72.75
# 8    8  60  91  62  90 75.75
# 9    9  65  70  86  76 74.25
# 10  10 100  98  97 100 98.75

 

 - k-means

library(NbClust)
data_s <- scale(data[2:5])
head(data_s)
#             kor        mat        eng        sci
# [1,]  1.4199308  0.8523469  1.0794026  0.4640535
# [2,] -0.7196910  0.5167772 -0.9517313  0.3255301
# [3,]  0.5770495 -1.9664380 -1.6481201 -2.3064152
# [4,] -0.7196910  0.6510051 -0.8356665  0.4640535
# [5,] -0.5251799 -0.6912734  0.6731758 -0.7133957
# [6,]  0.9012346  0.6510051  0.7892406  0.8796238

 

 

 -  Best 군집 수 획득

nc <- NbClust::NbClust(data_s, min.nc = 2, max.nc = 5, method = "kmeans")
nc # 4 2 3 2 1 4 1 2 1 4

 

plot(table(nc$Best.nc[1,]))

 

 - model

model_kmeans <- kmeans(data[, c("bun", "avg")], 4)
model_kmeans

table(model_kmeans$cluster)
# 1 2 3 4 
# 3 1 3 3 

cluster <- model_kmeans$cluster
cluster # 2 1 4 1 1 2 3 3 3 2
kmeans_df <- cbind(cluster, data[, c("bun", "avg")])
kmeans_df
#    cluster bun   avg
# 1        4   1 94.50
# 2        1   2 75.75
# 3        3   3 59.00
# 4        1   4 77.25
# 5        1   5 75.25
# 6        4   6 92.00
# 7        2   7 72.75
# 8        2   8 75.75
# 9        2   9 74.25
# 10       4  10 98.75

str(kmeans_df)
kmeans_df <- transform(kmeans_df, cluster = as.factor(cluster)) # 범주형으로 변경
str(kmeans_df) 

 

 - clustering

library(ggplot2)
df_plot <- ggplot(data = kmeans_df, aes(x=bun, y=avg, col = cluster)) +
            geom_point(aes(shape=factor(cluster), size = 4)) +
            ggtitle("군집분석연습")
df_plot


 - 계층적 군집분석 : k -means

data("diamonds")
diamonds
# carat cut       color clarity depth table price     x     y     z
# <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#   1 0.23  Ideal     E     SI2      61.5    55   326  3.95  3.98  2.43
# 2 0.21  Premium   E     SI1      59.8    61   326  3.89  3.84  2.31
# 3 0.23  Good      E     VS1      56.9    65   327  4.05  4.07  2.31
# 4 0.290 Premium   I     VS2      62.4    58   334  4.2   4.23  2.63
# 5 0.31  Good      J     SI2      63.3    58   335  4.34  4.35  2.75
# 6 0.24  Very Good J     VVS2     62.8    57   336  3.94  3.96  2.48
# 7 0.24  Very Good I     VVS1     62.3    57   336  3.95  3.98  2.47
# 8 0.26  Very Good H     SI1      61.9    55   337  4.07  4.11  2.53
# 9 0.22  Fair      E     VS2      65.1    61   337  3.87  3.78  2.49
# 10 0.23  Very Good H     VS1      59.4    61   338  4     4.05  2.39
typeof(diamonds) # list

length(diamonds) # 10
NROW(diamonds) # 53940
t <- sample(1:nrow(diamonds), 1000)
test <- diamonds[t, ]
dim(test) # 1000   10
str(test)

mydia <- test[c("price", "carat","depth","table")]
head(mydia)

 

1. 계층적 군집분석(탐색적)

result1 <- hclust(dist(mydia), method = "ave")
result1
plot(result1, hang = -1)

2. 비계층적 군집분석(확인적)

result2 <- kmeans(mydia, 4) # 군집 수 4
result2
names(result2)

result2$cluster

mydia$cluster <- result2$cluster
head(mydia)
#     price carat depth table cluster
# <int> <dbl> <dbl> <dbl>   <int>
#   1 11322  1.7   60.1    58       1
# 2  1009  0.5   63.8    57       3
# 3  1022  0.43  62.4    60       3
# 4  4778  1.2   58.5    61       4
# 5  4111  0.81  61.6    58       4
# 6   675  0.3   61.3    60       3

cor(mydia[, -5], method = 'pearson') # 상관계수
#             price      carat       depth      table
# price  1.00000000 0.90263800 -0.01329869  0.1134894
# carat  0.90263800 1.00000000  0.02856267  0.1670910
# depth -0.01329869 0.02856267  1.00000000 -0.3562396
# table  0.11348941 0.16709103 -0.35623960  1.0000000

plot(mydia[, -5])

 

plot(mydia[c("carat", "price")], col=mydia$cluster) # price과 carat열로 군집 결과 시각화

# 중심점 표시
points(result2$centers[, c("carat", "price")], col = c(1,2,3,4), pch=8, cex=5)

22. 비계층적 군집분석 : 군집수를 정해 주고 분석을 진행
 : k-means가 가장 많이 쓰임

iris_s <- scale(iris[-5]) # scale : 표준화 함수를 이용. Species열은 제외
head(iris_s, 3)

 - 군집 개수 결정 후 k-means 모델 작성

install.packages("NbClust")
library(NbClust)
nc <- NbClust(iris_s, min.nc = 2, max.nc = 10, method="kmeans") # nc 클러스터 수

table(nc$Best.nc[1, ])
# 0  2  3  8 10 
# 2 11 11  1  1 
plot(table(nc$Best.nc[1, ]))

iris_k <- kmeans(iris_s, centers = 3, iter.max = 100)
iris_k

names(iris_k)

table(iris_k$cluster)
# 1  2  3 
# 62 50 38
plot(iris_k$cluster, col=iris_k$cluster)

iris$Species2 <- ifelse(iris$Species == 'setosa', 1, iris$Species)
head(iris, 3)
plot(iris$Species2, col=iris$Species2)

 

 - PAM

library(cluster)
iris_pam <- pam(iris_s, 3)
iris_pam
names(iris_pam)
(iris_pam$clustering)
table(iris_pam$clustering) # 교차 분할표
# 1  2  3 
# 50 52 48 
clusplot(iris_pam)

 

21. 군집분석(Clustering) : 비지도학습 - 유클리디안 거리 계산법 사용

 

x <- matrix(1:16, nrow = 4)
x
# [,1] [,2] [,3] [,4]
# [1,]    1    5    9   13
# [2,]    2    6   10   14
# [3,]    3    7   11   15
# [4,]    4    8   12   16
help(dist)
d <- dist(x, method = "euclidean")
d
#   1 2 3
# 2 2    
# 3 4 2  
# 4 6 4 2
plot(d)
text(d, c(LETTERS[1:6]))

txt1 <- read.csv("testdata/cluster_ex.csv")
txt1
# irum kor eng
# 1 홍길동  80  90
# 2 이기자  70  40
# 3 유별나  65  75
# 4 강나루  85  65
# 5 전속력  95  87
plot(txt1[, c(2:3)],
     xlab ='국어',
     ylab ='영어',
     xlim = c(30, 100),
     ylim = c(30, 100),
     main = '학생점수')

text(txt1[, 2], txt1[, 3], labels = abbreviate(rownames(txt1)), cex = 0.8, pos = 1, col = "blue")
text(txt1[, 2], txt1[, 3], labels = txt1[,1], cex = 0.8, pos = 2, col = "red")

dist_m <- dist(txt1[c(1:2), c(2:3)], method = "manhattan")
dist_m
# 1
# 2 60

dist_e <- dist(txt1[c(1:2), c(2:3)], method = "euclidean")
dist_e
# 1
# 2 50.9902

 - 계층적 군집분석

x <- c(1,2,2,4,5)
y <- c(1,1,4,3,5)
xy <- data.frame(cbind(x,y))
plot(xy,
     xlab ='x',
     ylab ='y',
     xlim = c(0, 6),
     ylim = c(0, 6),
     main = '응집적 군집분석')

text(xy[, 1], xy[, 2], labels = abbreviate(rownames(xy)),
     cex = 0.8, pos = 1, col = "blue")
abline(v=c(3), col = 'gray', lty=2)
abline(h=c(3), col = 'gray', lty=2)

 

 - 유클리디안 거리 계산법

dist(xy, method = 'euclidean') ^ 2
#    1  2  3  4
# 2  1         
# 3 10  9      
# 4 13  8  5   
# 5 32 25 10  5

 

 - Dendrogram으로 출력

hc_sl <- hclust(dist(xy) ^ 2, method = "single") # 최단거리법
hc_sl
plot(hc_sl, hang = -1)

hc_co <- hclust(dist(xy) ^ 2, method = "complete") # 완전(최장) 거리법
hc_co
plot(hc_co, hang = -1)

hc_av <- hclust(dist(xy) ^ 2, method = "average") # 평균 거리법
hc_av
plot(hc_av, hang = -1)

par(oma = c(3, 0, 1, 0))
par(mfrow = c(1,3))
plot(hc_sl, hang = -1)
plot(hc_co, hang = -1)
plot(hc_av, hang = -1)


 - 중학생 신체검사 결과

body <- read.csv("testdata/bodycheck.csv")
body
#      번호 악력 신장 체중 안경유무
# 1     1   28  146   34        1
# 2     2   46  169   57        2
# 3     3   39  160   48        2
# 4     4   25  156   38        1
# 5     5   34  161   47        1
# 6     6   29  168   50        1
# 7     7   38  154   54        2
# 8     8   23  153   40        1
# 9     9   42  160   62        2
# 10   10   27  152   39        1
# 11   11   35  155   46        1
# 12   12   39  154   54        2
# 13   13   38  157   57        2
# 14   14   32  162   53        2
# 15   15   25  142   32        1
dim(body)
head(body, 2)

d <- dist(body[, -1]) # 거리계산
d

hc <- hclust(d, method = "complete")
hc
# Cluster method   : complete 
# Distance         : euclidean 
# Number of objects: 15 

plot(hc, hang=-1) # hang=-1 정렬
rect.hclust(hc, k=3, border = "red")

 -  군집별 특징

g1 <- subset(body, 번호 == 10 |번호 == 4 |번호 == 8 |번호 == 1 |번호 == 15)
g2 <- subset(body, 번호 == 11 |번호 == 3 |번호 == 5 |번호 == 6 |번호 == 14)
g3 <- subset(body, 번호 == 2 |번호 == 9 |번호 == 13 |번호 == 7 |번호 == 12)

g1[2:5]
g2[2:5]
g3[2:5]

summary(g1[2:5])
summary(g2[2:5])
summary(g3[2:5])

20. Neural Network : MLP - 역전파 지원 (deep learning)

 

- 라이브러리 load

install.packages("neuralnet")
library(neuralnet)

 

 - 데이터

head(iris, 2)
unique(iris$Species) # setosa     versicolor virginica 
iris$Species2[iris$Species == 'setosa'] <- 1
iris$Species2[iris$Species == 'versicolor'] <- 2
iris$Species2[iris$Species == 'virginica'] <- 3
iris$Species <- NULL
head(iris, 2)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species2
# 1          5.1         3.5          1.4         0.2        1
# 2          4.9         3.0          1.4         0.2        1

 

 - train, test

set.seed(42)
idx <- sample(1:nrow(iris), nrow(iris)*0.7)
train <- iris[idx, ]
test <- iris[-idx, ]

 

 - 정규화

normal_func <- function(x){
  return ((x - min(x) / max(x) - min(x)))
}
normal_func(c(1,2,3))

train_nor <- as.data.frame(lapply(train, normal_func))
head(train_nor, 3)
# Sepal.Length Sepal.Width Petal.Length Petal.Width   Species2
# 1    0.4556962   1.2454545    0.2358209        0.06 -0.3333333
# 2    0.7556962   0.4454545    2.3358209        1.16  0.6666667
# 3    1.2556962   0.3454545    3.4358209        1.06  0.6666667
test_nor <- as.data.frame(lapply(test, normal_func))
head(test_nor, 3)
# Sepal.Length Sepal.Width Petal.Length Petal.Width   Species2
# 1   -0.3714286   0.6210526    0.2550725        0.02 -0.3333333
# 2    0.4285714   0.9210526    0.3550725       -0.08 -0.3333333
# 3   -0.1714286   0.6210526    0.4550725       -0.08 -0.3333333

 

- 모델생성

help("neuralnet")
model <- neuralnet(Species2 ~ Sepal.Length+Sepal.Width+Petal.Length+Petal.Width,
                   data=train_nor, hidden = 1) # 레이블, 피쳐
model
plot(model)

 - 모델 성능평가 : predict() x compute() 사용

model_result <- compute(model, test_nor[c(1:4)])
names(model_result) # neurons    net.result
model_result$neurons
head(model_result$net.result, 3) # 예측값
# [,1]
# [1,] -0.2967633
# [2,] -0.3408647
# [3,] -0.3024315
head(test_nor$Species2, 3) # 실제값

 

 -  상관관계 확인 후 분류 정확도 출력

cor(model_result$net.result, test_nor$Species2) # 0.9762009

pred_weights <- model_result$net.result

func <- function(x){
  if(x >= 1)
    return ('virginica')
  else if(x >= 0)
    return ('versicolor')
  else
    return ('setosa')
}
func(-1)
func(2)
func(0.2)
sp <- apply(pred_weights, 1, func)
sp
t <- table(sp, test_nor$Species2)
# sp           -0.333333333333333 0.666666666666667 1.66666666666667
# setosa                     12                 0                0
# versicolor                  0                12                0
# virginica                   0                 3               18
sum(diag(t)) / nrow(test_nor)

 

 - 모델 파라미터 변경

model2 <- neuralnet(Species2 ~ Sepal.Length+Sepal.Width+Petal.Length+Petal.Width,
                   data=train_nor, hidden = 5, algorithm = "backprop", learningrate = 0.01)
# learningrate : 학습률
model2
plot(model2)

 


 - 입력값을 정규화 하지않고 모델 작성

data(iris)
head(iris, 2)
unique(iris$Species)
set.seed(123)
idx <- sample(1:nrow(iris), nrow(iris)*0.7)
train <- iris[idx, ]
test <- iris[-idx, ]

train <- cbind(train, train$Species == 'setosa')
train <- cbind(train, train$Species == 'versicolor')
train <- cbind(train, train$Species == 'virginica')
train
names(train)[6:8] <- c('setosa', 'versicolor', 'virginica')
head(train, 2)

model <- neuralnet(setosa+versicolor+virginica ~ Sepal.Length+Sepal.Width+Petal.Length+Petal.Width,
                   data=train, hidden = 3)
plot(model)

 

pred <- compute(model, test[-5])
pred_weight <- pred$net.result
idx <- apply(pred_weight, 1, which.max) # 행에서 가장 큰값을 반환
idx
# 1   2   3   5  11  18  19  28  29  33  36  45  48  49  55  56  57  58  59  61  62  65  66  68  70  77 
# 1   1   1   1   1   1   1   1   1   1   1   1   1   1   2   2   2   2   2   2   2   2   2   2   2   2 
# 83  84  94  95  98 100 101 104 105 111 113 116 125 131 133 135 140 141 145 
# 2   3   2   2   2   2   3   3   3   3   3   3   3   3   3   3   3   3   3 
c('setosa', 'versicolor', 'virginica')[1]

pred <- c('setosa', 'versicolor', 'virginica')[idx]
pred
# [1] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"     "setosa"     "setosa"    
# [8] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"     "setosa"     "setosa"    
# [15] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
# [22] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor" "versicolor" "virginica" 
# [29] "versicolor" "versicolor" "versicolor" "versicolor" "virginica"  "virginica"  "virginica" 
# [36] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"  "virginica"  "virginica" 
# [43] "virginica"  "virginica"  "virginica" 
table(pred, test$Species)
# pred         setosa versicolor virginica
# setosa         14          0         0
# versicolor      0         17         0
# virginica       0          1        13

 

 - 새로운 값으로 예측

my <- test
my <- my[c(1:3), ]
my <- edit(my)
my
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1            7           1            1           1  setosa
# 2            7           5            3           1  setosa
# 3            2           3            4           5  setosa

mycomp <- compute(model, my[-5])
mypred <- mycomp$net.result
idx2 <- apply(mypred, 1, which.max)
idx2
pred2 <- c('setosa', 'versicolor', 'virginica')[idx2]
pred2 # versicolor setosa virginica

'BACK END > R' 카테고리의 다른 글

[R] R 정리 22 - 비계층적 군집분석  (0) 2021.02.04
[R] R 정리 21 - 계층적 군집분석  (0) 2021.02.04
[R] R 정리 19 - ANN(인공 신경망)  (0) 2021.02.03
[R] R 정리 18 - svm, knn  (0) 2021.02.02
[R] R 정리 17 - Naive Bayes  (0) 2021.02.02

19. ANN (Artificial Neural Network)

 

 1) 논리 회로 처리

 - 라이브러리 read

install.packages("nnet")
library(nnet)

 

 - 학습 모델 작성

input <- matrix(c(0,0,1,1,0,1,0,1), ncol=2)
input
# [,1] [,2]
# [1,]    0    0
# [2,]    0    1
# [3,]    1    0
# [4,]    1    1
output <- matrix(c(0,0,0,1)) # and
output
# [,1]
# [1,]    0
# [2,]    0
# [3,]    0
# [4,]    1
output <- matrix(c(0,1,1,1)) # or
output <- matrix(c(0,1,1,0)) # xor - size가 1로는 비선형이라 안됨.

ann <- nnet(input, output, maxit = 10000, size = 3, decay = 0.001)
# maxit : 학습 횟수, size: node수, decay: 학습률
ann

 - 결과 확인

result <- predict(ann, input) # 예측모델 생성
result
#             [,1]
# [1,] 0.002724474
# [2,] 0.070330761
# [3,] 0.070331671
# [4,] 0.897269791
ifelse(result>0.5, 1, 0) # 0.5 이상일경우 1 아닐경우 0으로 판단
#      [,1]
# [1,]    0
# [2,]    0
# [3,]    0
# [4,]    1

df <- data.frame(
  x1 = c(1:6),
  x2 = c(6:1),
  y  = factor(c('n','n','n','y','y','y'))
)
df
# x1 x2 y
# 1  1  6 n
# 2  2  5 n
# 3  3  4 n
# 4  4  3 y
# 5  5  2 y
# 6  6  1 y
str(df)
model_net1 <- nnet(y ~ ., df, size = 1)
model_net1
# a 2-1-1 network with 5 weights
# inputs: x1 x2 
# output(s): y 
# options were - entropy fitting
summary(model_net1)

model_net2 <- nnet(y ~ ., df, size = 2)
model_net2
# a 2-2-1 network with 9 weights
# inputs: x1 x2 
# output(s): y 
# options were - entropy fitting
summary(model_net2)
install.packages("devtools")
library(devtools)
source_url('https://gist.githubusercontent.com/fawda123/7471137/raw/466c1474d0a505ff044412703516c34f1a4684a5/nnet_plot_update.r')
par(mar=c(1,1,1,1))
plot.nnet(summary(model_net1))

plot.nnet(summary(model_net2))

# predict
model_net2$fitted.values
predict(model_net2, df)

pred <- predict(model_net2, df, type='class')
pred
table(pred, df$y)
# pred n y
# n 3 0
# y 0 3

# iris dataset 사용
data(iris)
set.seed(123)
idx <- sample(1:nrow(iris), nrow(iris)*0.7)
train <- iris[idx, ]
test <- iris[-idx, ]

# node 1개 사용한 경우
model_iris1 = nnet::nnet(Species ~ ., train, size = 1)
model_iris1
# a 4-1-3 network with 11 weights
# inputs: Sepal.Length Sepal.Width Petal.Length Petal.Width 
# output(s): Species 
# options were - softmax modelling 
summary(model_iris1)  # weights 11로 weights가 클수록 정교한 분석가능
plot.nnet(summary(model_iris1))

# node 3개 사용한 경우
model_iris3 = nnet::nnet(Species ~ ., train, size = 3)
summary(model_iris3)
plot.nnet(summary(model_iris3))

# 분류평가
pred1 <- predict(model_iris1, test, type="class")
t1 <- table(pred1, test$Species)
sum(diag(t1))/nrow(test) # 0.9777778

pred3 <- predict(model_iris3, test, type="class")
t3 <- table(pred3, test$Species)
sum(diag(t3))/nrow(test)

'BACK END > R' 카테고리의 다른 글

[R] R 정리 21 - 계층적 군집분석  (0) 2021.02.04
[R] R 정리 20 - MLP(deep learning)  (0) 2021.02.04
[R] R 정리 18 - svm, knn  (0) 2021.02.02
[R] R 정리 17 - Naive Bayes  (0) 2021.02.02
[R] R 정리 16 - Random Forest  (0) 2021.02.02

+ Recent posts

1234567···9