https://wikidocs.net/16074

 

위키독스

온라인 책을 제작 공유하는 플랫폼 서비스

wikidocs.net

1. 정적메소드(@classmethod와 @staticmethod)

  • 정적메소드라 함은 클래스에서 직접 접근할 수 있는 메소드입니다.
  • 파이썬에서는 클래스에서 직접 접근할 수 있는 메소드가 두가지가 있습니다.staticmethod와 classmethod 입니다.
  • 하지만 파이썬에서는 다른언어와는 다르게 정적메소드임에도 불구하고 인스턴스에서도 접근이 가능합니다. 이 차이에 유의해야합니다.
  • 에디터에서 static_method.py파일을 작성합니다.
  • 인스턴스 메소드는 첫번째 인자로 객체 자신 self자신을 입력합니다.
  • classmethod는 첫번째 인자로 클래스를 입력합니다.
  • staticmethod는 특별히 추가되는 인자가 없습니다.
class hello:
    t = '내가 상속해 줬어'

    @classmethod
    def calc(cls):
        return cls.t

class hello_2(hello):
    t = '나는 상속 받았어'

print(hello_2.calc())
#결과
내가 상속해 줬어

@staticmethod

즉, 스태틱 메서드는 그냥 클래스 바깥에 정의된 일반 함수와 완전히 동일하게 동작한다.

다만, 특정 클래스와 보다 밀접한 관계가 있다는 것을 나타내기위해,

혹은 조금이라도 코드를 줄여 간단하게 표현하기 위해 @staticmethod 키워드를 사용해 정의하는 것

 

https://suwoni-codelab.com/python%20%EA%B8%B0%EB%B3%B8/2018/03/11/Python-Basic-class-staticmethod/

 

Python(파이썬) 기본 - 43. class 정리 - 정적메소드 @classmethod와 @staticmethod의 정리

Python에서 class에서 정적메소드를 정리합니다.

suwoni-codelab.com

 

@property 사용하기

접근제어자(Access Modifier)

접근 제어자에는 public , private , protected , default 가 있다.
파이썬은 다른언어와 달리 접근 제어자가 없고 작명법으로 접근을 제어할 수 있다. 파이썬에서의 작명법은 아래와 같다.

  • public → 접두사에 아무 밑줄이 없다.
  • private → 접두사에 두개의 밑줄(__)을 적용
  • protected → 접두사에 한개의 밑줄(_) 을 적용
class Example :
    def __init__(self):
        pass
    def public(self): 
        print('public')
    def _protected(self):
        print('protected')
    def __private(self):
        print('private')

Get, Set

다른 언어에서 private 를 사용한 속성값이 있을때 그것을 가져오기 위해서는 get , set 메소드를 쓴다. 파이썬에서는 다음과 같이 사용할 수 있다.

class Person :
    def __init__(self):
        self.__name = 'hong'
    def get_name(self): 
        return self.__name
    def set_name(self, name):
        self.__name = name

 

위와 같이 get , set 메소드를 만들면 함수가 너무 많아지고 복잡해진다.

@property

파이썬에서는 @property 데코레이터를 이용하여 위의 get , set 메소드보다 더욱 직관적으로 표현이 가능하다.

class Person :
    def __init__(self):
        self.__name = 'hong'
        
    @property
    def name(self): 
        return self.__name
        
    @name.setter
    def name(self, name):
        self.__name = name
        
person = Person()
print(person.name)    # hong

person.name = 'park'
print(person.name)    # park

get의 역할은 property , set의 역할은 setter가 한다. property 가 setter 보다 윗줄에 사용되어야 한다.

https://medium.com/@hckcksrl/python-property-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-89eb0f0e2e56

쿠키와 세션 다루기

쿠키: 클라이언트의 PC에 텍스트 파일 형태로 저장되는 것으로 일반적으로는 시간이 지나면 소멸

자동 로그인, 팝업 창에서 "오늘은 이 창을 더 이상 보지 않기" 등의 기능을 클라이언트에 저장해놓기 위해 사용

 

쿠키

웹 페이지에서 폼을 전송받으며, 클라이언트에 쿠키를 넘겨주는 코드

#routes.py

from flask import Flask, render_template, request
app = Flask(__name__)

@app.route('/')
def index():
   return render_template('index.html')

if __name__ == '__main__':
   app.run(debug = True)

 

#index.html
 <form action = "/setcookie" method = "POST">
         <p><h3>Enter userID</h3></p>
         <p><input type = 'text' name = 'nm'/></p>
         <p><input type = 'submit' value = 'Login'/></p>
 </form>

 

# routes.py

from flask import Flask, render_template, request, make_response

app = Flask(__name__)


# 가장 먼저 플라스크 객체를 만들어놓아야 한다.

@app.route('/')
def index():
    return render_template('index.html')  # 자바의 welcomlist와 같이 만들어지는 부분

#해당 폼은 /setcookie URL로 전송되는데, 이제 그 쪽을 짜보자.
# 폼으로 데이터를 입력받을 경우, POST 메소드로 /setcookie에 오게 된다.
@app.route('/setcookie', methods=['POST', 'GET'])
def setcookie():
    if request.method == 'POST':
        user = request.form['nm']

   #make_response() 함수는 사용자에게 반환할 뷰 함수를 생성한 후, 그대로 묶어두는 역할
   #뷰를 보여주기 전에 쿠키를 생성해야 하므로
    resp = make_response("Cookie Setting Complete")
    #set_cookie() 함수를 사용해 쿠키를 생성하였다.
    # 쿠키의 이름은 'userID'이며, 내용에는 아까 폼으로 입력된 문자열이 들어간다.
    # 그 후 해당 뷰 객체를 반환하여 보여주게 하였다.
    resp.set_cookie('userID', user)

    return resp

# 등록된 쿠키를 확인(http://127.0.0.1:5000/getcookie)
@app.route('/getcookie')
def getcookie():
   name = request.cookies.get('userID')
   return '<h1>welcome '+name+'</h1>'


if __name__ == '__main__':
    app.run(debug=True)

 

세션

세션과 관련된 데이터는 서버에 저장된다. 서버에서 관리할 수 있다는 점에서 안전성이 좋아서 보통 로그인 관련으로 사용되고 있다. 플라스크에서 세션은 딕셔너리의 형태로 저장되며 키를 통해 해당 값을 불러올 수 있다

# routes.py

from flask import Flask, request, session, redirect, url_for
app = Flask(__name__)
app.secret_key = 'any random string'

# 가장 먼저 플라스크 객체를 만들어놓아야 한다.
@app.route('/')
def index():
   if 'username' in session:
    	username = session['username']
    	return 'Logged in as ' + username + '<br>' + \
    	"<b><a href = '/logout'>click here to log out</a></b>"

   return "You are not logged in <br><a href = '/login'></b>" + \
      "click here to log in</b></a>"


if __name__ == '__main__':
    app.run(debug=True)

조건문으로 Flask 세션 정보 안에 'username' 이라는 세션 정보가 있냐 없냐에 따라서 로그인을 했는지 안했는지를 판단

# routes.py

from flask import Flask, request, session, redirect, url_for
app = Flask(__name__)
app.secret_key = 'any random string'

# 가장 먼저 플라스크 객체를 만들어놓아야 한다.
@app.route('/')
def index():
   if 'username' in session:
    	username = session['username']
    	return 'Logged in as ' + username + '<br>' + \
    	"<b><a href = '/logout'>click here to log out</a></b>"

   return "You are not logged in <br><a href = '/login'></b>" + \
      "click here to log in</b></a>"

#로그인으로 처음엔 get 메소드로 요청 되므로 로그인을 하기 위한 폼을 전송(폼을 통한 전송으로 post)
@app.route('/login', methods=['GET', 'POST'])
def login():
   if request.method == 'POST':
      #username이라는 세션을 생성하여 입력받은 폼의 데이터를 세션에 저장
      session['username'] = request.form['username']
      # 처음페이지로 리다이렉트
      return redirect(url_for('index'))
   return '''

   <form action = "" method = "post">
      <p><input type = text name = username /></p>
      <p><input type = submit value = Login /></p>
   </form>

   '''

#세션 제거
@app.route('/logout')
def logout():
   # remove the username from the session if it is there
   session.pop('username', None)
   return redirect(url_for('index'))

'''
#세션의 유효기간을 직접 설정
from datetime import timedelta
from flask import session, app

@app.before_request
def make_session_permanent():
    session.permanent = True
    app.permanent_session_lifetime = timedelta(minutes=5)
'''
if __name__ == '__main__':
    app.run(debug=True)

 

 

리다이렉션과 에러처리

 

리다이렉션

특정 URL로 강제로 이동시키고 싶을 때

# routes.py

from flask import Flask, render_template, request, make_response
from flask import session, redirect, url_for
from flask import app
from datetime import timedelta

app = Flask(__name__)
# 가장 먼저 플라스크 객체를 만들어놓아야 한다.
app.secret_key = 'any random string'


@app.route('/')
def index():
    if 'username' in session:
        username = session['username']
        return 'logged in as' + username + "<b><a href='/logout'>click here to log out</a></b>"
    return "you are not logged in <br><a href='/loginForm'></b>" + "click here to log in</b></a>"


@app.route('/setcookie', methods=['POST', 'GET'])  # 쿠키저장
def setcookie():
    if request.method == 'POST':
        user = request.form['nm']

    resp = make_response("Cookie Setting Complete")
    resp.set_cookie('userID', user)  # 쿠키저장

    return resp


@app.route('/getcookie')
def getcookie():
    name = request.cookies.get('userID')  # 쿠키가져오기
    return '<h1>welcome' + name + '</h1>'


@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST' and request.form['username'] == 'admin':  # post이고 admin이면 adminname이란변수에 대입
        adminname = request.form['username']
        return redirect(url_for('success'))  # redirect() 페이지 이동함수
    return redirect(url_for('index'))


@app.route('/success')
def success():
    return '관리자 로그인 성공'


@app.route('/loginForm', methods=['GET', 'POST'])
def loginForm():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''

   <form action = "/login" method = "post">
      <p><input type = text name = username /></p>
      <p><input type = submit value = Login /></p>
   </form>

   '''


@app.route('/logout')
def logout():
    session.pop('username', None)
    return redirect(url_for('index'))


# 요청이 들어오기 전에 세션수명만들어야함
@app.before_request
def make_session_permanent():
    session.permanent = True  # False면 31동안 보관
    app.permanent_session_lifetime = timedelta(minutes=1)  # 수명을 1분유지


if __name__ == '__main__':
    app.run(debug=True)

 

 

에러

# routes.py

from flask import Flask, render_template, request, make_response
from flask import session, redirect, url_for, abort
from flask import app
from datetime import timedelta

app = Flask(__name__)
# 가장 먼저 플라스크 객체를 만들어놓아야 한다.
app.secret_key = 'any random string'


@app.route('/')
def index():
    if 'username' in session:
        username = session['username']
        return 'logged in as' + username + "<b><a href='/logout'>click here to log out</a></b>"
    return "you are not logged in <br><a href='/loginForm'></b>" + "click here to log in</b></a>"


@app.route('/setcookie', methods=['POST', 'GET'])  # 쿠키저장
def setcookie():
    if request.method == 'POST':
        user = request.form['nm']

    resp = make_response("Cookie Setting Complete")
    resp.set_cookie('userID', user)  # 쿠키저장

    return resp


@app.route('/getcookie')
def getcookie():
    name = request.cookies.get('userID')  # 쿠키가져오기
    return '<h1>welcome' + name + '</h1>'

# abort(): 오류 코드와 함께 강제로 페이지를 중지시킬 수 있는 함

@app.route('/login',methods = ['POST', 'GET'])
def login():
   if request.method == 'POST':
      if request.form['username'] == 'admin' :
         return redirect(url_for('success'))
      else:
         abort(401)
   else:
      return redirect(url_for('index'))

@app.route('/success')
def success():
    return '관리자 로그인 성공'


@app.route('/loginForm', methods=['GET', 'POST'])
def loginForm():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''

   <form action = "/login" method = "post">
      <p><input type = text name = username /></p>
      <p><input type = submit value = Login /></p>
   </form>

   '''


@app.route('/logout')
def logout():
    session.pop('username', None)
    return redirect(url_for('index'))


# 요청이 들어오기 전에 세션수명만들어야함
@app.before_request
def make_session_permanent():
    session.permanent = True  # False면 31동안 보관
    app.permanent_session_lifetime = timedelta(minutes=1)  # 수명을 1분유지


if __name__ == '__main__':
    app.run(debug=True)

 

 

# routes.py

from flask import Flask, render_template, request, make_response
from flask import session, redirect, url_for, abort
from flask import app
from datetime import timedelta

app = Flask(__name__)
# 가장 먼저 플라스크 객체를 만들어놓아야 한다.
app.secret_key = 'any random string'


@app.route('/')
def index():
    if 'username' in session:
        username = session['username']
        return 'logged in as' + username + "<b><a href='/logout'>click here to log out</a></b>"
    return "you are not logged in <br><a href='/loginForm'></b>" + "click here to log in</b></a>"


@app.route('/setcookie', methods=['POST', 'GET'])  # 쿠키저장
def setcookie():
    if request.method == 'POST':
        user = request.form['nm']

    resp = make_response("Cookie Setting Complete")
    resp.set_cookie('userID', user)  # 쿠키저장

    return resp


@app.route('/getcookie')
def getcookie():
    name = request.cookies.get('userID')  # 쿠키가져오기
    return '<h1>welcome' + name + '</h1>'

# abort(): 오류 코드와 함께 강제로 페이지를 중지시킬 수 있는 함
@app.route('/login',methods = ['POST', 'GET'])
def login():
   if request.method == 'POST':
      if request.form['username'] == 'admin' :
         return redirect(url_for('success'))
      else:
         abort(401)
   else:
      return redirect(url_for('index'))

#각 에러에 한해서 자신이 만든 페이지를 뜨게 하고 싶다면
@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404


@app.route('/success')
def success():
    return '관리자 로그인 성공'


@app.route('/loginForm', methods=['GET', 'POST'])
def loginForm():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''

   <form action = "/login" method = "post">
      <p><input type = text name = username /></p>
      <p><input type = submit value = Login /></p>
   </form>

   '''


@app.route('/logout')
def logout():
    session.pop('username', None)
    return redirect(url_for('index'))


# 요청이 들어오기 전에 세션수명만들어야함
@app.before_request
def make_session_permanent():
    session.permanent = True  # False면 31동안 보관
    app.permanent_session_lifetime = timedelta(minutes=1)  # 수명을 1분유지


if __name__ == '__main__':
    app.run(debug=True)

 

파일 업로드하기

 

from flask import Flask, render_template, request
from werkzeug.utils import secure_filename

app = Flask(__name__)


@app.route('/upload')
def load_file():
    return render_template('upload.html')

@app.route('/uploader', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
       #f = request.files['file'] :  request 객체의 'file'이라는 이름의 폼으로 전송된 파일에 해당
        f = request.files['file']
        # f.save() : 말 그대로 해당 파일 객체를 저장하는 메소드
        #secure_filename(f.filename): 해당 파일명을 보호하기 위한 메소드이다.
        # 해당 파일이 실제 시스템에 저장되기 전에 파일명을 보호하기 위한 함수
        f.save(secure_filename(f.filename))
        return 'file uploaded successfully'

if __name__ == '__main__':
    app.run(debug=True)

 

플라스크

http://blog.naver.com/PostView.nhn?blogId=shino1025&logNo=221345904588&categoryNo=0&parentCategoryNo=0&viewDate=¤tPage=1&postListTopCurrentPage=1&from=postView&userTopListOpen=true&userTopListCount=30&userTopListManageOpen=false&userTopListCurrentPage=1

 

[Flask 입문] 플라스크로 웹 프로그래밍 입문하기

이번 포스팅을 시작으로 필자는 파이썬의 웹 개발 프레임워크인 Flask에 대해 공부한 내용을 정리해볼까 ...

blog.naver.com

플라스크는 파이썬으로 작성된 웹 개발 도구로 마이크로 프레임워크라고 부른다.

그이유는 플라스트로 웹 개발을 하는데에 특별한 도구나 라이브러리가 전혀 필요없기 때문에

 

플라스크는 파이썬을 알고 있다면 매우 배우기 쉽고 짮은 시간안에 퓁 어플리케이션 하나를 뚝딱 만들 ㅅ플라스크는 파이썬으로 작성된 웹 개발 도구로 마이크로 프레임워크라고도 부른다.

그 이유는 플라스크로 웹 개발을 하는 데에 특별한 도구나 라이브러리가 전혀 필요 없기 때문에


플라스크는 파이썬을 알고 있다면 매우 배우기 쉽고,

짧은 시간 안에 웹 어플리케이션 하나를 뚝딱 만들어낼 수 있다.


물론 너무나 간단하다 보니,

보다 복잡한 기능의 구축에 있어선 다른 프레임워크에 비해 효율이 떨어졌지만 꾸준히 업데이트가 되고 있어 큰 걱정은 필요 없다.


가상환경 구축하기

폴더 안에 a로 시작하는 모든 파일을 찾아준다.

dir test.* - >파일명이

dir_ a*t*.*/s -> 서브폴더까지 전부 찾아달라고 요청 할 때. 
dir_a*.* : a로 시작하는 모든 파일

dir_test.* : 파일명이 test인 모든 애들

dir_*t*.* : t를 포함하는 모든 것들

dir_*t*.*/s : 서브폴더까지 전부다 찾아달라고 요청

dir_*t*.*/s/p : 서브폴더 / 서브서브폴더 등 페이지를 끊어서 볼 수 있다.

리눅스에서는 ls 가 dir 명령어를 대체한다.

 

~.bat -> 일괄처리 시켜주는 배치 파일

 

type 파일명.bat -> 파일의 내용을 볼 수 있다.

 

 

bin 폴더 안에는 javac.exe/java.exe 가 있음

환경변수를 잡아주는 이유 :  어떤 폴더에서 작업을 하든 운영체제가 알아서 위 실행 파일을 실행 처리를 시키기 위해서.

Java 가 컴파일 되기 위해 필요한 것은 javac.exe
실행할 때 필요한 것 : java.exe
javac.exe, java.exe를 가지고 있는 폴더명 : bin(binary) ( 환경변수 잡아줄 때 bin 폴더까지 잡는다 - 이 폴더 안에 실행파일 있어서 )
환경변수를 설정하는 이유 : 실행파일들의 위치와 내가 작업하는 폴더의 위치가 다르기 때문에 실행파일이 있는 위치를 잡아놓고자 함(javac, java.exe)

* 환경변수의 종류

1) 사용자용 ( 여기에 걸어두면 자동으로 잡아주지 않는다. )
2) 시스템용(우리가 잡은 용도는 모두 시스템용) - 혼자서 컴퓨터를 사용하고 개발 외에는 사용하지 않기 때문

 

cmd창에서 작업 폴더를 만들어줬음

 

플라스크를 설치 해줌

 

메모장에 아래 내용을 저장
파일을 실행시켜서  http://127.0.0.1:5000/로 접속
접속 하게 되면 사진과 같이 나옴

 app = Flask(__name__)

가장 먼저 전역에서 Flask 클래스 객체를 선언하였다.
해당 app 객체를 통해 플라스크를 사용할 수 있게 된다.
__name__의 경우, 해당 코드를 직접 실행시킬 경우, "__main__"이라는 문자열이 들어온다.

@app.route('/')

데코레이터를 사용하여 hello_world 함수를 wrapping 되었음을 알 수 있다.
이 데코레이터를 통해 웹으로 접근한 사용자가 어떤 URL에 따라 어떤 함수를 실행시켜야 할지 정해주거나
위의 예제의 경우'/'(wmr, 메인페이지)가 URL 파라미터인 셈이다.

app.run()
app의 run()메소드를 통하여 플라스크 웹 어플리케이션을 실행 할 수 있다.
아무런 인자도 넘겨주지 않을 경우,
적당히 포트를 잡고 127.0.0.1로 실행 시키게 된다.
주로 사용하는 인자는 다음과 같다.

port(ex:port=5000)
수동적으로 특정 포트 번호를 잡고 싶다면 이걸 사용하자.

host(ex : 0.0.0.0, 127.0.0.1, ...)
해당 웹 서비스로 접근을 허용하는 IP 혹은 Domain을 적을 수 있다. 
예를 들어 (127.0.0.1)를 보내면 웹 서버를 실행시킨 해당 PC 외에는 접속이 불가능하지만,
모든 IP를 뜻하는 (0.0.0.0)을 보내면 외부에서도 접속이 가능해지는 셈이다.
# routes.py
from flask import Flask
app = Flask(__name__)

# ex) user/IML, user/ash123
@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username

# 자기 자신이 실행 될 때 아래 if문이 실행 된다.
if __name__ == '__main__':
    app.run()

값을 받아서 보여준다. str반환

 

# routes.py
from flask import Flask
app = Flask(__name__)

# ex) post/123 int 반환
@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id

# 자기 자신이 실행 될 때 아래 if문이 실행 된다.
if __name__ == '__main__':
    app.run()

값을 받아서 int로 반환

# routes.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

# ex) user/IML, user/ash123
@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username

# ex) post/123 
@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id


# 자기 자신이 실행될 때 실행
if __name__ == '__main__':
    app.run()
    
    
   # 같은 파일에 넣어도 한번에 실행이 가능하다.
인자로 받을 변수 규칙에는 string(%s), Int(%d), float(%f) 등이 있으며 아무것도 적지 않을 경우,
자동으로 string 형태로 인자를 주게 된다.
또한, 특정 함수 1개에 복수의 데코레이터를 덮어씌울 수 있다. 
예를 들어 아래처럼 2개의 데코레이터를 씌워준 후, 
기본 함수 인자 설정을 None으로 해주면 인자가 없을 경우 첫 번째 URL이고, 
있을 경우 2번 째 URL이 되는 것이다

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
// Code


------------------------
# routes.py
from flask import Flask
app = Flask(__name__)

# ex) user/IML, user/ash123 str 반환
@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username

# ex) post/123 int 반환
@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id

#복수의 데코레이터
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return 'User %s' % name

# 자기 자신이 실행 될 때 아래 if문이 실행 된다.
if __name__ == '__main__':
    app.run()

 

웹 페이지 소스를 보는 방법

view-source:소스를 보고 싶은 URL

view-source:https://www.naver.com/

 

NAVER

이게 오리지널이야, 재즈 힙합의 원곡을 찾아서 2020.05.04 케이팝이 세계를 만날 때 2020.04.29 이주의 디깅 #56 EXO 2020.04.28 팝 음악계 역주행 대표곡들 2020.04.25 키아나 르데와 함께한 음악가들 2020.04.2

www.naver.com

 

 

파이썬과 HTML

 

Templates

 

 

jinja2 문법

# routes.py
from flask import Flask
app = Flask(__name__)

#routes.py
from flask import Flask, render_template
app = Flask(__name__)

#ex)hello/IML
@app.route('/hello/<user>')
def hello_name(user):
   return render_template('hello.html', name = user)

if __name__ == '__main__':
   app.run(debug = True)

#HTML에 값을 던져 준다.

플라스크의 경우, HTML 문서를 보관하기 위한 디렉터리를 따로 만들어주어야 
해당 파일들을 인식할 수 있는데, 해당 폴더의 위치는 반드시 플라스크를 실행시키는 코드와 
같은 경로이며, templates라는 이름이여야 한다. (바꿀 수는 있지만 굳이 바꿀 이유는 없음)


 

HTML에 값이 전달 된다.

 

https://snacky.tistory.com/7

 

플라스크(Flask) ; Jinja2 템플릿 엔진 기본문법

플라스크에서는 템플릿을 이용하여 html을 구성한다는 설명을 지난 포스팅에서 했었습니다. 그렇다면 이 템플릿을 해석하는 템플릿 엔진인 Jinja2의 기본적인 문법에 대해서도 조금 알아야겠다 싶어 포스팅합니다...

snacky.tistory.com

{{...}} :  변수나 표현식의 결과를 출력하는 구분자

{%...%} : if문이나 for문 같은 제어문을 할당하는 구분자

 

{#...#} :  주석

{% ... ..#},{%+...%},{%...-%}...: 공백 제거 혹은 유지

기본적으로 진자 템플릿 엔진은 템플릿 줄 끝의 &nbsp; 개행 문자를 제외한 나머지 공백은 그대로 출력

실제로 보이는 화면에는 이러한 공백을 제외 하고 싶을 경우에 템플릿 태그 앞뒤에 +나 -를 붙여

+를 붙이면 공백 유지, -를 붙이면 공백 제거의 형태가 되는 것입니다.

 

{% raw %} ... {% endraw %} : 이스케이프(escape)
우리가 템플릿 형태와 동일한 "텍스트"를 출력하고자 할 때 사용.
{% raw %} 와 {% endraw %} 사이에 이스케이프 할 문자들을 입력.
그러나 {{'{{' }} 와 같이 따옴표로 간단하게 이스케이프 할 수도 있다.
작은 문자열의 경우는 이런식으로 사용하는 것이 편리

 

플라스크 진자2 반복문(for문)

 

{% for <개별요소> in <리스트> %}
<실행코드>
{% endfor %}

{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}

플라스크 진자2 반복문(if문)

{% if <조건> %}
    <실행코드>
{% elif <조건> %}
    <실행코드>
{% else %}
    <실행코드>
{% endif %}

{% <실행코드> if <조건> else <거짓일때 실행코드> %}

플라스크 진자2 반복문(for if문)

{% for user in users if users %}
    <li>{{ user.username }}</li>
{% endfor %}

 

locals()메소드 활용하기

#routes.py
from flask import Flask, flash, redirect, render_template, request

app = Flask(__name__)


@app.route("/")
def index():
    return "Flask App!"


@app.route("/user/")
def hello():
    users = ["Frank", "Steve", "Alice", "Bruce"]
    var = 1
    return render_template(
        'user.html', **locals())


if __name__ == "__main__":
    app.run(host='0.0.0.0', debug=True)

 

 

URL 및 HTTP 메소드 다루기

Redirect(리다이렉트)
Flask에서는 URL 간의 쉽고 편한 이동을 위해 redirect 메소드를 제공

 

from flask import Flask, redirect, url_for
app = Flask(__name__)

@app.route('/admin')
def hello_admin():
   return 'Hello Admin'

@app.route('/guest/<guest>')
def hello_guest(guest):
   return 'Hello %s as Guest' % guest

@app.route('/user/<name>')
def hello_user(name):
   if name =='admin':
      return redirect('/admin')
     #return redirect(url_for("hello_admin"))
   else:
      return redirect(url_for('hello_guest',guest = name))

if __name__ == '__main__':
   app.run(debug = True)

 

user로 주소를 입력해도 리다이렉트로 guest로 페이지가 이동한다.
http://127.0.0.1:5000/user/admin 이름이 같으면 어드민 페이지로 이동한다.

HTTP Methods

http 프로토콜은 WWW(월드 와이드 웹)에서 데이터 통신의 기본 토대

 

from flask import Flask, redirect, url_for, request
app = Flask(__name__)

@app.route('/success/<name>')
def success(name):
   return 'welcome %s' % name

@app.route('/login',methods = ['POST', 'GET'])
def login():
   if request.method == 'POST':
      user = request.form['nm']
      return redirect(url_for('success',name = user))
   else:
      user = request.args.get('nm')
      return redirect(url_for('success',name = user))

if __name__ == '__main__':
   app.run(debug = True)

웹 서버에 연결하는 것이 아닌, 직접 파일을 열어야 한다.  해당 폼이 담긴 html 문서는 딱히 flask와 연결된 게 아니기 때문이다.  그러나 form의 action 필드에 해당 URL로 해두면 POST 요청을 웹 서버로 보내서 결과를 확인할 수 있게 된다. 

//get 방식
<html>
   <body>
      
      <form action = "http://localhost:5000/login" method = "get">
         <p>Enter Name:</p>
         <p><input type = "text" name = "nm" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
      
   </body>
</html>


//post 방식
<html>
   <body>
      
      <form action = "http://localhost:5000/login" method = "post">
         <p>Enter Name:</p>
         <p><input type = "text" name = "nm" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
      
   </body>
</html>

Static 파일 다루기

http://127.0.0.1:5000/로 실행

 

// /static/hello.js
function sayHello() {
   alert("Hello World")
}

//routes.py
from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def index():
   return render_template("hello.html")

if __name__ == '__main__':
   app.run(debug = True)

//hello.html
<html>
   <head>
      <script type = "text/javascript" 
         src = "{{ url_for('static', filename = 'hello.js') }}" ></script>
   </head>
   
   <body>
      <input type = "button" onclick = "sayHello()" value = "Say Hello" />
   </body>
</html>

결과물

 

//style.css
* {
box-sizing: border-box;
}
 
*:focus {
	outline: none;
}
body {
font-family: Arial;
background-color: #3498DB;
padding: 50px;
}
.login {
margin: 20px auto;
width: 300px;
}
.login-screen {
background-color: #FFF;
padding: 20px;
border-radius: 5px
}
 
.app-title {
text-align: center;
color: #777;
}
 
.login-form {
text-align: center;
}
.control-group {
margin-bottom: 10px;
}
 
input {
text-align: center;
background-color: #ECF0F1;
border: 2px solid transparent;
border-radius: 3px;
font-size: 16px;
font-weight: 200;
padding: 10px 0;
width: 250px;
transition: border .5s;
}
 
input:focus {
border: 2px solid #3498DB;
box-shadow: none;
}
 
.btn {
  border: 2px solid transparent;
  background: #3498DB;
  color: #ffffff;
  font-size: 16px;
  line-height: 25px;
  padding: 10px 0;
  text-decoration: none;
  text-shadow: none;
  border-radius: 3px;
  box-shadow: none;
  transition: 0.25s;
  display: block;
  width: 250px;
  margin: 0 auto;
}
 
.btn:hover {
  background-color: #2980B9;
}
 
.login-link {
  font-size: 12px;
  color: #444;
  display: block;
	margin-top: 12px;
}

 

//hello.HTML

<link rel="stylesheet" href="/static/style.css" type="text/css">
 
<form action="/login" method="POST">
	<div class="login">
		<div class="login-screen">
			<div class="app-title">
				<h1>Login</h1>
			</div>
 
			<div class="login-form">
				<div class="control-group">
				<input type="text" class="login-field" value="" placeholder="username" name="username">
				<label class="login-field-icon fui-user" for="login-name"></label>
				</div>
 
				<div class="control-group">
				<input type="password" class="login-field" value="" placeholder="password" name="password">
				<label class="login-field-icon fui-lock" for="login-pass"></label>
				</div>
 
                <input type="submit" value="Log in" class="btn btn-primary btn-large btn-block" >
			    <br>
			</div>
		</div>
	</div>
</form>

결과물

 

폼으로 데이터 전송 받기

 

 

 

 

//student.html
<html>
   <body>
   
      <form action = "http://localhost:5000/result" method = "POST">
         <p>Name <input type = "text" name = "Name" /></p>
         <p>Physics <input type = "text" name = "Physics" /></p>
         <p>Chemistry <input type = "text" name = "chemistry" /></p>
         <p>Maths <input type ="text" name = "Mathematics" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
      
   </body>
</html>

//result.html
<!doctype html>
<html>
   <body>
   
      <table border = 1>
         {% for key, value in result.items() %}
         
            <tr>
               <th> {{ key }} </th>
               <td> {{ value }} </td>
            </tr>
            
         {% endfor %}
      </table>
      
   </body>
</html>

#폼 객체의 경우 각 데이터를 딕셔너리 형태로 보관하기 때문에 기존에 파이썬에서 
사용하는 items() 등의 메소드를 사용하여 출력



#form
#routes.py


from flask import Flask, render_template, request
app = Flask(__name__)

@app.route('/')
def student():
   return render_template('student.html')

@app.route('/result',methods = ['POST', 'GET'])
def result():
   if request.method == 'POST':
      result = request.form
      return render_template("result.html",result = result)

if __name__ == '__main__':
   app.run(debug = True)
   
   
   # 특정 필드 값만 뽑아내고 싶다면 request.form['name']와 같은 식으로 처리



플라스크에서 폼의 데이터를 사용하는 방법
result = request.form
폼 관련 데이터를 다루는 부분

 

 

결과 이미지

 


# 워드 클라우드
# WordCloud 설치 : pip install wordcloud
from wordcloud import WordCloud,STOPWORDS

import numpy as np
from PIL import Image

# alice.txt
text = open('./data/09. a_new_hope.txt').read()
alice_mask = np.array(Image.open('./data/09. stormtrooper_mask.png'))

stopwords = set(STOPWORDS)
stopwords.add("said")

import matplotlib.pyplot as plt
import platform


path = "c:/Windows/Fonts/malgun.ttf"


# 폰트 설정(특히 한글 부분)
from matplotlib import font_manager, rc, pyplot as plt
plt.rcParams['axes.unicode_minus'] = False

if platform.system() == 'Darwin':
    rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
    path = "c:/Windows/Fonts/malgun.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc('font', family=font_name)
else:
    print('Unknown system... sorry~~~~')
    
plt.figure(figsize=(8, 8))
plt.imshow(alice_mask, cmap=plt.cm.gray, interpolation='bilinear')
plt.axis('off')
plt.show()

wc = WordCloud(background_color='white', max_words=2000, mask=alice_mask, stopwords=stopwords1)
wc = wc.generate(text)

#wc.words_
plt.figure(figsize=(12, 12))
plt.imshow(wc, interpolation='bilinear')
plt.axis('off')
plt.show()

#starwars
plt.figure(figsize=(10, 10))
plt.imshow(wc, interpolation='bilinear')
plt.axis('off')
plt.show()

stopwords1 = set(STOPWORDS)
stopwords1.add("EXT")
stopwords1.add("INT")
stopwords1.add("Luke")
# =============================================================================
# 
# =============================================================================

#a_new_hope.txt
text = open('.data/09. a_new>hope.txt').read()
text = text.replace('HAN', 'Han')
text = text.replace("LUKE'S", "Luke")

mask = np.array(Image.oepn('.data/09. stormtrooper_mask.png'))

stopwords2 = set(STOPWORDS)
stopwords2.add("int")
stopwords2.add("ext")

wc = WordCloud(max_words=1000, mask=alice_mask, stopwords=stopwords2, margin=10, random_state=1).generate(text)
# =============================================================================
# 
# =============================================================================
import random
def grey_color_func(word, font_size, position, orientation, random_state=None, **kwargs):
    return 'hsl(0, 0%%, %d%%)' % random.randint(60, 100)

plt.figure(figsize=(12,12))
plt.imshow(wc.recolor(color_func=grey_color_func, random_state=3),interpolation='bilinear')

plt.axis('off')
plt.show()

 

# -*- coding: utf-8 -*-
"""
Created on Fri Apr 24 11:03:15 2020

@author: USER
"""


# 꼬꼬마에 대하여
from konlpy.corpus import kolaw
from konlpy.tag import Kkma
from konlpy.utils import concordance

#'''
#헌법 관련된 텍스트 불러오기
constitution = kolaw.open('constitution.txt').read()

print(constitution)

#몇번째 줄에 '민주'라는 단어가 있는지 찾아줌
r=concordance(u'민주',constitution, show=False)
print("show=False =>", r)

#고려사항 : 정확성,속도
from konlpy.tag import Kkma
from konlpy.utils import pprint

kkma = Kkma()

text = u'네, 안녕하세요. 반갑습니다.'

#문장단위로 찾아냄
text_s = kkma.sentences(text)
print("text_s => ",  text_s)

print("type(text_s) =>",type(text_s))
print("text_s[0]=>",text_s[0])
print("text_s[0]=>",text_s[-1])

#tagset : 형식들에 대한 정보 파악
kkma = Kkma()
print(kkma.tagset)

text = "자연어처리는 재미있습니다.\ 그러나 한국어 분석은 쉽지 않습니다."

# 명사,추출기, Noun extractor
text_nouns = kkma.nouns(text)
print(text_nouns)

#형태소 해석, Parse phrase to morphemes
#나중에 조사들을 추출해서 버리고
#의미있는 것들만 분석에 활용한다
text_morphs = kkma.morphs(text)
print(text_morphs)

# POS태그
pos_tagger = kkma.pos(text)
print(pos_tagger)

print(len(pos_tagger))
print(type(pos_tagger))
print(type(pos_tagger[0]))

#flatten=False : 문장단위에 따라서 묶음이 달라짐
# True일 때는 하나하나 다 풀어서 저장
pos_tagger_f = kkma.pos(text, flatten=False)

print(pos_tagger_f)
print(len(pos_tagger_f))
print(type(pos_tagger_f))
print(type(pos_tagger_f[0]))

# =============================================================================
# 
# =============================================================================
constitution = kolaw.open('constitution.txt').read()
pos_const = kkma.pos(constitution)

print(len(pos_const))
# 보통명사만 추출->가나다 순으로
pos_const_NNG = [ word[0] for word in pos_const
                                     if word[1]=='NNG']

print(len(pos_const_NNG))

pos_const_NNG.sort()
print(pos_const_NNG[:10])
print(pos_const_NNG[-10:])


# 모든 명사 추출
NN_list = [ 'NN', 'NNB', 'NNG', 'NNM', 'NNP', 'NP']

# 모든명사의 개수 파악하기
pos_const_NN = [ word[0] for word in pos_const
                                if word[1] in NN_list]
print(len(pos_const_NN))

pos_const_NN.sort()
print(pos_const_NN[:10])
print(pos_const_NN[-10:])

#set로 묶어서 유니크한 값 찾기
s=set(pos_const_NN)
print(len(s))

#헌법 관련된 텍스트 불러오기
constitution = kolaw.open('constitution.txt').read()

print(constitution)


#몇번째 줄에 '민주'라는 단어가 있는지 찾아줌
r=concordance(u'All',constitution, show=True)
print("show=False =>", r)
# =============================================================================
# 
# =============================================================================
def getNounCnt(pos_list):
    noun_cnt = {}
    for noun in pos_list:
        if noun_cnt.get(noun):
            noun_cnt[noun] += 1
        else:
            noun_cnt[noun] = 1
    return noun_cnt

noun_dict = getNounCnt(pos_const_NN)
print(len(noun_dict))
print(noun_dict)
# =============================================================================
# pos list=['가격','가부','가입','가족','가족','가치','각급','각급','각급']
# noun_cnt={'가격':1, '가부':1,'가입':2}
# noun='가입'
# =============================================================================
# =============================================================================
# 
# =============================================================================
# =============================================================================
# 
# =============================================================================

constitution = kolaw.open('constitution.txt').read()
pos_const = kkma.pos(constitution)

from collections import Counter
# most_common : 가장 많이 나온 것들만 뽑아냄
counter = Counter(pos_const)
print(counter.most_common(10))
# =============================================================================
# 
# =============================================================================
'''
noun_dict = getNounCnt(pos_const_NN)
'''
# 의미 있는 것을 찾기 위해서 명사들 중에서
# 가장 많이 나온 것들을 뽑아냄
noun_dict = getNounCnt(pos_const_NN)
counter = Counter(noun_dict)
print(counter.most_common(10))
# =============================================================================
# 
# =============================================================================
# 육아휴직관련 법안 대한민국 국회 제 1809890호 의안
import nltk
from konlpy.corpus import kobill

files_ko = kobill.fileids()
doc_ko = kobill.open('1809890.txt').read()


doc_ko
# =============================================================================
# 
# =============================================================================
# Twitter
from konlpy.tag import Twitter;

t = Twitter()
tokens_ko = t.nouns(doc_ko)
tokens_ko

ko = nltk.Text(tokens_ko, name='대한민국 국회 의안 제 1809890호')

print(len(ko.tokens))
print(len(set(ko.tokens)))
ko.vocab()

# chart 1
plt.figure(figsize=(12,6))
ko.plot(50)
plt.show()

stop_words =['.','(',')',',',"'",'%','-','X',').','의','자','에','안','번','호','을','이','다','만','로','가','를']
ko = [each_word for each_word in ko if each_word not in stop_words]
ko

# chart 2
ko = nltk.Text(ko, name='대한민국 국회 의안 제 1809890호')

plt.figure(figsize=(12,6))
ko.plot(50)
plt.show()

# =============================================================================
# 
# =============================================================================

# chart 3
ko.count('초등학교')
plt.figure(figsize=(12,6))
ko.dispersion_plot(['육아휴직','초등학교','공무원'])
ko.concordance('초등학교')

data = ko.vocab().most_common(150)

# wordcloud
# for mac : font_path='/Library/Fonts/AppleGothic.ttf'
wordcloud = WordCloud(font_path='c:/Windows/Fonts/malgun.ttf', relative_scaling = 0.2, background_color='white',).generate_from_frequencies(dict(data))
plt.figure(figsize=(12,8))
plt.imshow(wordcloud)
plt.axis("off")
plt.show()

 

# -*- coding: utf-8 -*-
"""
Created on Fri Apr 24 09:15:29 2020

@author: USER
"""


#### 한글 자연어 처리 기초
# Kkma
from lib2to3.btm_utils import tokens
from konlpy.tag import Kkma

kkma = Kkma()

print(kkma.sentences('한국어 분석을 시작합니다. 재미있어요~~'))
print(kkma.nouns('한국어 분석을 시작합니다. 재미있어요~~'))
print(kkma.pos('한국어 분석을 시작합니다. 재미있어요~~'))

# =============================================================================
# 
# =============================================================================
# Hannanum
from konlpy.tag import Hannanum

print(hannanum.nouns('한국어 분석을 시작합니다 재미있어요~~'))
print(hannanum.morphs('한국어 분석을 시작합니다 재미있어요~~'))
print(hannanum.pos('한국어 분석을 시작합니다 재미있어요~~'))
# =============================================================================
# 
# =============================================================================
# Twitter
from konlpy.tag import Okt

t = Okt()

print(t.nouns('한국어 분석을 시작합니다 재미있어요~~'))
print(t.morphs('한국어 분석을 시작합니다 재미있어요~~'))
print(t.pos('한국어 분석을 시작합니다 재미있어요~~'))
# =============================================================================
# 
# =============================================================================
# Komoran()
# Komoran
from konlpy.tag import Komoran

k = Komoran()
print(k.nouns('한국어 분석을 시작합니다 재미있어요~~'))
print(k.morphs('한국어 분석을 시작합니다 재미있어요~~'))
print(k.pos('한국어 분석을 시작합니다 재미있어요~~'))
# =============================================================================
# 
# =============================================================================
#성능비교
import time
sentence = u"감정노동자 보호법은 사업주로 하여금 감정노동으로부터 근로자를 보호"
sentences = [sentence] * 100

from konlpy.tag import Hannanum, Kkma, Komoran, Okt

morphs_processors= [('Hannanum', Hannanum()), ('Kkma', Kkma()),'Komoran', Komoran(),('Okt',Okt())]

for name, morphs_processors in morphs_processors:
    start_time = time.time()
    morphs = [morphs_processor.morphs(sentence) for sentence in sentences]
    elapsed_time = time.time() - start_time
    print('morphs_processor name = %20s, % 5f secs' % (name,elapsed_time))

'''
빠른 속도와 보통의 정확도를 원한다면 "Komoran" 또는 "Hannanum"
속도는 느리더라도 정확하고 상세한 품사 정보를 원한다면 "Kkma"

어느 정도의 띄어쓰기 되어 있는 "인터넷" 영화평/상품명을 처리할 땐 "Okt"
(만약 띄어쓰기가 없다면 느린 처리속도는 감수해야함)
'''

'''
언어를 분석할때, stopwords 라는 용어가 나온다.
stopwords 또는 불용어 란, 우리가 언어를 분석할 때,
의미가 있는 단어와, 의미가 없는 단어나 조사 등이 있다.

이렇게 의미가 없는 것들을 stopwords 라고 한다.

예를 들어서, 다음 문장이 있으면,
"Family is not an important thing. It's everything."

Family, important, thing, everything은 의미가 있다고 보고,
나머지 아래 같은 것들은 의미가 없다고 판단하여 stopwords로 정의한다.
'''

 

# Naive Bayes Classifier의 이해 - 한글
# 문장의 유사도 측정
'''
'메리가 좋아'
'고양이도 좋아'
'난 수업이 지루해'
'메리는 이쁜 고양이야'
'난 마치고 메리랑 놀거야'
'''

from konlpy.tag import Okt
from nltk.tokenize import word_tokenize
import nltk

pos_tagger = Okt()

train = [('메리가 좋아', 'pos'),
         ('고양이도 좋아', 'pos'),
         ('난 수업이 지루해', 'neg'),
         ('메리는 이쁜 고양이야', 'pos'),
         ('난 마치고 메리랑 놀거야', 'pos')]

all_words = set(word.lower()
                for sentence in train
                for word in word_tokenize(sentence[0]))

all_words

t = [({word: (word in word_tokenize(x[0]))
        for word in all_words}, x[1]) for x in train]

t

classifier = nltk.NaiveBayesClassifier.train(t)
classifier.show_most_informative_features()

 

'''
Numpy란 Numerical Python 의 약자로
대규모 다차원 배열과 행렬 연산에 필요한 다양한 함수를 제공한다.
데이터 분석할 때 사용되는 다른 라이브러리 pandas와 matplotlib의 기반이 된다.
기본적으로 array라는 단위로 데이터를 관리하는데, 행렬 개념으로 생각하면 된다.

- numpy 특징 : 일반 list에 비해 빠르고 메모리에 효율적이다.
선형대수와 관련된 다양한 기능을 제공하고,
for문, while문 같은 반복문 없이 데이터 배열에 대한 처리를 지원한다.

 - numpy가 빠른 이유 : numpy는 메모리에 차례대로 생성/할당을 해준다.
 반면 기존의 List는 이 값(value)가 어디에 있는지 주소만 저장을 해놓고 그 주소를 알려준다.
 그래서 list를 for문을 돌리면 그 주소마다 하나하나씩 다 찾아가면서 연산을 해줘야 하는데,
 (파이썬은 변수형태로 들어가고 numpy는 메모리를 직접관리)
 numpy는 같은 곳에 몰려 있기 때문에 연산이 더 빠르게 이뤄진다.
 
  --> 넘파이는 데이터들을 한군데 차곡차곡 모아서 관리하는게 특징이다. 그러나 파이썬의 리스트는
  데이터가 있는 번지수가 있어서 그 변수. 즉, 주소들만 기억하고 실제로 찾아내려면 그 번지를 이용해서 찾아다녀야 한다.
  
 - numpy 호출 : "import numpy as np"로 numpy를 호출하는데 모두 np라는 별칭(alias)로 호출하지만 특별한 이유는 없다.
 - numpy로 array 생성하는 방법 : ex)test_array = np.array([1,3,5,7], float)
  type(test_array[3])을 하면 4바이트씩 numpy.float64 라는 값이 반환된다.
  float32 같은 데이터 타입은 하나씩 모여서 메모리 블럭을 구성한다.
  32bit(비트) = 4byte(바이트)이다. (8bit 가 1byte)
'''
import numpy as np

test_array = np.array([1,3,5,7], float)
print(test_array) # [1. 3. 5. 7.]
print(type(test_array)) # <class 'numpy.ndarray'>

'''
ndarray의 구성 -> (4,)
ndarray의 shape : (type : tuple)
이건 1차원 벡터형식이라고 부른다.

vector는 1차원 행렬을 말하고 하나의 행에 열만 있는 것이다.
(위의 그림 예시에서는 1차원에 4개의 element만 있음)
각 숫자는 value(요소)라고도 부른다.
shape를 보는 코드 예시는 그림 상에 없지만 결과적으로 (4,)의 결과를 보여줄 것이다.
'''

matrix = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
matrix2 = np.array(matrix, int).shape # (3, 4)
type(matrix2) # tuple
type(matrix) # list

tensor = [[[1,2,3,4],[5,6,7,8],[9,10,11,12]],
          [[1,2,3,4],[5,6,7,8],[9,10,11,12]],
          [[1,2,3,4],[5,6,7,8],[9,10,11,12]]]

type(tensor) # list
np.array(tensor, int).shape # (3, 3, 4)
# 3차원 matrix, nparray의 shape(type : tuple)

np.array(tensor, int).ndim # number of dimension
# 3
np.array(tensor, int).size # data의 개수
# 36

'''
- Ndarray의 single element가 가지는 data type
- 각 element가 차지하는 memory의 크기가 결정됨
'''
np.array( [[1,2.6, 3.2], [4, 5.1, 6]], dtype=int)
#array([[1, 2, 3],
#       [4, 5, 6]])

np.array( [[1,2.6, 3.2], [4, "5", 6]], dtype=np.float32)
#array([[1. , 2.6, 3.2],
#       [4. , 5. , 6. ]], dtype=float32)

'''
각 요소마다 데이터 타입을 지정해주면 그 데이터 타입으로 변환이 되는 걸 볼 수 있다.

아래의 예시를 보면 여기는 실수형이고 여기는 string 타입인데 소수점 타입으로 바꾸면
???????????????????????????????????????????????????????????????????????????????
'''

# - nbyte : ndarray object의 메모리 크기 리턴

np.array([[1, 2.6, 3.2], [4, "5", 6]], dtype=np.float32).nbytes
# 24 -> 32bits = 4bytes -> 6 * 4 bytes
np.array([[1, 2.6, 3.2], [4, "5", 6]], dtype=np.float64).nbytes
# 48 -> 64bits = 8bytes -> 6 * 8 bytes
np.array([[1, 2.6, 3.2], [4, "5", 6]], dtype=np.int8).nbytes
# 6 -> 8bits = 1 bytes -> 6 * 1bytes


'''
하나의 value가 4바이트를 가지는데
요소가 6개 있으니까, 이게 메모리에서 차지하는 건 총 24바이트가 된다.
그 다음 타입은 하나가 8바이트이니까 48바이트를 차지한다.
'''

# - Array의 크기를 변경함(element의 개수는 동일)
t_matrix = [[1,2,3,4], [5,6,7,8]]
np.array(t_matrix).shape
#(2, 4)
np.array(t_matrix).reshape(8,)
#array([1, 2, 3, 4, 5, 6, 7, 8]) --> 2행으로 되어있는 것을 1행으로 변경하였다.
np.array(t_matrix).reshape(8,).shape
#(8,)


# - Array의 size만 같다면 다차원으로 자유로이 변형 가능
np.array(t_matrix).reshape(2, 4).shape
#(2, 4)
np.array(t_matrix).reshape(-1, 2).shape # -1 을 입력하면 알아서 행 갯수를 맞춰준다.
#(4, 2)
np.array(t_matrix).reshape(2,2,2)
#array([[[1, 2],
#        [3, 4]],
#       [[5, 6],
#        [7, 8]]])
np.array(t_matrix).reshape(2,2,2).shape
#(2, 2, 2)

# flatten : 다차원 array를 1차원 array로 변환
t_matrix = [ [[1,2], [3,4]], [[1,2], [3,4]], [[1,2],[3,4]]]
np.array(t_matrix).flatten()
# array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4])

# flatten : 다차원을 1차원으로만 만들어 주는 함수. 즉, reshape은 최소화할 열이나 행 둘중에 하나를 뿌려줘야 하는데 flatten은 1차원으로만됨

# indexing
a = np.array([[1,2.2,3], [4,5,6.3]],int)
print(a)

#[[1 2 3]
# [4 5 6]]

print(a[0,0]) # 1
print(a[0][0]) # 1
a[0,0]=7
print(a)
#[[7 2 3]
# [4 5 6]]

# slicing
# - list와 달리 행과 열 부분을 나눠서 slicing 이 가능함
# - matrix 부분 집합 추출할 때 유용
a = np.array([[1,2,3,4,5],[6,7,8,9,10]],int)
a[:,1:] # 전체 row의 1열 이상
#array([[ 2,  3,  4,  5],
#       [ 7,  8,  9, 10]])

a[1, 2:4] # 1row의 2~3열
#array([8, 9])

a[1:3] #1row ~ row 전체
#array([[ 6,  7,  8,  9, 10]])

a = np.array([[0,1,2,3,4], [5,6,7,8,9], [10,11,12,13,14]], int)
print(a)
#[[ 0  1  2  3  4]
# [ 5  6  7  8  9]
# [10 11 12 13 14]]

a[:,::2] # 행과 열은 내부 인덱스를 뽑는거고, 두 번째는 위치를 뽑는것
#array([[ 0,  2,  4],
#       [ 5,  7,  9],
#       [10, 12, 14]])

a[::2,::2] # ::은 스텝(간격)을 의미한다.
#array([[ 0,  2,  4],
#       [10, 12, 14]])

#배열을 만드는데 범위를 지정해서 만드는 방법
# - array의 범위를 지정하여, 값의 list를 생성하는 명령어

np.arange(20)#list의 range와 같은 역할, intege로 0부터 19까지 배열 추출
# array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

np.arange(0, 1, 0.2) #float 가능
#array([0. , 0.2, 0.4, 0.6, 0.8])

np.arange(20).reshape(4,5) # 만든 값을 reshape한다.
#array([[ 0,  1,  2,  3,  4],
#       [ 5,  6,  7,  8,  9],
#       [10, 11, 12, 13, 14],
#       [15, 16, 17, 18, 19]])

np.zeros(shape = (5,2), dtype = np.int8) # 5 by 2 zero matrix 생성, int8
#array([[0, 0],
#       [0, 0],
#       [0, 0],
#       [0, 0],
#       [0, 0]], dtype=int8)

np.ones(shape = (5,2), dtype = np.int8) # 5 by 2 one matrix 생성, int8
#array([[1, 1],
#       [1, 1],
#       [1, 1],
#       [1, 1],
#       [1, 1]], dtype=int8)

np.empty(shape=(3,2), dtype=np.int8)
#array([[1, 2],
#       [3, 4],
#       [5, 6]], dtype=int8)
# 실행할 때 마다 다른 값이 출력된다.

'''
empty는 주어진 shape대로 비어있는 것을 생성한다.
이런 식으로 array를 만드는데 메모리를 어느 정도 할당 시켜준다.
그런데 메모리에 기존에 있었던 값을 보여준다.

zeros나 ones는 0과 1로 메모리 할당 값을 초기화 시켜주는데
empty는 초기화시키지 않고 기존에 메모리에 있는 찌꺼기 그대로 보여준다.
'''
'''
empty는 주어진 shape대로 비어있는 것을 생성한다.
이런 식으로 array를 만드는데 메모리를 어느 정도 할당 시켜준다.
그런데 메모리에 기존에 있었던 값을 보여준다.

zeros나 ones는 0과 1로 메모리 할당 값을 초기화 시켜주는데
empty는 초기화시키지 않고 기존에 메모리에 있는 찌꺼기 그대로 보여준다.
'''

#기존 ndarray의 shape 크기만큼 1 or 0 or empty array 반환
t_matrix = np.arange(15).reshape(3,5)
np.ones_like(t_matrix) # 채워져있는 구조를 이용해서 1로 바꾼 것, 원본 반영되는게 아님
#array([[1, 1, 1, 1, 1],
#       [1, 1, 1, 1, 1],
#       [1, 1, 1, 1, 1]])

t_matrix1 = np.arange(15).reshape(3,5)
np.zeros_like(t_matrix1) # 채워져있는 구조를 이용해서 0으로 바꾼 것, 원본 반영되는게 아님
#array([[0, 0, 0, 0, 0],
#       [0, 0, 0, 0, 0],
#       [0, 0, 0, 0, 0]])

t_matrix2 = np.arange(15).reshape(3,5)
np.empty_like(t_matrix2)
#array([[ 0,  1,  2,  3,  4],
#       [ 5,  6,  7,  8,  9],
#       [10, 11, 12, 13, 14]])
#기존 ndarray의 shape 크기만큼 1 or 0 or empty array 반환
t_matrix = np.arange(15).reshape(3,5)
np.ones_like(t_matrix) # 채워져있는 구조를 이용해서 1로 바꾼 것, 원본 반영되는게 아님
#array([[1, 1, 1, 1, 1],
#       [1, 1, 1, 1, 1],
#       [1, 1, 1, 1, 1]])

t_matrix1 = np.arange(15).reshape(3,5)
np.zeros_like(t_matrix1) # 채워져있는 구조를 이용해서 0으로 바꾼 것, 원본 반영되는게 아님
#array([[0, 0, 0, 0, 0],
#       [0, 0, 0, 0, 0],
#       [0, 0, 0, 0, 0]])

t_matrix2 = np.arange(15).reshape(3,5)
np.empty_like(t_matrix2)
#array([[ 0,  1,  2,  3,  4],
#       [ 5,  6,  7,  8,  9],
#       [10, 11, 12, 13, 14]])


# 단위행렬 (i행렬)을 생성 n -> number of rows
np.identity(n=3, dtype=np.int8)
#array([[1, 0, 0],
#       [0, 1, 0],
#       [0, 0, 1]], dtype=int8)

np.identity(n=5) #정사각형 행렬
#array([[1., 0., 0., 0., 0.],
#       [0., 1., 0., 0., 0.],
#       [0., 0., 1., 0., 0.],
#       [0., 0., 0., 1., 0.],
#       [0., 0., 0., 0., 1.]])

np.eye(N=3, M=4, dtype=np.int) # N값과 M 값을 변경시켜서 직사각형 형태로 만들 수 있다.
#array([[1, 0, 0, 0],
#       [0, 1, 0, 0],
#       [0, 0, 1, 0]])

np.eye(4) # identity행렬과 같게 출력
#array([[1., 0., 0., 0.],
#       [0., 1., 0., 0.],
#       [0., 0., 1., 0.],
#       [0., 0., 0., 1.]])

np.eye(4) # identity행렬과 같게 출력
#array([[1., 0., 0., 0.],
#       [0., 1., 0., 0.],
#       [0., 0., 1., 0.],
#       [0., 0., 0., 1.]])

np.eye(3, 6, k=3) # k --> start index
# 기준 열에서 1을 시작점으로 찍는 옵션(3칸 건너 뛰고 시작한다.)
#array([[0., 0., 0., 1., 0., 0.],
#       [0., 0., 0., 0., 1., 0.],
#       [0., 0., 0., 0., 0., 1.]])


'''행렬 중 대각선 값만 뽑아내는 함수'''
t_matrix = np.arange(16).reshape(4,4)
np.diag(t_matrix)
# array([ 0,  5, 10, 15])

np.diag(t_matrix, k=1) # k옵션은 출력하는 열의 시작 위치를 나타낸다.
# array([ 1,  6, 11])

'''Random Sampling'''
# 정규분포 만들어주는 함수
np.random.uniform(0,1,12).reshape(4,3) # 균등분포
# np.random.uniform(최소값, 최대값, 데이터 개수)
#array([[0.39422635, 0.83574142, 0.10830835],
#       [0.33941921, 0.97021726, 0.91356626],
#       [0.9100399 , 0.8243246 , 0.85169551],
#       [0.48654262, 0.15473669, 0.8773488 ]])


np.random.normal(0,1,12).reshape(4,3) # 정규분포
#array([[ 0.29332096, -0.05565469, -0.04275069],
#       [ 0.15716903, -0.50732937, -0.12142198],
#       [ 1.42172159,  0.29410614, -2.32252451],
#       [ 1.44995498, -0.75131102,  0.35022273]])

'''axis'''
# - 모든 operation function 을 실행할 때, 기준이 되는 dimension 축
# 집계연산을 할 때 어떤 축을 기준으로 집계연산을 해달라는 의미
t_array = np.arange(1,13).reshape(3,4)
t_array
#array([[ 1,  2,  3,  4],
#       [ 5,  6,  7,  8],
#       [ 9, 10, 11, 12]])

t_array.sum(axis = 0), t_array.sum(axis=1)
#(array([15, 18, 21, 24]), array([10, 26, 42]))

t_array = np.arange(1, 13).reshape(3,4)
t_array
#array([[ 1,  2,  3,  4],
#       [ 5,  6,  7,  8],
#       [ 9, 10, 11, 12]])

t_array.mean(), t_array.mean(axis=0)
#(6.5, array([5., 6., 7., 8.]))

t_array.std(), t_array.std(axis=0)
#(3.452052529534663, array([3.26598632, 3.26598632, 3.26598632, 3.26598632]))

a = np.array([1,2,3])
b = np.array([4,5,6])
np.vstack((a,b))
# array([[1],
#        [2],
#        [3],
#        [4],
#        [5],
#        [6]])

a = np.array([ [1], [2], [3]])
b = np.array([ [4], [5], [6]])
np.hstack((a,b))
# array([[1, 4],
#        [2, 5],
#        [3, 6]])

# All, Any
# - All : array의 데이터가 전부 조건에 만족하면 True
# - Any : array의 데이터 중 하나라도 조건에 만족하면 True
a = np.arange(5)
a
#array([0, 1, 2, 3, 4])

np.all(a>3)
# False
np.all(a<5)
# True
np.any(a>3)
# True
np.any(a>5)
# False

'''all은 말 그대로 모든 조건 만족하면 true가 나오고, any는 하나라도 만족하면 true를 추출해내는 함수이다.'''

'''all은 말 그대로 모든 조건 만족하면 true가 나오고, any는 하나라도 만족하면 true를 추출해내는 함수이다.'''

a = np.array( [1,5,3], float)
b = np.array( [4,7,2], float)
a>b
#array([False, False,  True])
a==b
#array([False, False, False])
(a>b).any()
#True
(a>b).all()
#False

'''np.where'''
# - where(조건, True, False)

a = np.array( [2,3,1], float)
np.where(a > 1, 0, 3)
#array([0, 0, 3])

a = np.arange(3,10)
np.where(a>6) # True값의 index 반환
#(array([4, 5, 6], dtype=int64),)

a = np.array( [2, np.NaN, np.Inf], float)
np.isnan(a)
#array([False,  True, False])

np.isfinite(a) # 한정된 수인 경우 True
#array([ True, False, False])

# np.where은 우리가 생각하는 if문의 역할을 한다.
'''
isnan은 null값인 경우에만 True가 나온다
np.Nan은 numpy의 null 값을 입력하는 함수이고,
null값이니까 True

np.Inf 는 무한대

np.isinfite()는 한정된 수의 경우 True가 나오고
한정되지 않은 NaN이나 Inf의 경우에는 False가 나온다

'''
'''argmax, argmin'''
# - array 내 최대값 또는 최소값의 index 반환
a = np.array( [2,3,1,5,6,22,11])
np.argmax(a), np.argmin(a)
#(5, 2)

# -axis 기반의 반환
a = np.array( [[1,4,2,22], [45,32,4,7], [34,54,9,8]])
np.argmax(a,axis=0), np.argmin(a, axis=1)
#(array([1, 2, 2, 0], dtype=int64), array([0, 2, 3], dtype=int64))

'''argmax, argmin'''
# - array 내 최대값 또는 최소값의 index 반환
a = np.array( [2,3,1,5,6,22,11])
np.argmax(a), np.argmin(a)
#(5, 2)

# -axis 기반의 반환
a = np.array( [[1,4,2,22], [45,32,4,7], [34,54,9,8]])
np.argmax(a,axis=0), np.argmin(a, axis=1) # 0번(열 기준), 1번(행 기준)
#(array([1, 2, 2, 0], dtype=int64), array([0, 2, 3], dtype=int64))
# 첫 번째 열에서 가장 큰 값 45(1번 인덱스)-컬럼
# 첫 번째 행에서 가장 작은 값 1(0번 인덱스)-로우, 두번째 행에서 가장 작은값 4(2번 인덱스) - 로우

'''boolean index '''
# -numpy의 배열은 특정 조건에 따른 값을 배열 형태로 추출 가능
# -comparison operation 함수들도 모두 사용 가능
t_a = np.array( [3,5,8,0,7,4], float)
t_a > 4
#array([False,  True,  True, False,  True, False])

t_a[t_a>4] # 조건이 True인 index 의 요소값만 추출
#array([5., 8., 7.])

t_c = t_a <4
t_c
# array([ True, False, False,  True, False, False])

 

# -*- coding: utf-8 -*-
"""
Created on Fri Apr 24 17:19:42 2020

@author: admin
"""


import numpy as np

# concatenate
# - numpy array를 합치는 함수
a = np.array([[1,2,3]])
b = np.array([[4,5,6]])
np.concatenate((a,b), axis = 0)
#array([[1, 2, 3],
#       [4, 5, 6]])

a = np.array([[1,2], [3,4]])
b = np.array([[5,6]])
np.concatenate((a,b.T), axis=1 ) # a.T는 a의 역행렬 
#array([[1, 2, 5],
#       [3, 4, 6]])

# vstack 이랑 hstack은 같은 함수인데 axis로 결정된다.

'''Operations betwwn arrays'''
a = np.array( [[1,2,3], [4,5,6]], float)
a+a # matrix + matrix 연산
#array([[ 2.,  4.,  6.],
#       [ 8., 10., 12.]])

a-a # - 연산
#array([[0., 0., 0.],
#       [0., 0., 0.]])

a*a # matrix 내 요소들간 같은 위치에 있는 값들끼리 연산
#array([[ 1.,  4.,  9.],
#       [16., 25., 36.]])

'''이렇게 같은 index에 있는 것 끼리 더하고 빼고 곱해줘서 그 자리에 결과값을 넣어주는 연산 
= Element-wise Operation 이라고 한다.'''


# Dot product
# - matrix 의 기본 연산
# - dot 함수 사용

dot_a = np.arange(1, 7).reshape(2,3)
#array([[1, 2, 3],
#       [4, 5, 6]])

dot_b = np.arange(1, 7).reshape(3,2)
#array([[1, 2],
#       [3, 4],
#       [5, 6]])

dot_a.dot(dot_b)
# 행렬 연산식 적용 ( 2x3 행렬과 3x2 행렬의 곱)
#array([[22, 28],
#       [49, 64]])

t_matrix = np.array( [[1,2], [3,4]], float)
#array([[1., 2.],
#       [3., 4.]])

scalar = 2

t_matrix + scalar
#array([[3., 4.],
#       [5., 6.]])
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 23 09:49:21 2020

@author: admin
"""

'''
서울시 구별 CCTV 현황 분석하기

서울시 각 구별 CCTV 수를 파악하고,
인구대비 CCTV 비율을 파악해서 순위 비교

인구대비 CCTV의 평균치를 확인하고
그로부터 CCTV가 과하게 부족한 구를 확인

Python 기본 문법 / Pandas 와 Matplotlib의 기본적 사용법을 이용한 시각화
단순한 그래프 표현에서
한 단계 더 나아가 경향을 확인하고 시각화하는 기초 확인
 
'''
import pandas as pd
import numpy as np

# CCTV 데이터와 인구 데이터 합치고 분석하기

##CCTV 데이터 읽기
CCTV_Seoul = pd.read_csv('./data/01. CCTV_in_Seoul.csv', encoding='UTF-8')
#데이터프레임
CCTV_Seoul.head()

CCTV_Seoul.columns

CCTV_Seoul.columns[0]

#칼럼명 변경 : 기관명을 구별로 변경 
CCTV_Seoul.rename(columns={CCTV_Seoul.columns[0]:'구별'}, inplace=True)
CCTV_Seoul.head()


# 인구데이터 읽기 1
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls', encoding='UTF-8')
pop_Seoul.head()

#인구 데이터 읽기2 - 필요한 데이터만 선별하여 읽기
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls',
                          header=2, # 헤더 두 줄 건너 뛰고 나타내라
                          usecols='B, D, G, J, N', # 사용할 컬럼 지정
                          encoding='utf-8')

pop_Seoul.head()

#계라고 나오는 컬럼을 알기 쉬운 컬럼명으로 변경
pop_Seoul.rename(columns={pop_Seoul.columns[0]:'구별',
                          pop_Seoul.columns[1]:'인구수',
                          pop_Seoul.columns[2]:'한국인',
                          pop_Seoul.columns[3]:'외국인',
                          pop_Seoul.columns[4]:'고령자'},inplace=True)

pop_Seoul.head()

#CCTV 데이터 파악하기
# 소계 순으로 정렬(오름차순)
CCTV_Seoul.sort_values(by='소계', ascending=True).head(5)
# 소계 순으로 정렬(내차순)
CCTV_Seoul.sort_values(by='소계', ascending=False).head(5)
#sort_values : 원본에 정렬순으로 저장되는 것은 아니다.


# 최근증가율 = (2016년+2015년+2014년)/2013년도 이전 * 100
CCTV_Seoul['최근증가율']=(CCTV_Seoul['2016년']+CCTV_Seoul['2015년']+ \
                     CCTV_Seoul['2014년']) / CCTV_Seoul['2013년도 이전'] * 100
    
    
CCTV_Seoul.sort_values(by='최근증가율', ascending=False).head()


#서울시 인구데이터 파악하기
pop_Seoul.head()

#첫번째 합계 행 삭제
pop_Seoul.drop([0],inplace=True)
pop_Seoul,head()

#'구별' 칼럼의 중복값 제거
pop_Seoul['구별'].unique()

#'구별' 칼럼의 NULL 값 확인
#isnull() : 널값의 행값과 널값을 인덱스 번호를 반환 시켜준다.
#     구별  인구수  한국인  외국인  고령자
#26  NaN  NaN  NaN  NaN  NaN
pop_Seoul[pop_Seoul['구별'].isnull()]

# '구별' 컬럼의 NULL값 있는 행 제거
pop_Seoul.drop([26],inplace=True)
pop_Seoul.head()

'''
데이터 분석
1.분석데이터 수집(R or python )
2.수집된 데이터 형식 확인 및 로컬 전처리
3.분석 prg에서 수집 데이터 읽기
4.읽은 데이터 확인 및 3차 전처리
'''

#외국인비율과 고령자 비율 추가
pop_Seoul['외국인비율']=pop_Seoul['외국인']/pop_Seoul['인구수']*100
pop_Seoul['고령자비율']=pop_Seoul['고령자']/pop_Seoul['인구수']*100
pop_Seoul.head()

# 각 칼럼 확인
pop_Seoul.sort_values(by='인구수', ascending=False).head()
pop_Seoul.sort_values(by='외국인', ascending=False).head()
pop_Seoul.sort_values(by='외국인비율', ascending=False).head()
pop_Seoul.sort_values(by='고령자', ascending=False).head()
pop_Seoul.sort_values(by='고령자비율', ascending=False).head()

# 시각화 작업을 위함 구이름('구별')을 index화
data_result.set_index('구별', inplace=True)
data_result.head()


###CCTV 데이터와 인구 데이터 합치고 분석하기

# 두개의 데이터프레임을 합할 경우 동일 컬럼명은 하나('구별')로 통일 된다.
data_result = pd.merge(CCTV_Seoul,pop_Seoul, on='구별') 
data_result.head() 

# CCTV에 대한 '소계' 컬럼을 제외한 나머지 CCTV 데이터 삭제
del data_result['2013년도 이전']
del data_result['2014년']
del data_result['2015년']
del data_result['2016년']
data_result.head()

#CCTV와 각 칼럼에 대한 상솬관계 분석
# 상관관계 함수 :np.corrcoef()
np.corrcoef(data_result['고령자비율'],data_result['소계'])
np.corrcoef(data_result['외국인비율'],data_result['소계'])
np.corrcoef(data_result['인구수'],data_result['소계'])
data_result.sort_values(by='소계', ascending=False).head(5)

#csv로 저장시켜주는 함수
data_result.to_csv('data_result.csv')
# 데이터 읽히는지 확인하기
pd.read_csv('data_result.csv', encoding='utf-8')

 

# CCTV와 인구현황 그래프로 분석하기

import platform
import pandas as pd
import numpy as np

# 폰트 설정(특히 한글부분)
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus']=False

data_result = pd.read_csv('data_result.csv', encoding='utf-8')

if platform.system() == 'Darwin':
    rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
    path = "c:/Windows/Fonts/malgun.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc('font', family=font_name)
else:
    print('Unknown system.... sorry')
    
# CCTV 비율을 구하고 그에 따른 시각화 작업
data_result['CCTV비율'] = data_result['소계'] / data_result['인구수'] * 100

data_result['CCTV비율'].sort_values().plot(kind='barh', grid=True, figsize=(10,10))
plt.show()

# 산점도(인구수와 소계)
plt.figure(figsize=(6,6))
plt.scatter(data_result['인구수'], data_result['소계'], s=50)
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()

# 인구수와 CCTV는 상관계수가 양의 값이므로 산점도와 직선
# 직선 구하기 (Polyfit을 이용한 회귀선)
# polyfit 함수를 이용해서 예측 모델 z의 계수를 생성
fp1 = np.polyfit(data_result['인구수'], data_result['소계'],1)
fp1

# 만들어진 예측 모델을 이용한 그래프 그리기
f1 = np.poly1d(fp1) # y축 데이터
fx = np.linspace(100000, 700000, 100) # x축 데이터

plt.figure(figsize = (10, 10))
plt.scatter(data_result['인구수'], data_result['소계'], s=50)
plt.plot(fx, f1(fx), ls='dashed', lw=3, color = 'g')
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()
'''인구수가 310000 정도일 때, cctv는 1100대가 적당하다'''

# 조금더 설득력 있는 자료 만들기
'''
직선이 전체 데이터의 대표값 역할을 한다면 
인구수가 300,000일경우 CCTV는 1100정도여야 한다는 결론
가독성 향상을 위해 오차를 계산할 수 있는 코드 작성후,
오차가 큰 순으로 데이터를 정렬
'''
fp1 = np.polyfit(data_result['인구수'], data_result['소계'],1)

f1 = np.poly1d(fp1) # y축 데이터
fx = np.linspace(100000, 700000, 100) # x축 데이터

data_result['오차'] = np.abs(data_result['소계']- f1(data_result['인구수']))
df_sort = data_result.sort_values(by = '오차', ascending =False)
df_sort.head()

#plot 크기 설정
plt.figure(figsize=(14,10))

#산점도
plt.scatter(data_result['인구수'],data_result['소계'],
            c =data_result['오차'], s=50)

#회귀선
plt.plot(fx,f1(fx),ls='dashed', lw=3, color='g')

#주요 10개 지역 구이름 출력
for n in range(10):
    plt.text(df_sort['인구수'][n]*1.02, df_sort['소계'][n]*0.98,
             df_sort.index[n], fontsize=15)

plt.xlabel('인구수')
plt.ylabel('인구당비율')
plt.colorbar() #오른쪽에 생상바
plt.grid() #가이드라인
plt.show()

 

# =============================================================================
#  강남 3구는 안전한가 ?
# =============================================================================

'''
강남 3구의 주민들이 자신들이 거주하는 구의 체감 안전도를
높게 생각한다는 기사를 확인해보도록 한다.
기사 원문 : 

Matplotlib 의 heatmap 등을 그릴 때
cmap의 디폴트 설정이 변경되어 heatmap 등에서 cmap을 적용할 때
옵션을 잡아주어야 동일한 효과가 나타난다.

Folium 0.4.0으로 버전업 되면서
choropleth 명령에서 geo_str 옵션명이 geo_data 옵션명으로 변경됨.
circle marker 적용할 때, fill=True 옵션을 반드시 사용해야 함.
'''

##########
# 데이터 정리하기
# 필요한 모듈을 import

import numpy as np
import pandas as pd

'''다운받은 데이터(csv) 파일을 읽는다,
콤마(,)로 천단위가 구분되어 있고, 한글 인코딩은 euc-kr
'''

crime_anal_police = pd.read_csv('./data/02. crime_in_Seoul.csv',
                                thousands = ',', encoding='euc-kr')

r=crime_anal_police.head()
print(r)

'''
관서별로 되어 있는 데이터를 소속 구별로 변경
1. 경찰서 이름으로 구 정보 얻기
'''
# 구글 맵스를 사용해서 경찰서의 위치(위도, 경도) 정보를 받아온다.
import  googlemaps

# 자신의 key를 사용.
gmaps_key = "AIzaSyC8BVOCtGMXacY8URBfmH1SWiYIErRWJ5M"
gmaps = googlemaps.Client(key=gmaps_key)
r=gmaps.geocode('서울중부경찰서', language='ko')
print(r)

#중부서, 수서서 => 서울**경찰서로 변경
station_name=[]
for name in crime_anal_police['관서명']:
    station_name.append('서울'+ str(name[:-1])+'경찰서')
    
print(station_name)

# 경찰서 이름을 이용하여 주소 얻기
station_address = []
station_lat =[]
station_lng =[]

for name in station_name:
    tmp = gmaps.geocode(name, language='ko')
    station_address.append(tmp[0].get("formatted_address"))
    
    tmp_loc = tmp[0].get("geometry")
    
    station_lat.append(tmp_loc['location']['lat'])
    station_lng.append(tmp_loc['location']['lng'])
    
    print(name+'-->' + tmp[0].get("formatted_address"))

print(station_address)

station_address

for name in station_name:
    tmp=gmaps.geocode(name,language='ko')
    '''
    [{'address_components': 
        [{'long_name': '617', 
        'short_name': '617', 
        'types': ['premise']}, 
        {'long_name': '개포로', 
        'short_name': '개포로', 
        'types': ['political', 'sublocality', 'sublocality_level_4']},
        {'long_name': '개포동', 'short_name': '개포동', 
        'types': ['political', 'sublocality', 'sublocality_level_2']}, 
        {'long_name': '강남구', 'short_name': '강남구', 
        'types': ['political', 'sublocality', 'sublocality_level_1']},
        {'long_name': '서울특별시', 'short_name': '서울특별시', 
        'types': ['administrative_area_level_1', 'political']}, 
        {'long_name': '대한민국', 'short_name': 'KR', 
        'types': ['country', 'political']}, 
        {'long_name': '135-240', 'short_name': '135-240', 
        'types': ['postal_code']}], 
    'formatted_address': '대한민국 서울특별시 강남구 개포동 개포로 617', 
    'geometry': 
        {'location': {'lat': 37.49349, 'lng': 127.0772119}, 'location_type': 'ROOFTOP', 
            'viewport': 
                {'northeast': {'lat': 37.4948389802915, 'lng': 127.0785608802915}, 
            'southwest': {'lat': 37.49214101970851, 'lng': 127.0758629197085}}}, 
    'place_id': 'ChIJY2ee_TGkfDURAWUtC8jBHag', 
    'plus_code': 
        {'compound_code': 'F3VG+9V 대한민국 서울특별시', 
         'global_code': '8Q99F3VG+9V'}, 
    'types': ['establishment', 'point_of_interest', 'police']
    }]
    '''
    station_address.append(tmp[0].get("formatted_address"))
    #formatted_address': '대한민국 서울특별시 강남구 개포동 개포로 617'
    
    

    tmp_loc=tmp[0].get("geometry")
    #{'location': {'lat': 37.49349, 'lng': 127.0772119}
    
    
    #print(tmp_loc)
    '''
    {'location': {'lat': 37.49349, 'lng': 127.0772119}, 
    'location_type': 'ROOFTOP', 
    'viewport': {'northeast': {'lat': 37.4948389802915, 'lng': 127.0785608802915}, 
    'southwest': {'lat': 37.49214101970851, 'lng': 127.0758629197085}}}
    '''
    station_lat.append(tmp_loc['location']['lat'])
    station_lng.append(tmp_loc['location']['lng'])
    
    print(name+'-->' + tmp[0].get("formatted_address"))
    '''
    서울중부경찰서-->대한민국 서울특별시 중구 을지로동 수표로 27
    서울종로경찰서-->대한민국 서울특별시 종로구 종로1.2.3.4가동 율곡로 46
    서울남대문경찰서-->대한민국 서울특별시 중구 회현동 한강대로 410
    서울서대문경찰서-->대한민국 서울특별시 서대문구 충현동 통일로 113 ....
    '''
print(station_address)
print(station_lng)


'''
금천 경찰서의 경우 관악구로 되어 있어서 금천구로 변경
'''
crime_anal_police[crime_anal_police['관서명']=='금천서']
crime_anal_police.loc[crime_anal_police['관서명']==금천서,
                      ['구별']] =='금천구'

crime_anal_police[crime_anal_police['관서명']=='금천서']

#현재까지 작업 내용 저장.
crime_anal_police.to_csv('./dada/02_crime_in_Seoul_include_gu_name.csv',
                         sep = ',', encoding='utf-8')

####### 범죄데이터 구별로 정리하기
from GangnamSatety_20200423 import station_lng, station_lat
crime_anal_raw = pd.read_csv('./data/02_crime_in_Seoul_include_gu_name.csv', encoding='utf-8')

crime_anal_raw.head()
### pandas의 pivot_table

'''
pd.pivot_table(df,                피벗 테이블을 만들기 위한 기본 데이터
               index = [],        pivot_table의 index를 설정(multi index도 가능)
               columns = [],      원하는 columns을 설정
               values = [],       columns에 해당하는 값
               aggfunc = [],      분석을 위한 파라미터
                                  예) np.sum, np.mean 사용
               fill_value = 0,    Nan 값을 채우기.
               margins = True)    모든 데이터의 결과를 아래에 붙일 것인지 설정

--> 원하는 컬럼을 인덱스화 시켜서 나머지 데이터들을 재정렬시켜주는 것이 피벗 테이블의 역할이다.
'''

# pivot_table을 이용
# 저장한 데이터를 관서별에서 구별로..
crime_anal = pd.pivot_table(crime_anal_raw, index='구별', aggfunc=np.sum)
crime_anal.head()

print(crime_anal)
print(type(crime_anal))
'''
각 범죄별 검거율을 계산하고,
검거 건수는 검거율로 대체한 후, 검거 건수는 삭제
'''

crime_anal['강간검거율'] = crime_anal['강간 검거']/crime_anal['강간 발생']*100
crime_anal['강도검거율'] = crime_anal['강도 검거']/crime_anal['강도 발생']*100
crime_anal['살인검거율'] = crime_anal['살인 검거']/crime_anal['살인 발생']*100
crime_anal['절도검거율'] = crime_anal['절도 검거']/crime_anal['절도 발생']*100
crime_anal['폭력검거율'] = crime_anal['폭력 검거']/crime_anal['폭력 발생']*100


del crime_anal['강간 검거']
del crime_anal['강도 검거']
del crime_anal['살인 검거']
del crime_anal['절도 검거']
del crime_anal['폭력 검거']

print(crime_anal.head())


'''
100이 넘는 숫자들은 100으로 처리
'''

con_list = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']

for columns in con_list:
    crime_anal.loc[crime_anal[column]>100, column] =100
    
print(crime_anal.head())

# 컬럼 뒤에 발생이라는 단어 삭제 : rename()을 이용
crime_anal.rename(columns = {'강간 발생':'강간',
                             '강도 발생':'강도',
                             '살인 발생':'살인',
                             '절도 발생':'절도',
                             '폭력 발생':'폭력',}, inplace = True)

print(crime_anal.head())


################
# 데이터 표현을 위해 전처리 
'''
강도와 살인은 두 자리수,
절도와 폭력은 네 자리수로 구성 되어 있어
각각을 비슷한 범위에 놓고 비교하는 것이 편리하기 때문에
각 컬럼별로 정규화(normalize) 작업

각 항목의 최대값을 1로 두면,
추후 범죄발생 건수를 종합적으로 비교할 때 편리

각각, 강도, 살인, 절도, 폭력에 대하여
각 컬럼별로 정규화(normalize)
'''
'''
파이썬의 머신러닝에 관한 모듈 중
scikit learn에 있는 전처리(preprocessing) 도구에는
최소, 최대값을 이용하여 정규화시키는 함수가 존재 : MinMaxScaler()
'''

from sklearn import preprocessing

col =['강간', '강도', '살인', '절도', '폭력']

x = crime_anal[col].values
min_max_scaler = preprocessing.MinMaxScaler()

x_scaled = min_max_scaler.fit_transform(x.astype(float))

crime_anal_norm = pd.DataFrame(x_scaled, columns = col, index = crime_anal.index)


# 정규화된 데이터프레임에 검거율 추가
col2 = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']

crime_anal_norm[col2] = crime_anal[col2]

print(crime_anal_norm.head())

# CCTV_result.csv 에서 구별 인구수와 CCTV 개수만 추가
result_CCTV = pd.read_csv('./data/01. CCTV_result.csv', encoding='UTF-8', index_col = '구별')

crime_anal_norm[['인구수', 'CCTV']] = result_CCTV[['인구수', '소계']]

print("인구수와 CCTV 개수 =>", crime_anal_norm.head())
# 발생 건수의 합을 '범죄'라는 컬럼으로 합하여 추가

col = ['강간', '강도', '살인', '절도', '폭력']

crime_anal_norm['범죄'] = np.sum(crime_anal_norm[col], axis=1)

print("범죄라는 컬럼으로 합 =>", crime_anal_norm.head())
# 검거율도 통합하여 추가

col = ['강간검거율','강도검거율', '살인검거율','절도검거율','폭력검거율']

crime_anal_norm['검거'] = np.sum(crime_anal_norm[col], axis=1)

print('검거율도 통합 =>', crime_anal_norm.head())

import matplotlib.pyplot as plt

import seaborn as sns # 다수의 상관관계 표현하기 위한 모듈
import platform       # 한글 폰트 설정하기 위한 모듈
import pivotTable_20200423
from pivotTable_20200423 import crime_anal_norm
# 한글 폰트 설정
path = "c:/Windows/Fonts/malgun.ttf"
from matplotlib import font_manager, rc

if platform.system() == 'Darwin':
    rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
    path = "c:/Windows/Fonts/malgun.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc('font', family=font_name)
else:
    print('Unknown system.... sorry')
    
# pairplot() 상관관계 : '강도', '살인', '폭력'

#'''
sns.pairplot(crime_anal_norm, vars=["강도", "살인", "폭력"], kind = 'reg', size=3)
plt.show()
#'''

# pairplot() 상관관계 : "인구수", "CCTV", "살인", "강도"
# '''
sns.pairplot(crime_anal_norm, x_vars=["인구수", "CCTV"], y_vars =["살인","강도"], kind='reg', size=3)
plt.show()
# '''


# pairplot() 상관관계 : "인구수", "CCTV", "살인검거율", "폭력검거율"
sns.pairplot(crime_anal_norm, x_vars=["인구수", "CCTV"], y_vars=["살인검거율", "폭력검거율"], kind='reg', size=3)
plt.show()
'''
살인 및 폭력 검거율과 CCTV의 관계가 음의 상관계수도 보여줌.
인구수와 살인 및 폭력 검거율도 음의 상관관계를 보임.
'''
# pairplot() 상관관계 : "인구수", "CCTV", "절도검거율", "강도검거율"
sns.pairplot(crime_anal_norm, x_vars=["인구수", "CCTV"], y_vars=["절도검거율","강도검거율"],kind = 'reg', size=3)
plt.show()
# 검거율의 합계인 검거 항목 최고 값을 100으로 한정한 후, 그 값으로 정렬
tmp_max = crime_anal_norm['검거'].max()
crime_anal_norm['검거'] = crime_anal_norm['검거'] / tmp_max *100
crime_anal_norm_sort = crime_anal_norm.sort_values(by='검거', ascending=False)
crime_anal_norm_sort.head()
# heatmap 으로 시각화
target_col = ['강간검거율','강도검거율','살인검거율','절도검거율','폭력검거율']

crime_anal_norm_sort = crime_anal_norm.sort_values(by = '검거', ascending=False)

plt.figure(figsize=(10,10))

sns.heatmap(crime_anal_norm_sort[target_col],
            annot=True, fmt='f',
            linewidths=.5,     #linewidth는 칸 간격 의미.
            cmap = 'RdPu')

plt.title('범죄 검거 비율 (정규화된 검거의 합으로 정렬)')
plt.show()

# 발생 건수 정렬하여 heatmap으로 시각화
target_col = ['강간', '강도', '살인' ,'절도', '폭력', '범죄']

crime_anal_norm['범죄'] = crime_anal_norm['범죄'] / 5

crime_anal_norm_sort = crime_anal_norm.sort_values(by ='범죄', ascending=False)
plt.figure(figsize=(10,10))
sns.heatmap(crime_anal_norm_sort[target_col],
            annot=True, fmt='f',
            linewidths=.5,
            cmap='RdPu')

plt.title("범죄비율 (정규화 된 발생 건수로 정렬)")
plt.show()

import json

geo_path = './data/02. skorea_municipalities_geo_simple.json'
geo_str = json.load(open(geo_path, encoding='utf-8'))

crime_anal_raw['lat'] = station_lat
crime_anal_raw['lng'] = station_lng

col = ['살인 검거', '강도 검거', '강간 검거', '절도 검거', '폭력 검거']
tmp = crime_anal_raw[col] / crime_anal_raw[col].max()

crime_anal_raw['검거'] = np.sum(tmp, axis=1)

crime_anal_raw.head()

import folium
import webbrowser


################
# 지도를 이용한 시각화 작업을 위해 지도의 중심 좌표를 이용하여 12배 확대
map = folium.Map(location = [37.5502, 126.982], zoom_start=12)

# 로드된 지도 위에 각 경찰서의 검거율을 x10 배수의 크기(반지름)로 원을 그려준다.(외경 선과 내면 색 지정)
# .add_to()함수로 불러온 map 에 더해줌
for n in crime_anal_raw.index:
    folium.CircleMarker([crime_anal_raw['lat'][n], crime_anal_raw['lng'][n]],
                        radius = crime_anal_raw['검거'][n]*10,
                        color = '#3186cc',
                        fill_color = '#3186cc',
                        fill=True).add_to(map)

# map html파일로 저장 후 열기
map
map.save('folium_kr2.html')
webbrowser.open_new("folium_kr2.html")

##############
map = folium.Map(location = [37.5502, 126.982], zoom_start=12)

map.choropleth(geo_data=geo_str,
               data = crime_anal_norm['범죄'],
               columns = [crime_anal_norm.index, crime_anal_norm['범죄']],
               fill_color='PuRd',   #PuRd, YlGnBu
               key_on = 'feature.id')

for n in crime_anal_raw.index:
    folium.CircleMarker([crime_anal_raw['lat'][n], crime_anal_raw['lng'][n]],
                        radius = crime_anal_raw['검거'][n]*10,
                        color = '#3186cc',
                        fill_color = '#3186cc',
                        fill=True).add_to(map)

map.save('folium_kr3.html')
webbrowser.open_new("folium_kr3.html")

 

# =============================================================================
# 위에는 TL_SCCO_SIG_WGS84.json, Total_People_2018.csv 데이터로 맵 구역별로 나눈거 하기
# 아래는 외국인 거주자 인구수 데이터
# =============================================================================

import matplotlib.pyplot as plt

import seaborn as sns # 다수의 상관관계 표현하기 위한 모듈
import platform       # 한글 폰트 설정하기 위한 모듈
import pandas as pd
import numpy as np

import json

import folium
import webbrowser


pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls', encoding='utf-8')

pop_Seoul.head()

pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls',
                          header=2, # 2줄 건너뛰고 읽어온다
                          usecols='B, D, J', # 원하는 셀만 골라서 가져오기
                          encoding='utf-8')

pop_Seoul.head() 

# 알기 쉬운 컬럼명으로 변경
pop_Seoul.rename(columns={pop_Seoul.columns[0]:'구별',
                          pop_Seoul.columns[1]:'인구수',
                          pop_Seoul.columns[2]:'외국인거주인구'}, inplace=True)
pop_Seoul.head()

pop_Seoul.drop([0], inplace=True)
pop_Seoul.head()


# '구별' 컬럼의 중복값제거
pop_Seoul['구별'].unique()

# '구별' 컬럼의 NULL 값 확인
pop_Seoul[pop_Seoul['구별'].isnull()] # NULL 값이 있는 행 번호 & 값들을 함께 반환시켜준다.

# '구별' 컬럼의 NULL값 있는 행 제거
pop_Seoul.drop([26],inplace=True)
pop_Seoul.head()

#비율 추가
pop_Seoul['외국인비율']=pop_Seoul['외국인거주인구']/pop_Seoul['인구수']*100

#각 컬럼 확인
pop_Seoul.sort_values(by='인구수', ascending=False).head()
pop_Seoul.sort_values(by='외국인거주인구', ascending=False).head()

# 시각화 작업을 위한 구 이름('구별')을 index 화
pop_Seoul.set_index('구별', inplace=True)
pop_Seoul


geo_path = './data/02. skorea_municipalities_geo_simple.json'
geo_str = json.load(open(geo_path, encoding='utf-8'))

# # 지도를 이용한 시각화 작업을 위해 지도의 중심 좌표를 이용하여 12배 확대
map = folium.Map(location = [37.5502, 126.982], zoom_start=12)

map.choropleth(geo_data=geo_str,
               data = pop_Seoul['외국인비율'],
               columns = [pop_Seoul.index, pop_Seoul['외국인비율']],
               fill_color='PuRd',
               key_on = 'feature.id')

map.save('folium_foreingn.html')
webbrowser.open_new("folium_foreingn.html")
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 23 09:49:21 2020

@author: admin
"""

'''
서울시 구별 CCTV 현황 분석하기

서울시 각 구별 CCTV 수를 파악하고,
인구대비 CCTV 비율을 파악해서 순위 비교

인구대비 CCTV의 평균치를 확인하고
그로부터 CCTV가 과하게 부족한 구를 확인

Python 기본 문법 / Pandas 와 Matplotlib의 기본적 사용법을 이용한 시각화
단순한 그래프 표현에서
한 단계 더 나아가 경향을 확인하고 시각화하는 기초 확인
 
'''
import pandas as pd
import numpy as np

# CCTV 데이터와 인구 데이터 합치고 분석하기

##CCTV 데이터 읽기
CCTV_Seoul = pd.read_csv('./data/01. CCTV_in_Seoul.csv', encoding='UTF-8')
#데이터프레임
CCTV_Seoul.head()

CCTV_Seoul.columns

CCTV_Seoul.columns[0]

#칼럼명 변경 : 기관명을 구별로 변경 
CCTV_Seoul.rename(columns={CCTV_Seoul.columns[0]:'구별'}, inplace=True)
CCTV_Seoul.head()


# 인구데이터 읽기 1
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls', encoding='UTF-8')
pop_Seoul.head()

#인구 데이터 읽기2 - 필요한 데이터만 선별하여 읽기
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls',
                          header=2, # 헤더 두 줄 건너 뛰고 나타내라
                          usecols='B, D, G, J, N', # 사용할 컬럼 지정
                          encoding='utf-8')

pop_Seoul.head()

#계라고 나오는 컬럼을 알기 쉬운 컬럼명으로 변경
pop_Seoul.rename(columns={pop_Seoul.columns[0]:'구별',
                          pop_Seoul.columns[1]:'인구수',
                          pop_Seoul.columns[2]:'한국인',
                          pop_Seoul.columns[3]:'외국인',
                          pop_Seoul.columns[4]:'고령자'},inplace=True)

pop_Seoul.head()

#CCTV 데이터 파악하기
# 소계 순으로 정렬(오름차순)
CCTV_Seoul.sort_values(by='소계', ascending=True).head(5)
# 소계 순으로 정렬(내차순)
CCTV_Seoul.sort_values(by='소계', ascending=False).head(5)
#sort_values : 원본에 정렬순으로 저장되는 것은 아니다.


# 최근증가율 = (2016년+2015년+2014년)/2013년도 이전 * 100
CCTV_Seoul['최근증가율']=(CCTV_Seoul['2016년']+CCTV_Seoul['2015년']+ \
                     CCTV_Seoul['2014년']) / CCTV_Seoul['2013년도 이전'] * 100
    
    
CCTV_Seoul.sort_values(by='최근증가율', ascending=False).head()


#서울시 인구데이터 파악하기
pop_Seoul.head()

#첫번째 합계 행 삭제
pop_Seoul.drop([0],inplace=True)
pop_Seoul,head()

#'구별' 칼럼의 중복값 제거
pop_Seoul['구별'].unique()

#'구별' 칼럼의 NULL 값 확인
#isnull() : 널값의 행값과 널값을 인덱스 번호를 반환 시켜준다.
#     구별  인구수  한국인  외국인  고령자
#26  NaN  NaN  NaN  NaN  NaN
pop_Seoul[pop_Seoul['구별'].isnull()]

# '구별' 컬럼의 NULL값 있는 행 제거
pop_Seoul.drop([26],inplace=True)
pop_Seoul.head()

'''
데이터 분석
1.분석데이터 수집(R or python )
2.수집된 데이터 형식 확인 및 로컬 전처리
3.분석 prg에서 수집 데이터 읽기
4.읽은 데이터 확인 및 3차 전처리
'''

#외국인비율과 고령자 비율 추가
pop_Seoul['외국인비율']=pop_Seoul['외국인']/pop_Seoul['인구수']*100
pop_Seoul['고령자비율']=pop_Seoul['고령자']/pop_Seoul['인구수']*100
pop_Seoul.head()

# 각 칼럼 확인
pop_Seoul.sort_values(by='인구수', ascending=False).head()
pop_Seoul.sort_values(by='외국인', ascending=False).head()
pop_Seoul.sort_values(by='외국인비율', ascending=False).head()
pop_Seoul.sort_values(by='고령자', ascending=False).head()
pop_Seoul.sort_values(by='고령자비율', ascending=False).head()

# 시각화 작업을 위함 구이름('구별')을 index화
data_result.set_index('구별', inplace=True)
data_result.head()


###CCTV 데이터와 인구 데이터 합치고 분석하기

# 두개의 데이터프레임을 합할 경우 동일 컬럼명은 하나('구별')로 통일 된다.
data_result = pd.merge(CCTV_Seoul,pop_Seoul, on='구별') 
data_result.head() 

# CCTV에 대한 '소계' 컬럼을 제외한 나머지 CCTV 데이터 삭제
del data_result['2013년도 이전']
del data_result['2014년']
del data_result['2015년']
del data_result['2016년']
data_result.head()

#CCTV와 각 칼럼에 대한 상솬관계 분석
# 상관관계 함수 :np.corrcoef()
np.corrcoef(data_result['고령자비율'],data_result['소계'])
np.corrcoef(data_result['외국인비율'],data_result['소계'])
np.corrcoef(data_result['인구수'],data_result['소계'])
data_result.sort_values(by='소계', ascending=False).head(5)

#csv로 저장시켜주는 함수
data_result.to_csv('data_result.csv')
# 데이터 읽히는지 확인하기
pd.read_csv('data_result.csv', encoding='utf-8')

 

# CCTV와 인구현황 그래프로 분석하기

import platform
import pandas as pd
import numpy as np

# 폰트 설정(특히 한글부분)
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus']=False

data_result = pd.read_csv('data_result.csv', encoding='utf-8')

if platform.system() == 'Darwin':
    rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
    path = "c:/Windows/Fonts/malgun.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc('font', family=font_name)
else:
    print('Unknown system.... sorry')
    
# CCTV 비율을 구하고 그에 따른 시각화 작업
data_result['CCTV비율'] = data_result['소계'] / data_result['인구수'] * 100

data_result['CCTV비율'].sort_values().plot(kind='barh', grid=True, figsize=(10,10))
plt.show()

# 산점도(인구수와 소계)
plt.figure(figsize=(6,6))
plt.scatter(data_result['인구수'], data_result['소계'], s=50)
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()

# 인구수와 CCTV는 상관계수가 양의 값이므로 산점도와 직선
# 직선 구하기 (Polyfit을 이용한 회귀선)
# polyfit 함수를 이용해서 예측 모델 z의 계수를 생성
fp1 = np.polyfit(data_result['인구수'], data_result['소계'],1)
fp1

# 만들어진 예측 모델을 이용한 그래프 그리기
f1 = np.poly1d(fp1) # y축 데이터
fx = np.linspace(100000, 700000, 100) # x축 데이터

plt.figure(figsize = (10, 10))
plt.scatter(data_result['인구수'], data_result['소계'], s=50)
plt.plot(fx, f1(fx), ls='dashed', lw=3, color = 'g')
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()
'''인구수가 310000 정도일 때, cctv는 1100대가 적당하다'''

# 조금더 설득력 있는 자료 만들기
'''
직선이 전체 데이터의 대표값 역할을 한다면 
인구수가 300,000일경우 CCTV는 1100정도여야 한다는 결론
가독성 향상을 위해 오차를 계산할 수 있는 코드 작성후,
오차가 큰 순으로 데이터를 정렬
'''
fp1 = np.polyfit(data_result['인구수'], data_result['소계'],1)

f1 = np.poly1d(fp1) # y축 데이터
fx = np.linspace(100000, 700000, 100) # x축 데이터

data_result['오차'] = np.abs(data_result['소계']- f1(data_result['인구수']))
df_sort = data_result.sort_values(by = '오차', ascending =False)
df_sort.head()

#plot 크기 설정
plt.figure(figsize=(14,10))

#산점도
plt.scatter(data_result['인구수'],data_result['소계'],
            c =data_result['오차'], s=50)

#회귀선
plt.plot(fx,f1(fx),ls='dashed', lw=3, color='g')

#주요 10개 지역 구이름 출력
for n in range(10):
    plt.text(df_sort['인구수'][n]*1.02, df_sort['소계'][n]*0.98,
             df_sort.index[n], fontsize=15)

plt.xlabel('인구수')
plt.ylabel('인구당비율')
plt.colorbar() #오른쪽에 생상바
plt.grid() #가이드라인
plt.show()

 

# 강남 3구는 안전한가?

 

 

# -*- coding: utf-8 -*-
# db 연결
import sqlite3
con = sqlite3.connect("C:/pythonwork/naver_db")
import pandas as pd
from pandas import Series, DataFrame

readed_df = pd.read_sql("SELECT * FROM naver_table", con)
print(readed_df.describe())


# 문제1. 평균/최대/최소/4분위 값을 각각 구하시오

# 평균
mean=readed_df["가격"].mean()
print(mean)
# 최대
max=readed_df["가격"].max()
print(max)
# 최소
min=readed_df["가격"].min()
print(min)

# 4분위
import pandas as pd
quantile=readed_df["가격"].quantile()
total=pd.DataFrame({"4분위값":quantile},index=[0])
print(total)


# 문제2. 읽어들인 데이터를 MatplotLib으로 구하시오
import matplotlib.pyplot as plt
plt.plot(readed_df["제품명"], readed_df["가격"])

print(read_df)
con.commit()
con.close()

 

# BeautifulSoup 사용하기

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc,'html.parser')

# html 문서의 계층 구조를 알기 쉽게 보여준다.(마치 코드 처럼)
print(soup.prettify()) 
''''
<html>
 <head>
  <title>
   The Dormouse's story
  </title>
 </head>
 <body>
  <p class="title">
   <b>
    The Dormouse's story
   </b>
  </p>
  <p class="story">
   Once upon a time there were three little sisters; and their names were
   <a class="sister" href="http://example.com/elsie" id="link1">
    Elsie
   </a>
   ,
   <a class="sister" href="http://example.com/lacie" id="link2">
    Lacie
   </a>
   and
   <a class="sister" href="http://example.com/tillie" id="link3">
    Tillie
   </a>
   ;
and they lived at the bottom of a well.
  </p>
  <p class="story">
   ...
  </p>
 </body>
</html>
'''

#타이틀 태그나 태그명을 추출하고 싶을 경우
soup.title
print(soup.title)
#<title>The Dormouse's story</title>

# 타이틀 태그의 이름('title')을 반환
soup.title.name
print(soup.title.name)
# title

#타이틀태그의 문자열을 반환
soup.title.string
print(soup.title.string)
#The Dormouse's story

# 타이틀 태그의 부모 태그의 이름을 반환
soup.title.parent.name
print(soup.title.parent.name)
# head

# 첫 p 태그를 반환
soup.p
print(soup.p)
#<p class="title"><b>The Dormouse's story</b></p>

#'class' 속성이 있는 첫 p태그를 반환
print(soup.p['class'])
# ['title']

# 첫 a 태그를 반환
soup.a
print(soup.a)
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>


#모든 a태그를 리스트 형태로 반환
soup.find_all()
print(soup.find_all('a'))
#[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

# soup.find() 설정한 값에 해당하는 태그를 반환.
# id가 link3인 태그를 반환.
soup.find(id="link3")
#<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>


#.get() : href 속성을 반환.
for link in soup.find_all('a'):
    print(link.get('href'))

#http://example.com/elsie
#http://example.com/lacie
#http://example.com/tillie


#get_text() :html 문서 안에 있는 텍스트를 반환
print(soup.get_text())
'''
The Dormouse's story

The Dormouse's story
Once upon a time there were three little sisters; and their names were
Elsie,
Lacie and
Tillie;
and they lived at the bottom of a well.
...

-----------------------------------------------------------------
#requests 기본 사용

html 소스 가져오기
requests를 사용하면 아래와 같이 간단한 코드만으로
웹페이지의 html 소스를 가져올 수 있다.
'''

import requests

'''
웹페이지의 content를 유니코드 형태가 아니라 bytes 형태로 얻기 위해서는
r.text가 아닌 r.content를 사용할 수도 있다.
'''
r = requests.get('https://google.com')
html = r.content
print(html)


#response 객체 ㅣesquest.get()의 반환 객체
'''
response 객체는 HTTP request에 의한 서버의 응답 정보를 갖고 있다,
starus_code, headers, encoding, ok등의 속성을 이용하면
다양한 정보를 얻을 수 있디.
'''
r = requests.get('https://google.com')
html = r.content

print(r.status_code)
print(r.headers['Content-Type'])
print(r.encoding)
print(r.ok)

'''
status_code는
정상일 경우 200, 페이지가 발견되지 않을 경우 404

encoding 방식은 ISO-8859-1이고
요청에 대한 응답이 정상적으로 이루어 졌음을 알 수 있다.

(status_code가 200 보다 작거나 같은 경우 True, 그렇지 않는 경우 False)
'''
'''
만약 인코딩 방식이 달라서 한글이 재대로 표시되지 않으면
아래와 같이 인코딩 방식을 변경.
'''

r.encoding ='UTF-8'

'''
requests를 이용해서 html 소스를 가져왔지만
단순한 문자열 형태이기 때문에 파싱(parsing)에 적합하지 않다.
그렇기 떄문에 BeautifulSoup으f 이용해서
파이썬 html 소스를 분석하고 데이터를 추출하기 편리하도록
객체로 변환
'''

# 많이 본 네이버 뉴스
'''
파이썬 과 BeautifulSoup을 이용하면
이 웹 크롤러를 간단하게 만들 수 있다.
네이버 뉴스의 많이 본 뉴스를 가져오기
'''

import requests
from bs4 import BeautifulSoup

'''
https://news.naver.com/main/ranking/popularDay.nhn?rankingType=popular_day&date=20190430

위의 주소에서 알 수 있듯이 맨위에 날짜를 바꿔주면 
해당하는 날짜의 많이 본 뉴스를 볼 수 있다.
'''

url = 'https://news.naver.com/main/ranking/popularDay.nhn?rankingType=popular_day&date=20190430'

r = requests.get(url)
html = r.content
soup = BeautifulSoup(html,'html.parser')

# 태그안에 태그를 찾고 싶다.
# 원하는 데이터 추출하기
# 네이버 많이 본 뉴스 페이지에서 헤드라인만 추출해서 출력

titles_html = soup.select('.ranking_section > ol >li >dl >dt >a')

# 30개의 헤드라인이 순서대로 출력
for i in range(len(titles_html)):
     print(i+1, titles_html[i].text)
    
# 삼성전자 주식 일별 시세 가져오기
 '''
네이버 증권에서 제공하는
삼성전자 종목(005930)의 일별 시세를 가져오가

주소:http://finance.naver.com/item/sise_day.nhn?code=005930
위의 주소와 같이 뒷부분에
code=005930와 같이 종목코드를 입력해주면
해당 종목의 일별시세를 볼 수 있다.
'''

#원하는 데이터 추출하기
'''
종목의 일별시세 페이지에서
날짜,종가, 거래량만 추출해서 출력해보겠다,

개발자 도구 (컨트롤 + 쉬프트 +i 또는 F12)를 통해 소스를보면
날짜, 종가, 거래량이 나온 부분을 찾을 수 있다.

'table', 'tr', 'td'태그 안의 텍스트임을 할 수 있다.
'''

import requests
from bs4 import BeautifulSoup as bs

#종목의 코드와 페이지 수를 입력하는 함수.
def print_stock_price(code,page_num):
    #result에는 날짜, 종가, 거래량이 추가된다.
    result = [[],[],[]]

    #주소 뒷부분에 &page=2와 같은 형식으로 연결해주면
    #해당페이지의 일별시세를 볼 수 있다.
    for n in range(page_num):
        url="http://finance.naver.com/item/sise_day.nhn?code="+code+'&page='+str(n+1)

        r = requests.get(url)
        html = r.content
        soup = bs(html,"html.parser")

        #table 안의 tr태그를 리스트형태로 가져온다.
        tr = soup.select('table>tr')

        #첫번째 tr태그는 th태그가,
        #마지막 tr태그는 페이지 넘버가 있어서 제외
        for i in range(1, len(tr)-1):
            #text가 없는 row가 존재.
            if tr[i].select('td')[0].text.strip():
                #text가 있는 row에 대해서
                #첫번째(날짜),두번재(종가),일곱번째(거래량)
                #td태그의text를 가져온다.
                result[0].append(tr[i].select('td')[0].text.strip())
                result[1].append(tr[i].select('td')[1].text.strip())
                result[2].append(tr[i].select('td')[6].text.strip())

    for i in range(len(result[0])):
        print(result[0][i],result[1][i],result[2][i])
#------------------------print_stock_price end
            
#해당 종목의 코드와 50페이지를 입력
stock_code = '005930'
pages = 50

#날짜, 종가, 거래량이 최근순으로 출력
print_stock_price(stock_code,pages)

'''
Matplotlib 기본 사용

Matplotlib 라이브러리를 이용하여 그래프를 그리는 일반적인 방밥

#pyplot 소개

matplotlib.pyplot은
Matplotlib을 MATLAB과 비슷하게 동작하도록 명력어 스타일의 함수의 모음
각각의 pyplot 함수를 사용해서 그림(figure)에 변화를 줄 수 있다.
예를 들어
그림을 만들어서 플롯 영역을 만들고
몇개의 라인을 플롯하고
(label)라벨들로 꾸미는 등의 일을 할 수 있다.
'''

# 기본 그래프
'''
pyplot으로 어떤 값들을 시각화하는 것은 매우 간단.
pyplot.polt()에 하나의 리스트를 입력함으로써 그래프가 그려진다.

matplotlib은 리스트의 값들이 y 값들이라고 가정하고
x값들 ([1,2,3,4])을 자동으로 만들어낸다.
'''
import matplotlib.pyplot as plt

plt.plot([1,2,3,4])
plt.ylabel('y-label')
plt.show()  

'''
plot()은 다재다능한(versatile)한 명령어여서,
임의의 개수의 인자를 받을 수 있다,
예를 들어 아래와 같이 입력하면 x와 y 값을 그래프로 나타낼수 있다.
'''
plt.plot([1,2,3,4],[1,4,9,16])

# 스타일 지정하기

'''
x,y값 인자에 대해
색상과 선의 형태를 지정하는 포맷 문자열을 세번쨰 인자에 입력할 수 있다.
디폴드 포맷 문자열은 'b-'인데 파란색의 선(line,'-')을 의미
아래의 'ro'는 빨간색의 원형(circle,'o') 마커를 의미
'''

import matplotlib.pyplot as plt
plt.plot([1,2,3,4],[1,4,9,16],'ro')

#axis()를 이용하여 축의 [xmin,xmax,ymin,ymax]범위를 지정
plt.axis([0,6,0,20])
plt.show()


#여러 개의 그래프 그리기
'''
matplotlib에서 리스트만 가지로 작업하는 것은 제한적이기 떄문에,
일반적으로 Numpy 어레이를 이용
사실, 모든 시퀸스는 내부적으로 Numpy 어레이로 반환 된다.
'''
#다양한 포맷스타일의 여러 개의 라인을 하나의 그래프로 그리기

import matplotlib.pyplot as plt
import numpy as np

#200ms 간격으로 균일한 샘플된 시간
t=np.arange(0.,5.,0.2)


#빨간 대쉬, 파란 사각형 녹색 삼각형

plt.plot(t,t,'r--',t,t**2,'bs',t,t**3,'g^')
plt.show()     

'''
Matplotlib라벨 설정하기

xlable(), ylabel() 함수를 사용해서
그래프의 x,y축에 대한 라벨을 설정 할 수 있다.

plt.polt([1,2,3,4],[1,4,9,16]) 

xlable(), ylabel()에 텍스트를 입력해주면 각각의 축에 라벨이 나타난다.
'''
import matplotlib.pyplot as plt
plt.plot([1,2,3,4],[1,4,9,16])
plt.xlabel('X-Label')
plt.ylabel('Y-Label')
plt.axis([0,5,0,20])
plt.show()

'''
axis()에 [xmin,xmax,ymin,ymax]의 형태로 x,y축의 범위를 지정
입력 리스트는 꼭 네개의 값 [xmin,xmax,ymin,ymax]이 있어야 한다.

입력값이 없으면 데이터에 맞게 자동(Auto)으로 범위를 지정.
'''


'''
Matplotlib 색깔 지정하기
자주 사용하는 색깔 외에도 다양한 색상을 지정할 수 있다.
polt()에 color='springgreen' 과 같이 입력해주면 색상이 적용된다..
'''
import matplotlib.pyplot as plt
plt.plot([1,2,3,4],[1,4,9,16],color='springgreen')
plt.xlabel('X-Label')
plt.ylabel('Y-Label')
plt.axis([0,5,0,20])
plt.show()

'''
Matplotlib 색깔 지정하기2
16진수 코드(hex code)로도 색깔을 지정할 수 있다.
색깔, 마커와 선의 종류까지 모두 지정

색깔은 '#e35f62'와 같이 16진수로, 마커는 circle,
선의 종류는 대쉬(dashed)로 지정
'''
import matplotlib.pyplot as plt
plt.plot([1,2,3,4],[1,4,9,16], color='#e35f62', marker='o', linestyle='--')
plt.xlabel('X-Label')
plt.ylabel('Y-Label')
plt.axis([0,5,0,20])
plt.show()
'''
Matplotlib 여러 곡선 그리기
세 개의 곡선을 하나의 그래프에 그리기
'''
import matplotlib.pyplot as plt
import numpy as np
'''
Numpy를 사용해서 array를 생성
numpy.array()
주어진 각격에 따라 균일한 array를 생성한다
'''
a=np.arange(5)#범위 [0 1 2 3 4]
b=np.arange(1,5) # [1 2 3 4]
c=np.arange(2,10,2)# [2 4 6 8]

print(a) 
print(b)
print(c)

'''
array a는 [0. , 0.2, 0.4, 0.6, 0.8, 1. , 1.2, 1.4, 1.6, 1.8]
'''
a = np.arange(0,2,0.2)
'''
plot() 에 x 값, y 값, 스타일을 순서대로 세 번씩 입력하면, 
세 개의 곡선 (y=x, y=x^2, y=x^3)이 동시에 그려진다.
'''

plt.plot(a,a,'r--',
         a,a**2,'bo',
         a,a**3,'g-')
'''
'r--':빨간색의 대쉬 스타일 선
'bo' : 파란색의 circle 마커
'g-' :녹색의 대쉬-닷 스타일 선을 의미
'''
#세 개의 곡선의 세세한 스타일을 설정 할 수 있다.
import matplotlib.pyplot as plt
import numpy as np

a = np.arange(0, 2, 0.2)

# 첫 번째 곡선의 스타일은 'bo'로,
plt.plot(a, a, 'bo')

# 두 번째 곡선은 color='#e35f62', marker='*', linewidth=2로,
plt.plot(a, a**2, color='#e35f62', marker='*', linewidth = 2)

# 세 번째 곡선은 color='springgreen, marker='^', markersize=9로
plt.plot(a, a**3, color='springgreen', market='^', markersize=9)


'''
Matplotlib 그리드와 틱 설정하기

grid() 와 tick_parms()를 이용해서
그래프의 그리드와 틱의 스타일을 설정할 수 있다.
'''
import matplotlib.pyplot as plt
import numpy as np

a = np.arange(0, 2, 0.2)

# 첫 번째 곡선의 스타일은 'bo'로,
plt.plot(a, a, 'bo')

# 두 번째 곡선은 color='#e35f62', marker='*', linewidth=2로,
plt.plot(a, a**2, color='#e35f62', marker='*', linewidth = 2)

# 세 번째 곡선은 color='springgreen, marker='^', markersize=9로
plt.plot(a, a**3, color='springgreen', market='^', markersize=9)

'''
그리드가 표시되도록하려면,
grid()의 첫번째 파라미터를 True로 설정

axis='y'로 설정하면 y축의 그리드만 표시

alpha는 투명도를 설정합니다
0으로 설정하게되면 투명
1은 불투명

linestyle을 대쉬(Dached)로 설정
'''
plt.grid(True, axis='y', color='gray', alpha=0.5, linestyle='--')

'''
tick_parms() 를 이용해서 그래프의 틱에 관련되 설정을 할 수 있다
 
axis='both'로 설정하면 x,y축의 틱에 모두 적용
 
direction='in'으로 틱의 방향을 그래프 안쪽으로 설정
 
틱의 길이를 3만큼하고
틱과 라벨의 거리를 6만큼
틱 라벨의 크기를 14로 설정
'''
plt.tick_params(axis='both', direction='in', length=3, pad=6, labelsize=14)

plt.show()

# Matplotlib 타이틀 설정하기
# title() 을 이용해서 그래프의 제목(타이틀)을 설정.
'''
plt.title()을 이용해서 그래프의 타이틀을 'Sample graph'로 설정.
'''
plt.title('Sample graph')
plt.show()

# 2 - 위치와 오프셋
plt.title('Sample graph', loc = 'right', pad=20)
'''
loc ='right'로 설정하면,
타이틀이 그래프의 오른쪽 위에 나타나게 된다.

'left', 'center', 'right'로 설정할 수 있으며
디폴트는 'center'

pad = 20 은
타이틀과 그래프와의 간격(오프셋)을 포인트 단위로 설정.
'''
# 3- 폰트 설정
'''
fontdict 에 딕셔너리 형태로 폰트에 대한 설정을 입력할 수 있다.
'fontsize'를 16으로, 'fontweight'를 'bold'로 설정.

'fontsize'는 포인트 단위의 숫자를 입력하거나,
'smaller', 'x-large' 등의 상대적인 설정을 할 수 있다.

'fontweight'에는 'normal', 'bold', 'heavy', 'light', 'ultrabold', 'ultralight'의
설정을 할 수 있다.
'''
title_font = {
    'fontsize':16,
    'fontweight':'bold'
    }
plt.title('Sample graph',fontdict=title_font, loc = 'left', pad=20)

# Marplotlib 막대그래프 그리기
'''
bar() 함수를 이용해서 막대 그래프(bar graph)를 그릴 수 있다.
연도별 값을 갖는 데이터를 막대 그래프로 플롯.
'''
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(3)

# years는 x축에 표시될 연도이고, values는 y값.
years = ['2017', '2018', '2019']
values = [100, 400, 900]

# 먼저 bar() 함수에 x(=[0, 1, 2])와 값(=[100, 400, 900])을 입력.
plt.bar(x, values)
values = [100, 400, 900]

# 먼저 bar() 함수에 x(=[0,1,2])와 값(=[100,400,900])을 입력.
plt.bar(x, values)

'''
xticks()에 x와 years를 입력해주면,
x축에 '2017', '2018', '2019'가 순서대로 표시된다.

'''
plt.xticks(x,years)
plt.show()

'''
막대그래프에도
막대와 테두리의 색, 두께 등 다양한 스타일을 적용할 수 있다.

우선 bar() 함수에 x, y(=values)값을 입력.
'''

plt.bar(x, values,
        width=0.6,
        align='edge',
        color='springgreen',
        edgecolor='gray',
        linewidth=3,
        tick_label=years,
        log=True)

'''
barh()를 이용하면 수평 막대 그래프를 그릴 수 있다.
'''
y = np.arange(3)
plt.barh(y,values,
         height=-0.6,
         color='springgreen',
         edgecolor='gray',
         linewidth=3,
         tick_label=years,
         log=False)
plt.show()

# https://matplotlib.org/contents
# 여기서 필요한 모양의 그래프들과 소스를 확인 및 다운할 수 있다.


# Numpy 난수 생성(Random 모듈)
# 난수 생성에 활용할 수 있는 Numpy의 random 모듈(numpy.random)

# 1- random.rand() : 주어진 형태의 난수를 생성.
import numpy as np

# 예제1
'''
만들어진 난수 array는 주어진 값에 의해 결정되며,
(0,1) 범위에서 귬일한 분포를 갖는다.
'''
a = np.random.rand(5)
print(a)
'''
결과 : [0.75004981 0.21139253 0.45048688 0.94381202 0.00407233]
'''

'''
random.rand() 주어진 형태의 난수 array를 생성

random.randint() [최저값, 최대값]의 범위에서 임의의 정수

random.randn() 표준정규분포(standard normal distribution)를 갖는 난수를 반환

random.standard_normal() : randn()과 standard_normal() 은 기능이 비슷하지만, 
                        standard_normal()은 튜플을 인자로 받는다는 점에서 차이가 있다.
                        
random.random_sample() : [0.0, 1.0) 범위의 임의의 실수를 반환
                          
random.choice() : 주어진 1차원 어레이에서 임의의 샘플을 생성

random.seed() : 난수 생성에 필요한 시드를 정한다. 코드를 실행할 때 마다 똑같은 난수가 생성
'''

# Matplotlib 산점도 그리기
# scatter() 를 이용해서 산점도(scatter plot)를 그릴 수 있다.

import matplotlib.pyplot as plt
import numpy as np
'''
np.random.seed() 를 통해서 난수 생성의 시드를 설정하면,
같은 난수를 재사용할 수 있다.

seed() 에 들어갈 파라미터는
0에서 4294967295 사이의 정수여야 한다.
'''

# 1 - random.rand() : 주어진 형태의 난수를 생성.
import numpy as np

'''
만들어진 난수 array는 주어진 값에 의해 결정되며,
[0, 1) 범위에서 균일한 분포를 갖는다.
'''

a = np.random.rand(5)
print(a) # 결과 : [0.44859207 0.21580016 0.1010523  0.0087913  0.7022354 ]
    
b = np.random.rand(2, 3)
print(b)
'''
결과 : 
    [[0.70633485 0.24791576 0.15788335]
     [0.69769852 0.71995667 0.25774443]]
'''
'''
x, y의 위치, 마커의 색(colors)과 면적(area)을 무작위로 지정.

예를 들어, x는
[0.7000003, 0.721613,... , 0.234654, 0.3216541]으로
0에서 1사이의 무작위한 50개의 값을 갖는다.
'''

N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = (30 * np.random.rand(N))**2  

'''
scatter()에 x,y 위치를 입력
s 는 마커의 면적을
c 는 마커의 색을 지정
alpha는 마커색의 투명도를 결정
'''
plt.scatter(x,y, s=area,c=colors, alpha=0.5)
plt.show()

'''
matplotlib 히스토그램 그리기
hist()를 이용해서 히스토그램을 그리기

1- 값입력하기
'''

import matplotlib.pyplot as plt
'''weight 리스트는 몸무게 값을 나타낸다.'''
weight = [68,81,64,56,78,74,61,77,66,68,59,
          71,80,59,67,81,69,73,69,74,70,65]
''' hist()함수에 리스트의 형태로 값들을 직접 입력해주면 된다.'''
plt.hist(weight)

2- 여러개의 히스토그램 그리기

import matplotlib.pyplot as plt
import numpy as np
'''
Numpy의 np.random.randn()와
np.random.standard_normal(), np.random.rand() 함수를 이용해서
임의의 값들을 생성
'''
# array a는 표준편차 2.0, 평균 1.0을 갖는 정규분포
a = 2.0 * np.random.randn(10000) + 1.0

# array b 는 표준정규분포를 따른다.
b = np.random.standard_normal(10000)

# array c는 -10.0 에서 10.0 사이의 균일한 분포를 갖는 5000개의 임의의 값.
c = 20.0*np.random.rand(5000) - 10.0

'''
세 개의 분포를 동시에 그래프에 나타내기.
plt.hist()

bins는 몇 개의 영역으로 쪼갤지를 설정.

density=True 로 설정해주면,
밀도함수가 되어서 막대의 아래 면적이 1이 된다.

alpha는 투명도를 의미합니다. 0.0에서 1.0사이의 값을 갖는다.
histtype 을 'step'으로 설정하면 막대 내부가 비어있고,
'stepfilled'로 설정하면 막대 내부가 채워진다.
'''
plt.hist(a, bins=100, density=True, alpha=0.7, histtype='step')
plt.hist(a, bins=50, density=True, alpha=0.5, histtype='stepfilled')
plt.hist(a, bins=100, density=True, alpha=0.9, histtype='step')

plt.show()

import matplotlib.pyplot as plt
import numpy as np

a = np.random.rand(1000)
b = np.random.rand(10000)
c = np.random.rand(100000)

plt.hist(a, bins=100, density=True, alpha=0.5, histtype='step', label='n=1000')
plt.hist(b, bins=100, density=True, alpha=0.75, histtype='step', label='n=10000')
plt.hist(c, bins=100, density=True, alpha=1.0, histtype='step', label='n=100000')
plt.legend()

#----------정수반환
import matplotlib.pyplot as plt
import numpy as np

''' a는 [0,10) 범위의 임의의 정수 1000개'''
a = np.random.randint(0, 10, 1000)
''' b는 [0,10) 범위의 임의의 정수 1000개'''
b = np.random.randint(10, 20, 1000)
''' c는 [0,10) 범위의 임의의 정수 1000개'''
c = np.random.randint(0, 20, 1000)

plt.hist(a, bins=100, density=False, alpha=0.5, histtype='step', label='0<=randint<10')
plt.hist(b, bins=100, density=False, alpha=0.75, histtype='step', label='10<=randint<20')
plt.hist(c, bins=100, density=False, alpha=1.0, histtype='step', label='0<=randint<20')
plt.legend()
plt.show()

 

# -*- coding: utf-8 -*-
"""
Created on Wed Apr 22 15:18:46 2020

@author: admin
"""


# Matplotlib 3차원 산점도 그리기
'''
scatter() 를 이용해서 3차원 산점도(3D Scatter plot)를 그리기.

3차원 그래프를 그리기 위해서
from mpl_toolkits.mplot3d import Axes3D 를 추가.

이 부분은 matplotlib 3.1.0 버전부터는
디폴트로 포함되기 때문에 적어주지 않아도 된다.
'''

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

'''
x, y의 위치, 마커의 색(colors)과 면적(area) 을 무작위로 지정.
'''
n = 100
xmin, xmax, ymin, ymax, zmin, zmax = 0, 20, 0, 20, 0, 50
cmin, cmax = 0, 2

xs = (xmax-xmin)*np.random.rand(n) + xmin
ys = (xmax-xmin)*np.random.rand(n) + ymin
zs = (xmax-xmin)*np.random.rand(n) + zmin
color = (xmax - xmin) * np.random.rand(n) + cmin


# rcParams 를 이용해서 figure의 사이즈를 설정
plt.rcParams["figure.figsize"] = (6,6) # 3차원 박스를 6분할로 나눈다.(가로, 세로)
fig = plt.figure()

'''
3D axes를 만들기 위해
add_subplot() 에 projection= '3d'키워드를 입력
'''
ax = fig.add_subplot(111, projection='3d')

'''
scatter() 함수에 x, y, z위치를 array의 형태로 입력
마커(marker)의 형태를 원형(circle)으로 설정
cmap = 'Greens'를 통해 colormap을 녹색 계열로 설정
'''

ax.scatter(xs, ys, zs, c=color, marker='o', s=15, cmap='Greens')

### Googletrans 기본 사용 ###
'''
Googletrans 라이브러리를 이용해서
간단한 문장을 특정 언어로 (구글) 번역하고, 언어를 자동 감지하는 기능을 사용.
'''

# 1. 번역하기
# googletrans에서 Translator를 불러오기

from googletrans import Translator

translator = Translator()

# translate() 에 번역할 문장을 입력해주면, 아래 같은 결과를 출력.
print(translator.translate('안녕하세요'))

### Googletrans - 파이썬을 위한 구글 번역 API ###
'''
Googletrans는
구글 번역 API(Google Translate API)를 구현한 파이썬 라이브러리.

파이썬과 Googletrans 를 이용해서
무료로 그리고 무제한으로 구글의 번역 기능을 사용할 수 있다.
'''

# Googletrans 설치
'''
pip install googletrans
conda install -c conda-forge googletrans
명령 프롬프트에서 pip 또는 conda를 통해서 설치를 진행
'''

### Googletrans 기본 사용 ###
'''
Googletrans 라이브러리를 이용해서
간단한 문장을 특정 언어로 (구글) 번역하고, 언어를 자동 감지하는 기능을 사용.
'''

# 1. 번역하기
# googletrans에서 Translator를 불러오기

from googletrans import Translator

translator = Translator()

# translate() 에 번역할 문장을 입력해주면, 아래 같은 결과를 출력.
print(translator.translate('안녕하세요'))
# 결과 : Translated(src=ko, dest=en, text=Hi, pronunciation=None, extra_data="{'translat...")
# 기본값인 영어로 번역되고(dest=en) 그 값은 Hi 이다(text=Hi)
print(translator.translate('안녕하세요').text)
# 이 함수가 가지고 있는 속성인 text 만 가지고 나와서 'Hi'를 출력한다.

'''
LANGUAGES = {    'af': 'afrikaans',    'sq': 'albanian',    'am': 'amharic',
             'ar': 'arabic',    'hy': 'armenian',    'az': 'azerbaijani',
             'eu': 'basque',    'be': 'belarusian',    'bn': 'bengali',
             'bs': 'bosnian',    'bg': 'bulgarian',    'ca': 'catalan',
             'ceb': 'cebuano',    'ny': 'chichewa',    'zh-cn': 'chinese (simplified)',
             'zh-tw': 'chinese (traditional)',    'co': 'corsican',    'hr': 'croatian',
             'cs': 'czech',    'da': 'danish',    'nl': 'dutch',    'en': 'english',
             'eo': 'esperanto',    'et': 'estonian',    'tl': 'filipino',
             'fi': 'finnish',    'fr': 'french',    'fy': 'frisian',    'gl': 'galician',
             'ka': 'georgian',    'de': 'german',    'el': 'greek',    'gu': 'gujarati',
             'ht': 'haitian creole',    'ha': 'hausa',    'haw': 'hawaiian',    'iw': 'hebrew',
             'hi': 'hindi',    'hmn': 'hmong',    'hu': 'hungarian',    'is': 'icelandic',
             'ig': 'igbo',    'id': 'indonesian',    'ga': 'irish',    'it': 'italian',
             'ja': 'japanese',    'jw': 'javanese',    'kn': 'kannada',    'kk': 'kazakh',
             'km': 'khmer',    'ko': 'korean',    'ku': 'kurdish (kurmanji)',    'ky': 'kyrgyz',
             'lo': 'lao',    'la': 'latin',    'lv': 'latvian',    'lt': 'lithuanian',
             'lb': 'luxembourgish',    'mk': 'macedonian',    'mg': 'malagasy',    'ms': 'malay',
             'ml': 'malayalam',    'mt': 'maltese',    'mi': 'maori',    'mr': 'marathi',
             'mn': 'mongolian',    'my': 'myanmar (burmese)',    'ne': 'nepali',    'no': 'norwegian',
             'ps': 'pashto',    'fa': 'persian',    'pl': 'polish',    'pt': 'portuguese',
             'pa': 'punjabi',    'ro': 'romanian',    'ru': 'russian',    'sm': 'samoan',
             'gd': 'scots gaelic',    'sr': 'serbian',    'st': 'sesotho',    'sn': 'shona',
             'sd': 'sindhi',    'si': 'sinhala',    'sk': 'slovak',    'sl': 'slovenian', 
             'so': 'somali',    'es': 'spanish',    'su': 'sundanese',    'sw': 'swahili',
             'sv': 'swedish',    'tg': 'tajik',    'ta': 'tamil',    'te': 'telugu',    'th': 'thai',
             'tr': 'turkish',    'uk': 'ukrainian',    'ur': 'urdu',    'uz': 'uzbek',
             'vi': 'vietnamese',    'cy': 'welsh',    'xh': 'xhosa',    'yi': 'yiddish',
             'yo': 'yoruba',    'zu': 'zulu',    'fil': 'Filipino',    'he': 'Hebrew'}
'''

####### Pandas 를 사용한 데이터 분석 기초
'''
분석할 데이터의 양(volume)이 커지고,
데이터의 입출력 속도(velocity)가 빨라지고
데이터의 종류가 다양해(variety) 짐에 따라
기존보다 데이터를 분석하기 어려워졌고
이로 인해 데이터 분석 분야가 업계의 주목을 받는 것

빅데이터 Volume, Velocity, Variety의 세 가지'V'를 가진 데이터

빅데이터 분석에는
다양한 프로그래밍 언어와 기술이 사용되고 있는데 파이썬도 그 중 하나.

파이썬이 오픈소스 기반의 통계언어인 R과 더불어
빅데이터 분석 분야에서 인기가 높아진 것은 여러 가지 이유가 있지만,
Pandas라는 라이브러리 덕이 크다.
'''

####### Pandas Series
'''
파이썬이 인기있는 이유 중 하나는
파이썬의 기본 자료구조인 리스트, 튜플, 딕셔너리가 사용하기 편리하며
데이터를 다루는 데 효과적이기 때문.

Pandas 역시 효과적인 데이터 분석을 위한
고수준의 자료구조와 데이터 분석 도구를 제공.

Pandas의
Series는 1차원 데이터를 다루는 데 효과적인 자료구조이며,
DataFrame은 행과 열로 구성된 2차원 데이터를 다루는 데 효과적인 자료구조 이다.

Pandas를 이해하려면
가장 먼저 Pandas의 핵심 자료구조인 Series와 DataFrame을 알아야 한다.
'''

######## 파이썬 리스트, 튜플, 딕셔너리
# 리스트
mystock = ['kakao','naver']
print(mystock[0])
print(mystock[1])
for stock in mystock:
    print(stock)
    
# 튜플
'''
튜플은
리스트의 []와 달리 ()를 사용.
수정이 가능한 리스트와 달리 수정할 수 없다.
대신 리스트에 비해서 속도가 빠르다는 장점이 있다.

그래서 원소를 한 번 넣은 후에
수정할 필요가 없으며
속도가 중요한 경우에 리스트 대신 튜플을 사용.
'''

# 딕셔너리
exam_dic = {'key1':'room1', 'key2':'room2'}
print(exam_dic['key1'])
print(exam_dic['key2'])

print(type(exam_dic)) # class dict

# 리스트와 딕셔너리
kakao_daily_ending_prices = [92300, 94300, 92100, 92400, 92600]
for price in kakao_daily_ending_prices:
    print(price)


kakao_daily_ending_prices = {'2016-02-19':92600,
                             '2016-02-18':92400,
                             '2016-02-17':92100,
                             '2016-02-16':94300,
                             '2016-02-15':92300}

print(kakao_daily_ending_prices['2016-02-19'])

# 시리즈는 리스트와도 비슷하고 딕셔너리와도 비슷하다, 데이터분석을 한다고 하면 기본적인 라이브러리가 Pandas

###### Series 기초
'''
Pandas의 Series는 1차원 배열과 같은 자료 구조.
파이썬 리스트와 튜플도 1차원 배열과 같은 자료구조

사실 Pandas의 Series는
어떤 면에서는 파이썬의 리스트와 비슷하고
어떤 면에서는 파이썬의 딕셔너리와 닮은 자료구조

Series를 사용하기에 앞서
Pandas라는 모듈에서 직접 Seires와 DataFrame을
로컬 네임스페이스로 import
'''

import pandas as pd
print(pd.Series)

'''
Series를 직접 로컬 네임스페이스로 import 한 경우에는
pandas는 생략하고 바로 Series라고만 적으면 된다.
'''
from pandas import Series, DataFrame

kakao = Series([92600, 92400, 92100, 94300, 92300]) # 해당 값을 자체는 리스트인데 리스트를 시리즈화 시킨다.
print(kakao)
print(type(kakao))
#데이터 프레임 역할을 할 수 있다, 인덱스 값을 가지게 한다.

'''
시리즈 객체는 일차원 배열과 달리 값뿐 아니라
각 값에 연결된 인덱스 값도 동시에 저장

시리즈 객체 생성시에
인덱스 값을 따로 지정하지 않으면
기본적으로 시리즈 객체는 0부터 시작하는 정숫 값을 사용하여 인덱싱
'''
print(kakao[0])
print(kakao[2])
print(kakao[4])


kakao2 = Series([92600, 92400, 92100, 94300, 92300], 
                index = ['2016-02-19','2016-02-18','2016-02-17','2016-02-16','2016-02-15'])

print(kakao2)

'''
카카오2라는 시리즈 객체는
인덱스 값으로 날짜에 해당하는 문자열을 지정했기 떄문에
정숫값으로 인덱싱하는 것 대신 날짜를 의미하는 문자열을 사용하여
각날짜에 대한 종가를 바로 얻어올 수 있다.
'''    
print(kakao2['2016-02-19'])
print(kakao2['2016-02-18'])

'''
시리즈 객체의
인덱스와 벨규라는 이름의 속성을 통해 접근할 수 있다.
'''

for date in kakao2.index:
    print(date)
    
for ending_price in kakao2.values:
    print(ending_price)
    
    
'''
판다스의 시리즈는
서로 다르게 인덱싱 된 데이터에 대해서도
알아서 덧셈 연산을 처리 해준다.
'''

#from pandas import Series, DataFrame

mine = Series([10,20,30], index = ['naver','sk','kt'])
friend = Series([40,50,60], index=["kt","naver",'sk'])

marge = mine+friend
print(marge)
# 있는 것들은 더해주고 없는 값은 합산해줄 수 없다.
# index 값을 바꿔서 'kt' -> 'kt'로 하면 일치하는 인덱스 값이 다르므로 연산은 되지만 해당 인덱스를 못찾는 것은 NaN값이 출력

#판다스 데이터프레임
'''
판다스의 시리즈가 1차원 형태의 자료구조라면
데이터프레임은 여러개의 칼럼으로 구성된 2차원 형태의 자료구조

판다스의 데이터 프레임을 사용하면
로우와 컬럼으로 구성된 2차원 구조의 데이터를
쉽게 저장하고 조작할 수 있다.
'''

#데이터프레임 생성
'''
데이터프레임 객체를 생성하는 가장귀운 방법은
파이썬의 딕셔너리를 사용하는것
딕셔너리를 통해 각 칼럼에 대한 데이터를 저장한 후,
딕셔너리를 데이터프레임 클래스의 생성자 인자로 넘겨주면
데이터프레임 객체가 생성 된다.
'''

#딕셔너리를 사용한 데이터 프레임 객체 생성

from pandas import Series, DataFrame
# 딕셔너리
raw_data = { "col0":[1,2,3,4],
            "col1":[10,20,30,40],
            "col2":[100,20,300,400]}
# 딕셔너리를 데이터 프레임으로 바꿔준다.
# 각각의 시리즈 명은 col1,col2,col3 별도로 0,1,2,3 으로 인덱스 값이 저장된다.
data =DataFrame(raw_data)
print(data)

'''
col0, col1, col2 라는 세 개의 칼럼이 존재
'col0', 'col1', 'col2' 라는 문자열은
DataFrame의 각 칼럼을 인덱싱하는 데 사용된다.

로우 방향으로는
Series와 유사하게 정수값으로 자동으로 인덱싱 된 것을
확인할 수 있다.

'''

# 'col0', 'col1', 'col2' 를 사용하여 각 컬럼을 선택
print('data["col"]----------------------------')
print(data['col0'])
print(data['col1'])
print(type(data['col0']))

'''
데이터 프레임에 있는 각 칼럼은 시리즈 객체임을 할 수 있다.
즉 데이터프레임은
인덱스가 같은 여러개의 시리즈 ㄱ객체로 구성된 자료구조

'''
'''
데이터라는 변수가 바인딩하는 데이터프레임에는 3개의 시리즈 객체가 있다
이는 col0, col1, col2 라는 키에 각각 대은하는 값이고
이것들을 하나의 파이썬 딕셔너리 객체로 생각하는것

따라서  col0, col1, col2 라는 키를 통해
벨류에 해당하는 시리즈 객체에 접근 할 수 있다.
'''
daeshin = { 'open':[11650,11100,11200,11100,11000],
           'high':[12100,11800,11200,11100,11150],
           'low':[11600,11050,10900,10950,109900],
           'clase':[11900,11600,11000,11100,11050]}

daeshin_day = DataFrame(daeshin)
print(daeshin_day)
'''
DataFrame 객체에는 칼럼의 순서는
DataFrame 객체를 생성할 때 columns 라는 키워드를 지정할 수 있다.
'''

daeshin_day2 = DataFrame(daeshin, columns = ['close', 'open', 'high', 'low']) #  순서 바꾸기
print(daeshin_day2)


'''
데이터프레임에서 인덱스 역시
데이터프레임 객체를 생성하는 시점에서 인덱스를 통해 지정 할 수 있다.
먼저 인덱싱에 사용할 값을 만든 후,
이를 데이터프레임 객체 생성 시점에 지정하면된다.
'''

date = ['20.02.29','20.02.26','20.02.25','20.02.24','20.02.23']
daeshin_day3 = DataFrame(daeshin,
                         columns = ['open', 'high', 'low', 'close'],
                         index = date)

print(daeshin_day3)

#데이터프라임 칼럼 로우 선택
'''
종가를 기준으로만 데이터를 분석한다면
'close'칼럼에 대한 데이터만을 데이터 프레임 객체로부터 얻어낸다.
'''
close = daeshin_day3['close']
print(close)

'''
DataFrame 객체의 칼럼 이름과 인덱스 값을 확인하려면
각각 columns와 index 속성을 사용.
'''
print(daeshin_day.columns)
print(daeshin_day.index)

 

print('SQLite -----------------------------------------')
import sqlite3 # DB저장하려면 sqlite3 모듈을 일단 임포트 해야한다.

print(sqlite3.version) #2.6.0
print(sqlite3.sqlite_version) #3.31.1

con = sqlite3.connect("C:/pythonwork/kospi.db") # 128비트 암호화기능 보유(데이터를 그냥 저장하는게 아닌 암호화 시켜서 저장/복원할 수 있음)
# 실제로 저장되는 파일의 확장자명은 .db 로 저장 -> 이렇게 저장해야 다른 db에 이식 가능
print(type(con)) #<class 'sqlite3.Connection'>

cursor = con.cursor() # 얘가 cursor 쿼리를 실행시키는 것(객체전달받아야함) -> 자바의 pstmt, stmt 와 같은 기능 (쿼리문 실행시키는 기능)

# 테이블 생성(close는 내장값이여서 closing으로 명명)
cursor.execute("CREATE TABLE kakao(Date text, Open int, High int, Low int, Closing int, Volume int)")
cursor.execute("INSERT INTO kakao VALUES('16.06.03', 97000, 98600, 96900, 98000, 321405)")

cursor.execute("SELECT * FROM kakao")
print(cursor.fetchone()) #('16.06.03', 97000, 98600, 96900, 98000, 321405) 출력
print(cursor.fetchone()) # 한 번에 데이터를 하나만 가져오는 것(rs.next()로 넘겨주는 것 처럼 한번에 하나 가져오는 것)

con.commit()
#con.close()

cursor.execute("SELECT * FROM kakao")
print(cursor.fetchall()) # 한 번에 모든 데이터를 가져오는 것

cursor.execute("SELECT * FROM kakao")
kakao = cursor.fetchall()
print(type(kakao)) # <class 'list'>
print(kakao[0][0]) #16.06.03
print(kakao[0][1]) #97000
print(kakao[0][2]) #98600
print(kakao[0][3]) #96900
print(kakao[0][4]) #98000
print(kakao[0][5]) #321405


con.commit()
con.close()

#web 데이터 읽기
'''
pip install pandas_datareader 쳐서 인스톨하고
pip install yfinance 이거 쳐서 인스톨 두개 하세요
'''
# web 데이터 읽기
import pandas_datareader.data as web
import pandas as pd
import datetime as dt

#야후증권
import yfinance
import sqlite3

# 추출할 시작 날짜 종료 날짜 설정
start = dt.datetime(2018, 1, 1)
end = dt.datetime(2019, 1, 1)

# 야후증권으로부터 삼성전자 주식 추출
samsung = web.get_data_yahoo("005930.KS", start, end)

# 상위 5개만 출력
sf = samsung.tail(5)
print(sf)

# 삼성전자 1년 데이터 데이터베이스에 저장
con = sqlite3.connect("C:/pythonwork/kospi3.db")

# 데이터프레임은 db에 저장할 수 있는 함수를 제공 :to_sql()
#Auto Commit이 기본
samsung.to_sql('samsung', con, chunksize=1000)

# dataframe은 DB를 통해 조회할 수 있는 쿼리도 제공
readed_df = pd.read_sql("SELECT * FROM samsung", con, index_col = 'Date')
print(readed_df)

'''
기본 설정값

DataFrame.to_sql(name,
                 con,
                 flavor = 'sqlite',
                 schema= None,
                 if_exists ='fail',
                 index = True,
                 index_label = None,
                 chunksize =None,
                 dtype=None)
'''
'''
name : SQL 테이블 이름으로 파이썬 문자열 형태로 나타낸다.
con : Cursor 객체

flavro : 사용한 DBMS를 지정할 수 있는데 'sqlite'또는 'mysql'을 사용할 수 있다. 기본값은 sqlite

schema : Schema를 지정할 수 있는데 기본값은 None 이다.

if_exists : 데이터베이스에 테이블이 존재할 때 수행 동작을 지정한다. 'fail', 'replace', 'append'중 하나를 사용할 수 있는데 기본값은 'fail'이다.
'fail'은 데이터베이스에 테이블이 있다면 아무 동작도 수행하지 않는다.
'repalce'는 테이블이 존재하면 기존 테이블을 삭제하고
새 테이블을 생성한 후 테이터를 삽입한다.
'append' 는 테이블이 존재하면 데이터만을 추가한다.

index : 데이터프레임의 인덱스를 데이터베이스에 칼럼으로 추가할지에 대한 여부를 지정한다.
기본값은 True

index_label : 인덱스 칼럼에 대한 라벨을 지정할 수 있다. 기본값은 None 이다.

chunksize : 한 번에 저장되는 로우의 크기를 정수값으로 지정할 수 있다.
 기본값은 None으로 DataFrame 내의 모든 로우가 한 번에 저장된다.
 
dtype : 칼럼에 대한 SQL 타입을 파이썬 딕셔너리로 넘겨줄 수 있다.
'''

'''
BeautifulSoup - 파이썬 웹 크롤링 라이브러리
BeautifulSoup은 파이썬 웹 크롤링에 가장 널리 사용되는 라이브러리이자 툴 입니다.

웹 크롤링(Web crawling) 또는 스크래핑(Scrapping)은
웹 페이지들을 긁어와서 데이터를 추출하는 것을 말합니다.

웹 크롤러는 자동화된 방식으로 웹 페이지들을 탐색하는 컴퓨터 프로그램입니다.

파이썬과 BeautifulSoup 라이브러리를 이용하면
프로그래밍에 익숙하지 않은 비전공자나 입문자도 쉽게 크롤링을 할 수 있습니다.

BeautifulSoup 크롤링 예제에서 Requests와 BeautifulSoup 라이브러리를 사용하는데,
기본적으로 아나콘다 통합 패키지에 포함되어 있지만
설치되어 있지 않다면 설치를 진행합니다.


#BeautifulSoup 설치
#pip install beautifulsoup4


#네이버 날씨 미세먼지 가져오기
#웹 페이지 가져오기(https://search.naver.com/search.naver?query=%EB%82%A0%EC%94%A8)
'''
from bs4 import BeautifulSoup as bs
import requests

html = requests.get('https://search.naver.com/search.naver?query=%EB%82%A0%EC%94%A8')
print(html.text) # html 텍스트 속성값을 가져옴 (검사창에서 가져옴)
print(type(html))
print(type(html.text))

# 뷰티플슾 객체로 만들어준 후 내가 원하는 객체를 가져와준다.
# 파싱
soup = bs(html.text, 'html.parser')
print(soup)

# 요소 1개 찾기(find)
# 미세먼지 정보가 있는 div 요소만 추출
data1 = soup.find('div',{'class':'detail_box'}) # html도, json도 파싱 가능하다
print(data1)


# 요소 모두 찾기(findAll)
'''
find와 사용방법이 똑같으나
find는 처음 매칭된 1개만,
findAll은 매칭된 모든 것을 리스트로 반환.
'''
data2 = data1.findAll('dd') 
#print(data2)

# 내부 텍스트 추출
# span 태그에 속성과 속성값은 class="num"
find_dust = data2[0].find('span',{'class':'num'})
print(fine_dust)

# 내부 텍스트만 골라내도록 .text를 이용
find_dust = data2[0].find('span',{'class':'num'}).text
print(fine_dust)


# 초미세먼지 추출
'''
data2변수에서 
미세먼지는 0번 인덱스
초미세먼지는 1번 인덱스
'''
ultra_find_dust = data2[1].find('span',{'class':'num'}).text
print(ultra_find_dust)

# 오존지수 추출
ozone = data2[2].find('span',{'class':'num'}).text
print(ozone)

# 데이터프레임으로 만들기(미세먼지&오존)
import pandas as pd

weather = {'미세먼지':fine_dust,'초미세먼지':ultra_fine_dust,'오존':ozone}
print(weather)
df_weather = pd.DataFrame(weather, columns=['미세먼지','초미세먼지','오존'], index = ['20.04.21'])
print(df_weather)

 

# 네이버 웹툰 썸네일 가져오기

# 제목과 썸네일이 같이 존재하는 영역
from bs4 import BeautifulSoup
import requests

# 웹 페이지를 열고 소스코드를 읽어오는 작업
html = requests.get("https://comic.naver.com/webtoon/weekday.nhn")
print(type(html)) # <class 'requests.models.Response'>
soup = BeautifulSoup(html.text, 'html.parser')
print(type(soup)) # <class 'bs4.BeautifulSoup'>
html.close()

# 요일별 웹툰영역 추출하기# 요일별 웹툰영역 추출하기
date_webtoon = soup.findAll('div',{'class':'col_inner'})
print(date_webtoon)

'''
<li>
<div class="thumb">
<a href="/webtoon/list.nhn?titleId=743721&amp;weekday=sun" onclick="nclk_v2(event,'thm*S.img','','49')">
<img alt="불발소년" height="90" onerror="this.src='https://ssl.pstatic.net/static/comic/images/migration/common/blank.gif'" src="https://shared-comic.pstatic.net/thumb/webtoon/743721/thumbnail/thumbnail_IMAG10_1a440839-f0da-4260-a107-8840f6fa4fc9.jpg" title="불발소년" width="83"/><span class="mask"></span>
<span class="ico_new2">NEW</span>
</a>
</div>
<a class="title" href="/webtoon/list.nhn?titleId=743721&amp;weekday=sun" onclick="nclk_v2(event,'thm*S.tit','','49')" title="불발소년">불발소년</a>
</li>
'''
li_list=[]
for data1 in date_webtoon:
    #제목+썸네일 영역추출
    #해당부분을 찾아 li_list와 병합
    li_list.extend(data1.findAll('li'))
    
#print(li_list)
    
# 각각의 요소 중 <img> 태그의 제목과 썸네일(~.jpg)만 추출하기
'''
<img alt="불발소년" height="90" onerror="this.src='https://ssl.pstatic.net/static/comic/images/migration/common/blank.gif'"
 src="https://shared-comic.pstatic.net/thumb/webtoon/743721/thumbnail/thumbnail_IMAG10_1a440839-f0da-4260-a107-8840f6fa4fc9.jpg" 
 title="불발소년" width="83"/>
'''

for li in li_list:
    img = li.find('img')
    title = img['title']
    img_src = img['src']
    print(title,img_src)
    

# 다운로드하기
'''
이미지 또는 동영상 링크가 있다면 다운로드 하는 방법은 쉽다.
from urllib.request import urlretrieve 를 추가한 뒤,
urlretrieve 호출 시에 링크와 저장할 파일명을 넣으면 된다.
'''

# 특수문자 처리
'''
도중에 에러가 난 부분을 보면 파일명에 특수문자가 있는 경우
따라서 추출한 제목에서 특수문자는 다른 문자로 변경해주거나 삭제해 주어야 한다.

변경은 replace 를 하면 되는데,
여기서는 정규식 표현을 이용한 re모듈을 사용하여 삭제
따라서 re모듈을 import
'''

# 저장폴더 생성
'''
여기서는 os 모듈을 참조
os.path.isdir : 이미 디렉토리가 있는지 검사
os.path.join : 현재 경로를 계산하여 입력을 ㅗ들어온 텍스트를 합하여 새로운 경로를 만듦

os.makedirs : 입력으로 들어온 경로로 폴더를 생성

모듈 참조와 아래 urlretrieve 부분도 변경
'''

 

import errno
from bs4 import BeautifulSoup

import requests,re,os
from urllib.request import urlretrieve #추가

# 저장 폴더를 생성
try:
    if not (os.path.isdir('image')):
        os.makedirs(os.path.join('image'))
        print("이미지 폴더 생성 성공!")
except OSError as e:
    if e.errno != errno.EEXIST:
        print("폴더 생성 실패!")
        exit()
        
# 웹 페이지를 열고 소스코드를 읽어오는 작업
html = requests.get("https://comic.naver.com/webtoon/weekday.nhn")
#print(type(html)) # <class 'requests.models.Response'>
soup = BeautifulSoup(html.text, 'html.parser')
#print(type(soup)) # <class 'bs4.BeautifulSoup'>
html.close()

# 요일별 웹툰영역 추출하기# 요일별 웹툰영역 추출하기
date1_list = soup.findAll('div',{'class':'col_inner'})
#print(date_webtoon)

# 전체 웹툰 리스트
li_list=[]
for data1 in date1_list:
    #제목+썸네일 영역추출
    #해당부분을 찾아 li_list와 병합
    li_list.extend(data1.findAll('li'))
    
# 각각 썸네일과 제목 추출하기
for li in li_list:
    img = li.find('img')
    title = img['title']
    img_src = img['src']
    #print(title,img_src)
    #해당 영역의 글자가 아닌 것은 ''로 치환시킨다.
    title = re.sub('[^0-9a-zA-Zㄱ-힗]', '', title)
    #주소, 파일 경로 + 파일명+확장자
    urlretrieve(img_src,'./image/' + title +'.jpg')

 

import errno
from bs4 import BeautifulSoup

import requests,re,os
from urllib.request import urlretrieve #추가

# 저장 폴더를 생성
try:
    if not (os.path.isdir('image_naver')):
        os.makedirs(os.path.join('image_naver'))
        print("이미지 폴더 생성 성공!")
except OSError as e:
    if e.errno != errno.EEXIST:
        print("폴더 생성 실패!")
        exit()
        
# 웹 페이지를 열고 소스코드를 읽어오는 작업
html = requests.get("https://search.shopping.naver.com/best100v2/detail.nhn?catId=50000003")
#print(type(html)) # <class 'requests.models.Response'>
soup = BeautifulSoup(html.text, 'html.parser')
#print(type(soup)) # <class 'bs4.BeautifulSoup'>
html.close()

# 쇼핑 네이버 영역 추출하기
date1_list = soup.findAll('ul',{'class':'type_normal'})
print(date1_list)

# 전체 쇼핑 리스트
li_list=[]
for data1 in date1_list:
    #영역추출
    #해당부분을 찾아 li_list와 병합
    li_list.extend(data1.findAll('li'))

print(li_list)

# 각각 이미지, 제목 추출하기
for li in li_list:
    img = li.find('img')
    title = img['alt']
    img_src = img['data-original']
    #print(title,img_src)
    #해당 영역의 글자가 아닌 것은 ''로 치환시킨다.
    title = re.sub('[^0-9a-zA-Zㄱ-힗]', '', title)
    #주소, 파일 경로 + 파일명+확장자
    urlretrieve(img_src,'./image_naver/' + title +'.jpg')


# 가격 추출
date1_list1 = soup.findAll('span',{'class':'num'})
print(date1_list1) 

price_list=[]

for data2 in date1_list1:
    price_list.append(data2.text)
price_list           

#가격을 int 타입으로 변경
price_int_list = [] 
for li in price_list:
    # 가격값을 넣고 price
    price = li
    # price의 가격의 ,를 없애고 공백을 없앤다.
    price = re.sub(',','',price)
    # 형변환을 해주고
    price = int(price)
    # price을 price_int_list에 append한다.
    price_int_list.append(price)
    
print(len(price_int_list))
print(price_int_list)

#썸네일, 품명, 가격 추출
names = []
for li in li_list:
    img = li.find('img')
    title = img['alt']
    # alt = 제목명
    names.append(img['alt'])
    img_src = img['data-original']
    # sub를 이용하여 특수문자를 공백으로 주겠다
    title = re.sub('[^0-9a-zA-Zㄱ-힗]','',title)
    # 이름+jpg로 변경하여 저장한다.
    urlretrieve(img_src, './image_naver/'+title+'.jpg')
    
print(len(names))

# db 연결
import sqlite3
con = sqlite3.connect("C:/pythonwork/naver_db")
import pandas as pd
from pandas import Series, DataFrame

# 딕셔너리 타입으로 업로드 해준다.
raw_data = {'제품명' : names,'가격' : price_int_list}

# 데이터프레임화 해준다.
data = DataFrame(raw_data)

print(data)

# 테이블을 생성하고 인덱스 없이 만든다.
data.to_sql('naver_table', con, chunksize=1000, index = False)

read_df = pd.read_sql("SELECT * FROM naver_db", con)
print(read_df)

con.commit()
con.close()

 

 

 

 

 

#프로젝트명 : Contact 파일명 : contact.py

class Contact:
    def __init__(self,name,phone_number,e_mail,addr):
        self.name=name
        self.phone_numder = phone_number
        self.e_mail=e_mail
        self.addr=addr
    def print_info(self):
        print("name:",self.name)
        print("phone numder:",self.phone_numder)
        print("e_mail:",self.e_mail)
        print("addr:",self.addr)

#모듈 자체 테스트 시. 호출할 함수
#기본 코드 작성
def run():
    kim=Contact('김일구','010-8812-1197','ligu.kim@python.com','Seoul')
    kim.print_info()

#모듈 자체 테스트 인지, import인지를 구분
if __name__=="__main__":
    run()

#프로젝트명 : Contact 파일명 : contact.py

class Contact:
    def __init__(self,name,phone_number,e_mail,addr):
        self.name=name
        self.phone_numder = phone_number
        self.e_mail=e_mail
        self.addr=addr
    def print_info(self):
        print("name:",self.name)
        print("phone numder:",self.phone_numder)
        print("e_mail:",self.e_mail)
        print("addr:",self.addr)
##Class Contact : end ####

#사용자로부터 데이터 입력 받기
def set_contact():
    name = input("Name:")
    phone_number = input("phone number:")
    e_mail =input("e_mail:")
    addr =input("addr:")
    print(name,phone_number,e_mail,addr)

#모듈 자체 테스트 시. 호출할 함수
#기본 코드 작성
def run():
   set_contact()

#모듈 자체 테스트 인지, import인지를 구분
if __name__=="__main__":
    run()

 

#프로젝트명 : Contact 파일명 : contact.py

class Contact:
    def __init__(self,name,phone_number,e_mail,addr):
        self.name=name
        self.phone_numder = phone_number
        self.e_mail=e_mail
        self.addr=addr
    def print_info(self):
        print("name:",self.name)
        print("phone numder:",self.phone_numder)
        print("e_mail:",self.e_mail)
        print("addr:",self.addr)
##Class Contact : end ####

#사용자로부터 데이터 입력 받기
def set_contact():
    name = input("Name:")
    phone_number = input("phone number:")
    e_mail =input("e_mail:")
    addr =input("addr:")
    print(name,phone_number,e_mail,addr)

#메인 메뉴 구성하기
def print_menu():
    print("1. 연락처 입력")
    print("2. 연락처 출력")
    print("3. 연락처 삭제")
    print("4. 중료")
    menu=input("메뉴선택:")

    return int(menu)

#모듈 자체 테스트 시. 호출할 함수
#기본 코드 작성
def run():
    while 1:
        menu=print_menu()
        if menu==4:
            break

#모듈 자체 테스트 인지, import인지를 구분
if __name__=="__main__":
    run()

C:\Users\admin\PycharmProjects\pythonwork1\venv\Scripts\python.exe C:/Users/admin/PycharmProjects/pythonwork1/contact.py
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:4

Process finished with exit code 0
#프로젝트명 : Contact 파일명 : contact.py

class Contact:
    def __init__(self,name,phone_number,e_mail,addr):
        self.name=name
        self.phone_numder = phone_number
        self.e_mail=e_mail
        self.addr=addr
    def print_info(self):
        print("name:",self.name)
        print("phone numder:",self.phone_numder)
        print("e_mail:",self.e_mail)
        print("addr:",self.addr)
##Class Contact : end ####

#사용자로부터 데이터 입력 받기
def set_contact():
    name = input("Name:")
    phone_number = input("phone number:")
    e_mail =input("e_mail:")
    addr =input("addr:")
    #print(name,phone_number,e_mail,addr)
    contact=Contact(name,phone_number,e_mail,addr)
    return contact

#-----def_set_contact() END--------

#메인 메뉴 구성하기
def print_menu():
    print("1. 연락처 입력")
    print("2. 연락처 출력")
    print("3. 연락처 삭제")
    print("4. 중료")
    menu=input("메뉴선택:")

    return int(menu)

#모듈 자체 테스트 시. 호출할 함수
#기본 코드 작성
def run():
    #추가
    contact_list=[]
    while 1:
        menu=print_menu()
        #1. 연락처 입력 선택
        if menu==1:
            contact=set_contact()
            contact_list.append(contact)
        #수정
        elif menu == 4:
            break
#----def run():END-----



#모듈 자체 테스트 인지, import인지를 구분
if __name__=="__main__":
    run()
    
    
C:\Users\admin\PycharmProjects\pythonwork1\venv\Scripts\python.exe C:/Users/admin/PycharmProjects/pythonwork1/contact.py
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:1
Name:왕
phone number:123-4567-7894
e_mail:왕@naed@com
addr:왕왕
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:
#프로젝트명 : Contact 파일명 : contact.py

class Contact:
    def __init__(self,name,phone_number,e_mail,addr):
        self.name=name
        self.phone_numder = phone_number
        self.e_mail=e_mail
        self.addr=addr
    def print_info(self):
        print("name:",self.name)
        print("phone numder:",self.phone_numder)
        print("e_mail:",self.e_mail)
        print("addr:",self.addr)
##Class Contact : end ####

#사용자로부터 데이터 입력 받기
def set_contact():
    name = input("Name:")
    phone_number = input("phone number:")
    e_mail =input("e_mail:")
    addr =input("addr:")
    #print(name,phone_number,e_mail,addr)
    contact=Contact(name,phone_number,e_mail,addr)
    return contact

#-----def_set_contact() END--------

#메인 메뉴 구성하기
def print_menu():
    print("1. 연락처 입력")
    print("2. 연락처 출력")
    print("3. 연락처 삭제")
    print("4. 중료")
    menu=input("메뉴선택:")

    return int(menu)

#모듈 자체 테스트 시. 호출할 함수
#기본 코드 작성
def run():
    #추가
    contact_list=[]
    while 1:
        menu=print_menu()
        #1. 연락처 입력 선택
        if menu==1:
            contact=set_contact()
            contact_list.append(contact)
        #2.연락처 출력
        if menu == 2:
            print(contact_list)
        #수정
        elif menu == 4:
            break
#----def run():END-----

#연락처 출력하기
def print_contact(contact_list):
    for contact in contact_list:
        contact.print_info()

#모듈 자체 테스트 인지, import인지를 구분
if __name__=="__main__":
    run()
    
C:\Users\admin\PycharmProjects\pythonwork1\venv\Scripts\python.exe C:/Users/admin/PycharmProjects/pythonwork1/contact.py
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:1
Name:왕
phone number:123-456-789
e_mail:왕@com
addr:왕왕
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:2
[<__main__.Contact object at 0x019ED0B8>]
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:
#프로젝트명 : Contact 파일명 : contact.py

class Contact:
    def __init__(self,name,phone_number,e_mail,addr):
        self.name=name
        self.phone_numder = phone_number
        self.e_mail=e_mail
        self.addr=addr
    def print_info(self):
        print("name:",self.name)
        print("phone numder:",self.phone_numder)
        print("e_mail:",self.e_mail)
        print("addr:",self.addr)
##Class Contact : end ####

#사용자로부터 데이터 입력 받기
def set_contact():
    name = input("Name:")
    phone_number = input("phone number:")
    e_mail =input("e_mail:")
    addr =input("addr:")
    #print(name,phone_number,e_mail,addr)
    contact=Contact(name,phone_number,e_mail,addr)
    return contact

#-----def_set_contact() END--------

#메인 메뉴 구성하기
def print_menu():
    print("1. 연락처 입력")
    print("2. 연락처 출력")
    print("3. 연락처 삭제")
    print("4. 중료")
    menu=input("메뉴선택:")

    return int(menu)

#모듈 자체 테스트 시. 호출할 함수
#기본 코드 작성
def run():
    #추가
    contact_list=[]
    while 1:
        menu=print_menu()
        #1. 연락처 입력 선택
        if menu==1:
            contact=set_contact()
            contact_list.append(contact)
        #2.연락처 출력
        elif menu == 2:
            print_contact(contact_list)
        # 3. 연락처 삭제
        elif menu == 3:
            name=input("Name:")
            delete_contact(contact_list,name)
        #4.종료
        elif menu == 4:
            break

#----def run():END-----

#연락처 출력하기
def print_contact(contact_list):
    for contact in contact_list:
        contact.print_info()
#연락처 삭제하기
def delete_contact(contact_list,name):
    for i, contact in enumerate(contact_list):
        if contact.name==name:
            del contact_list[i]


#모듈 자체 테스트 인지, import인지를 구분
if __name__=="__main__":
    run()
    
 C:\Users\admin\PycharmProjects\pythonwork1\venv\Scripts\python.exe C:/Users/admin/PycharmProjects/pythonwork1/contact.py
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:1
Name:와
phone number:와
e_mail:와
addr:와
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:2
name: 와
phone numder: 와
e_mail: 와
addr: 와
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:3
Name:와
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:2
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 중료
메뉴선택:
#프로젝트명 : Contact 파일명 : contact.py

class Contact:
    def __init__(self,name,phone_number,e_mail,addr):
        self.name=name
        self.phone_numder = phone_number
        self.e_mail=e_mail
        self.addr=addr
    def print_info(self):
        print("name:",self.name)
        print("phone numder:",self.phone_numder)
        print("e_mail:",self.e_mail)
        print("addr:",self.addr)
##Class Contact : end ####

#사용자로부터 데이터 입력 받기
def set_contact():
    name = input("Name:")
    phone_number = input("phone number:")
    e_mail =input("e_mail:")
    addr =input("addr:")
    #print(name,phone_number,e_mail,addr)
    contact=Contact(name,phone_number,e_mail,addr)
    return contact

#-----def_set_contact() END--------

#메인 메뉴 구성하기
def print_menu():
    print("1. 연락처 입력")
    print("2. 연락처 출력")
    print("3. 연락처 삭제")
    print("4. 종료")
    menu=input("메뉴선택:")

    return int(menu)

#모듈 자체 테스트 시. 호출할 함수
#기본 코드 작성
def run():
    #추가
    contact_list=[]
    while 1:
        menu=print_menu()
        #1. 연락처 입력 선택
        if menu==1:
            contact=set_contact()
            contact_list.append(contact)
        #2.연락처 출력
        elif menu == 2:
            print_contact(contact_list)
        # 3. 연락처 삭제
        elif menu == 3:
            name=input("Name:")
            delete_contact(contact_list,name)
        #4.종료
        elif menu == 4:
            store_contact(contact_list)
            break

#----def run():END-----

#연락처 출력하기
def print_contact(contact_list):
    for contact in contact_list:
        contact.print_info()
        
#연락처 삭제하기
def delete_contact(contact_list,name):
    for i, contact in enumerate(contact_list):
        if contact.name==name:
            del contact_list[i]

#연락처 파일 저장
def store_contact(contact_list):
    f=open("","wt")
    for contact in contact_list:
        f.write(contact.name+'\n')
        f.write(contact.phone_number + '\n')
        f.write(contact.e_mail+ '\n')
        f.write(contact.addr + '\n')
    f.close()


#모듈 자체 테스트 인지, import인지를 구분
if __name__=="__main__":
    run()
    
C:\Users\admin\PycharmProjects\pythonwork1\venv\Scripts\python.exe C:/Users/admin/PycharmProjects/pythonwork1/contact.py
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 종료
메뉴선택:1
Name:와1
phone number:와와1
e_mail:와와오아1
addr:와와1
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 종료
메뉴선택:1
Name:우우우1
phone number:우우우우1
e_mail:우우우우우1
addr:우우1
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 종료
메뉴선택:1
Name:네
phone number:네네
e_mail:네네네
addr:네네
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 종료
메뉴선택:3
Name:네
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 종료
메뉴선택:2
name: 와1
phone numder: 와와1
e_mail: 와와오아1
addr: 와와1
name: 우우우1
phone numder: 우우우우1
e_mail: 우우우우우1
addr: 우우1
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 종료
메뉴선택:
    
    

 

#프로젝트명 : Contact 파일명 : contact.py

class Contact:
    def __init__(self,name,phone_number,e_mail,addr):
        self.name=name
        self.phone_numder = phone_number
        self.e_mail=e_mail
        self.addr=addr
    def print_info(self):
        print("name:",self.name)
        print("phone numder:",self.phone_numder)
        print("e_mail:",self.e_mail)
        print("addr:",self.addr)
##Class Contact : end ####

#사용자로부터 데이터 입력 받기
def set_contact():
    name = input("Name:")
    phone_number = input("phone number:")
    e_mail =input("e_mail:")
    addr =input("addr:")
    #print(name,phone_number,e_mail,addr)
    contact=Contact(name,phone_number,e_mail,addr)
    return contact

#-----def_set_contact() END--------

#메인 메뉴 구성하기
def print_menu():
    print("1. 연락처 입력")
    print("2. 연락처 출력")
    print("3. 연락처 삭제")
    print("4. 종료")
    menu=input("메뉴선택:")

    return int(menu)

#모듈 자체 테스트 시. 호출할 함수
#기본 코드 작성
def run():
    #추가
    contact_list=[]
    load_contact(contact_list)
    while 1:
        menu=print_menu()
        #1. 연락처 입력 선택
        if menu==1:
            contact=set_contact()
            contact_list.append(contact)
        #2.연락처 출력
        elif menu == 2:
            print_contact(contact_list)
        # 3. 연락처 삭제
        elif menu == 3:
            name=input("Name:")
            delete_contact(contact_list,name)
        #4.종료
        elif menu == 4:
            store_contact(contact_list)
            break

#----def run():END-----

#연락처 출력하기
def print_contact(contact_list):
    for contact in contact_list:
        contact.print_info()
        
#연락처 삭제하기
def delete_contact(contact_list,name):
    for i, contact in enumerate(contact_list):
        if contact.name==name:
            del contact_list[i]

#연락처 파일 저장
def store_contact(contact_list):
    f=open("C:/Users/admin/PycharmProjects/pythonwork1/test.txt","wt")
    for contact in contact_list:
        f.write(contact.name+'\n')
        f.write(contact.phone_number + '\n')
        f.write(contact.e_mail+ '\n')
        f.write(contact.addr + '\n')
    f.close()

#연락처 불러들이기
def load_contact(contact_list):
    f = open("C:/Users/admin/PycharmProjects/pythonwork1/test.txt", "rt")
    # 파일에서 읽어들인 전체 라인 수를 4로 나누어, 몇 개의 데이터가 존재하는지 확인
    lines = f.readlines()
    num = len(lines)/4 # 나눗셈 연산을 수행하면 num 값이 실수가 되는데,
    num = int(num)     # 이 값을 int() 내장 함수를 사용해 정수형으로 형 변환

    for i in range(num):
        name = lines[4*i].rstrip("\n") # rstrip('\n') : 맨 오른쪽 '\n'을 제거
        phone = lines[4*i+1].rstrip('\n') # lstrip('\n') : 맨 왼쪽 '\n' 을 제거
        email = lines[4*i+2].rstrip('\n') # strip('\n') : 양쪽 끝의 '\n'을 제거
        addr = lines[4*i+3].rstrip('\n')
        contact = Contact(name, phone, email, addr)
        contact_list.append(contact)
    f.close()

#모듈 자체 테스트 인지, import인지를 구분
if __name__=="__main__":
    run()

 

 

cmd 창에서 실행하기

Microsoft Windows [Version 10.0.10240]
(c) 2015 Microsoft Corporation. All rights reserved.

C:\Users\admin>C:\Users\admin\PycharmProjects\pythonwork1\contact.py

C:\Users\admin>cd C:\Users\admin\PycharmProjects\pythonwork1\contact.py
디렉터리 이름이 올바르지 않습니다.

C:\Users\admin>cd\ C:\Users\admin\PycharmProjects\pythonwork1\contact.py
파일 이름, 디렉터리 이름 또는 볼륨 레이블 구문이 잘못되었습니다.

C:\Users\admin>cdC:\Users\admin\PycharmProjects\pythonwork1\contact.py
파일 이름, 디렉터리 이름 또는 볼륨 레이블 구문이 잘못되었습니다.

C:\Users\admin>cd..

C:\Users>cd..

C:\>cd C:\Users\admin\PycharmProjects\pythonwork1\contact.py
디렉터리 이름이 올바르지 않습니다.

C:\>cd C:\Users\admin\PycharmProjects\pythonwork1

C:\Users\admin\PycharmProjects\pythonwork1>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: 2EB3-B1D7

 C:\Users\admin\PycharmProjects\pythonwork1 디렉터리

2020-04-10  오후 05:32    <DIR>          .
2020-04-10  오후 05:32    <DIR>          ..
2020-04-10  오후 05:36    <DIR>          .idea
2020-04-10  오후 05:32             3,378 contact.py
2020-04-10  오후 04:05                25 hello.py
2020-04-10  오후 03:32    <DIR>          venv
               2개 파일               3,403 바이트
               4개 디렉터리  454,151,737,344 바이트 남음

C:\Users\admin\PycharmProjects\pythonwork1>contact.py

C:\Users\admin\PycharmProjects\pythonwork1>
Microsoft Windows [Version 10.0.10240]
(c) 2015 Microsoft Corporation. All rights reserved.

C:\Users\admin>C:\Users\admin\PycharmProjects\pythonwork1\contact.py

C:\Users\admin>cd C:\Users\admin\PycharmProjects\pythonwork1\contact.py
디렉터리 이름이 올바르지 않습니다.

C:\Users\admin>cd\ C:\Users\admin\PycharmProjects\pythonwork1\contact.py
파일 이름, 디렉터리 이름 또는 볼륨 레이블 구문이 잘못되었습니다.

C:\Users\admin>cdC:\Users\admin\PycharmProjects\pythonwork1\contact.py
파일 이름, 디렉터리 이름 또는 볼륨 레이블 구문이 잘못되었습니다.

C:\Users\admin>cd..

C:\Users>cd..

C:\>cd C:\Users\admin\PycharmProjects\pythonwork1\contact.py
디렉터리 이름이 올바르지 않습니다.

C:\>cd C:\Users\admin\PycharmProjects\pythonwork1

C:\Users\admin\PycharmProjects\pythonwork1>dir
 C 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: 2EB3-B1D7

 C:\Users\admin\PycharmProjects\pythonwork1 디렉터리

2020-04-10  오후 05:32    <DIR>          .
2020-04-10  오후 05:32    <DIR>          ..
2020-04-10  오후 05:36    <DIR>          .idea
2020-04-10  오후 05:32             3,378 contact.py
2020-04-10  오후 04:05                25 hello.py
2020-04-10  오후 03:32    <DIR>          venv
               2개 파일               3,403 바이트
               4개 디렉터리  454,151,737,344 바이트 남음

C:\Users\admin\PycharmProjects\pythonwork1>contact.py

C:\Users\admin\PycharmProjects\pythonwork1>contact.py

C:\Users\admin\PycharmProjects\pythonwork1>cd..

C:\Users\admin\PycharmProjects>cd..

C:\Users\admin>cd..

C:\Users>cd..

C:\>cd..

C:\>C:\Users\admin\PycharmProjects\pythonwork1\contact.py

C:\>cd C:\Users\admin\PycharmProjects\pythonwork1\contact.py
디렉터리 이름이 올바르지 않습니다.

C:\>cd C:\Users\admin\PycharmProjects\pythonwork1\contact.py
디렉터리 이름이 올바르지 않습니다.

C:\>cd C:\Users\admin\PycharmProjects\pythonwork1\contact.py
디렉터리 이름이 올바르지 않습니다.

C:\>cd C:\Users\admin\PycharmProjects\pythonwork1

C:\Users\admin\PycharmProjects\pythonwork1>python contact.py
Traceback (most recent call last):
  File "contact.py", line 104, in <module>
    run()
  File "contact.py", line 43, in run
    load_contact(contact_list)
  File "contact.py", line 87, in load_contact
    f = open("C:/Users/admin/PycharmProjects/pythonwork1/test.txt", "rt")
FileNotFoundError: [Errno 2] No such file or directory: 'C:/Users/admin/PycharmProjects/pythonwork1/test.txt'

C:\Users\admin\PycharmProjects\pythonwork1>python contact.py
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 종료
메뉴선택:

함수와 모듈

함수 선언

def print_ntimes(): 
 	print("대신증권") 
    
#값을 전달 할 때
def print_ntimes(n): 
 	print("대신증권") 
    

 

함수가 호출되고 전달하는 과정

def cal_upper(price): 
        increment = price * 0.3 
        upper_price = price + increment 
        return upper_price  
cal_upper(10000) 
#13000.0

#리턴 값을 두개 이상 돌려 줄 수 있다 단, 튜플 형태로 묶어 주어야한다.
#또한 전달 받는 변수도 2개가 있어야 한다.
>def cal_upper_lower(price): 
        offset = price * 0.3 
        upper = price + offset 
        lower = price - offset 
        return (upper, lower)
        
(upper, lower) = cal_upper_lower(10000) 
upper 
#13000.0 
lower 
#7000.0 

모듈

- 기능이 분리 되어있는 하나의 파일

함수를 만들어서 import 시켜서 가져오기

#함수를 만들어서 import 시켜서 가져오기

#stock.py

#상한가 구해주는 함수
def cal_upper(price): 
    increment = price * 0.3 
    upper_price = price + increment 
    return upper_price 

#하한가를 구해주는 함
def cal_lower(price): 
    decrement = price * 0.3 
    lower_price = price - decrement 
    return lower_price

author ="pystock"

#20200410.py
import stock

print(stock.cal_upper(10000)) 
print(stock.cal_lower(10000))
#stock.cal_lower(10000) #shell에서만 나옴
print(__name__) 


#shell
#13000.0
#7000.0
#__main__ 

########################################################################################
#print(__name__)
#__main__  관한 설명

if __name__ == "__main__": 
    print(cal_upper(10000)) 
    print(cal_lower(10000)) 
    print(__name__)
    
#shell   
#13000.0
#7000.0
#__main__ 

import stock 
#shell   
#13000.0
#7000.0
#stock
#print(__name__)의 결과로 __main__이라는 문자열이 출력되지만, 
#해당 모듈을 임포트했을 때는 모듈의 이름인 stock이라는 문자열이 출력된다는 점입니다
#__name__이라는 변수는 파이썬 자체에서 사용하는 변수로 특정 파이썬 파일이 직접 실행된 것인지
#또는 다른 파이썬 파일에서 임포트 된 것인지를 확인하는 용도로 사용됩니다
#모듈의 테스트 코드가 모듈을 임포트했을 때 자동으로 호출되는 문제를 해결

 

파이썬에서 시간 다루기

import time 
time.time() 
#1444532446.467043 
time.ctime()
#'Sun Oct 11 12:00:50 2015' 
type(time.ctime())
#<class 'str'> 

#문자열을 나누기
cur_time = time.ctime()
print(cur_time.split(' ')[-1]) 
#2015

#1초 간격으로 출력하기(파이썬은 1초 단위, 자바는 0.001초)
for i in range(10): 
        print(i) 
        time.sleep(1) 

내부에 있는 함수 알아보기

# 해당 내부에 있는 함수들을 알아보기dir() 
import time 
dir(time) 

#['_STRUCT_TM_ITEMS', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'altzone', 
#'asctime', 'clock', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 
#'monotonic', 'perf_counter', 'process_time', 'sleep', 'strftime', 'strptime', 'struct_time', 'time', 
#'timezone', 'tzname'] 

#올대분자: 바꿀 수 없는 값 상수
#__로 시작: 변수
#아무 것도 없는 것 : 해당 함수 명

 

os 모듈

import os print(os.getcwd()) 
#C:\pythonwork #현재 내가 작업하는 곳에 있는 내용
print(os.listdir()) 
#['20200409.py', '20200409_1.py', '20200409_2.py', '20200409_3.py', '20200409_4.py', 
'20200409_5.py', '20200409_ex1.py', '20200409_ex2.py', '20200409_ex3.py', '20200409_ex4.py', 
'20200409_ex5.py', '20200409_ex6.py', #'20200410.py', '20200410_1.py', 'stock.py', 'test.py', 
'test2.py', '__pycache__'] 

#경로명을 넣으면 해당 경로의 파일 들을 찾아 줌 
print(os.listdir(경로명)) 

#끝이 exe로 끝나는 파일 찾기(확장자 찾기) 
for x in os.listdir('c:/Anaconda3'): 
	if x.endswith('exe'):
print(x) 

#모듈을 임포트하는 3가지 방법
import os 
from os import listdir # "os 모듈로부터(from) listdir을 임포트하라"
import os as winos # "os 모듈을 winos로 임포트하라"
  

 

주요 내장함수

 

#abs(x) 내장 함수

#-정수형 또는 실수형 값을 입력받은 후 해당 값의 절댓값을 반환하는 함수
#정수형 또는 실수형이 아닌 문자열 값이 입력되면 오류가 발생
abs(-3) 
#3
abs(3.0)
#3.0

#chr(i) 내장 함수

#유니코드 값을 입력받은 후 해당 값에 해당하는 문자열을 반환
chr(97)
#a

#enumerate() 내장 함수

#입력으로 시퀀스 자료형(리스트, 튜플, 문자열) 등을 입력받은 후 enumerate 객체를 반환
#for 문에서 시퀀스 자료형 내의 값과 인덱스를 동시에 구하고 싶을 때 자주 사용

for i, stock in enumerate(['Naver', 'KAKAO', 'SK']): 
	 print(i, stock)
#0 Naver 
#1 KAKAO 
#2 SK 

#id(object) 내장 함수

#객체를 입력받아 해당 객체의 고윳값을 반환
>>> a = 1 
>>> b = 1 
>>> id(a) 
#1918947744 
>>> id(b) 
#1918947744 

#len(s) 내장 함수

#리스트, 튜플, 문자열, 딕셔너리등을 입력받아 그 객체의 원소 개수를 반환
>>> len(['SK', 'naver']) 
#2 
>>> len('SK hynix') 
#8 
>>> len({1:'SK', 2:'Naver'}) 
#2

#list() 내장 함수
#문자열이나 튜플을 입력받은 후 리스트 객체로 만들고 해당 리스트를 반환
#튜플을 리스트로 변환할 때 자주 사용
>>> list('hello') 
['h', 'e', 'l', 'l', 'o'] 
>>> list((1,2,3)) 
[1, 2, 3] 

#max() 내장 함수는 입력값 중 최댓값을 반환합니다.
#min() 내장 함수는 입력값 중 최솟값을 반환합니다
>>> max(1,2,3) 
3 
>>> max([1,2,3]) 
3 
>>> min(1,2,3) 
1 
>>> min([1,2,3]) 
1 

#sorted() 내장 함수
#입력값을 정렬한 후 정렬된 결괏값을 '리스트'로 반환
>>> sorted((4,3,1,0)) 
[0, 1, 3, 4] 
>>> sorted([5, 4, 3, 2, 1]) 
[1, 2, 3, 4, 5] 
>>> sorted(['c', 'b', 'a']) 
['a', 'b', 'c'] 

#int(x) 내장 함수는 문자열을 인자로 입력받아 해당 문자열을 정수형으로 변환한 후 반환
#str(x) 내장 함수는 객체를 입력받아 문자열로 변환
#문자열을 정수형으로, 정수형을 문자열로 변환할 때 자주 사용
>>> int('3') 
3 
>>> str(3) 
'3'

 

연습문제

#1.두 개의 정수 값을 받아 두 값의 평균을 구하는 함수를 작성하세요.
def myaverage(a,b):
    a=int(input("첫번째 정수를 입력해주세요. :"))
    b=int(input("두번째 정수를 입력해주세요. :"))
    c = (a+b)/2
    print(c)

def myaverage(a, b):
    c = (a + b) / 2
    return c

#2.함수의 인자로 리스트를 받은 후 리스트 내에 있는
#모든 정수 값에 대한 최댓값과 최솟값을 반환하는 함수를 작성하세요.
data_list=[1,2,3,4,5]
def get_max_min(data_list):
    print(max(data_list))
    print(min(data_list))

def get_max_min(data_list):
    d1 = max(data_list)
    d2 = min(data_list)
    return (d1, d2)

#3.절대 경로를 입력받은 후 해당 경로에 있는
#*.txt 파일의 목록을 파이썬 리스트로 반환하는 함수를 작성하세요.
import os

path='c:/Anaconda3'
def get_txt_list(path):
    for x in os.listdir(path):
        if x.endswith('txt'):
             print(x)
            
#절대경로 :'c:/Anaconda3/20155' 무조건 찾아줘야할 때
#상대경로:"./20155"

#4.체질량 지수(Body Mass Index, BMI)는 인간의 비만도를 나타내는 지수로서
#체중과 키의 관계로 아래의 수식을 통해 계산됩니다.
#여기서 중요한 점은 체중의 단위는 킬로그램(kg)이고 신장의 단위는 미터(m)라는 점입니다. 
#BMI=체중(kg)신장(m)2BMI=체중(kg)신장(m)2 
#일반적으로 BMI 값에 따라 다음과 같이 체형을 분류하고 있습니다.
#BMI <18.5, 마른체형 
#18.5 <= BMI < 25.0, 표준 
#25.0 <= BMI < 30.0, 비만 
#BMI >= 30.0, 고도 비만 
#함수의 인자로 체중(kg)과 신장(cm)을 받은 후
#BMI 값에 따라 '마른체형', '표준', '비만', '고도 비만' 중 하나를 출력하는 함수를 작성하세요.
def bmi_cal(kg, cm):
    bmi = kg / ((cm/100)**2)
    if bmi < 18.5:
        print("마른체형")
    elif 18.5 <= bmi < 25.0:
         print("표준")
    elif 25.0 <= bmi < 30.0:
        print("비만")
    elif bmi >= 30.0:
        print("고도비만")

#5.사용자로부터 키(cm)와 몸무게(kg)를 입력받은 후
#BMI 값과 BMI 값에 따른 체형 정보를 화면에 출력하는 프로그램을 작성해 보세요.
#파이썬에서 사용자로부터의 입력은 input() 함수를 사용하며,
#작성된 프로그램은 계속해서 사용자로부터 키와 몸무게를 입력받은 후 BMI 및 체형 정보를
#출력해야 합니다(무한 루프 구조).
def bmi_program():
    while 1:
        kg = int(input("몸무게를 입력하세요.(kg)"))
        m = int(input("키를 입력하세요.(cm)"))
        bmi = kg / ((m/100)**2)
        if bmi < 18.5:
            print("마른체형")
        elif 18.5 <= bmi < 25.0:
             print("표준")
        elif 25.0 <= bmi < 30.0:
            print("비만")
        elif bmi >= 30.0:
            print("고도비만")


#6.삼각형의 밑변과 높이를 입력받은 후 삼각형의 면적을 계산하는 함수를 작성하세요.
def get_triangle_area(width, height):
        width=int(input("밑변을 입력해주세요. :"))
        height=int(input("높이을 입력해주세요. :"))
        c = = width * height / 2
        print(c)
        
#7. 함수의 인자로 시작과 끝 숫자를 받아 시작부터
#끝까지의 모든 정수값의 합을 반환하는 함수를 작성하세요(시작값과 끝값을 포함).
def add_start_to_end(start, end):
    a = range(start, end+1)
    suma = sum(a)
    return suma

#8.함수의 인자로 문자열을 포함하는 리스트가 입력될 때 각 문자열의 첫 세 글자로만 구성된 리스트를 반환하는 함수를 작성하세요.
#예를 들어, 함수의 입력으로 ['Seoul', 'Daegu', 'Kwangju', 'Jeju']가 입력될 때 함수의 반환값은 ['Seo', 'Dae', 'Kwa', 'Jej']입니다.
a=['Seoul', 'Daegu', 'Kwangju', 'Jeju']
def first_three(list):
    lis = []
    for i in range(len(list)):
        lis.append(list[i][0:3])
    return lis

 

클래스

class BusinessCard:
    pass

card1= BusinessCard()
card1
# 'BusinessCard'라는 클래스의 인스턴스가 메모리의 0x0302ABB0 위치에 생성되고
# card1이라는 변수가 이를 바인딩하게 됩니다.
#<__main__.BusinessCard object at 0x0302ABB0>

type(card1) 
#<class '__main__.BusinessCard'>

class BusinessCard: 
        def set_info(self, name, email, addr): #일반 함수 set_info : 3가지 값을 전달 받아서 name,email,addr에 값을 준다
                self.name = name 
                self.email = email 
                self.addr = addr 
#자바처럼 변수를 선언 해줄 필요가 없다. self를 붙이면 된다.
#무조건 매개 변수명은 self를 넣어준다.

member1= BusinessCard()

#클래스 인스턴스를 통한 메서드 호출
member1.set_info("Yuna Kim", "yunakim@naver.com", "Seoul") 
member1.name
#'Yuna Kim' 
member1.email
#'yunakim@naver.com' 
member1.addr
#'Seoul'

 

'''class BusinessCard:
    pass

card1= BusinessCard()
card1
# 'BusinessCard'라는 클래스의 인스턴스가 메모리의 0x0302ABB0 위치에 생성되고
# card1이라는 변수가 이를 바인딩하게 됩니다.
#<__main__.BusinessCard object at 0x0302ABB0>

type(card1) 
#<class '__main__.BusinessCard'>

class BusinessCard: 
        def set_info(self, name, email, addr): #일반 함수 set_info : 3가지 값을 전달 받아서 name,email,addr에 값을 준다
                self.name = name 
                self.email = email 
                self.addr = addr 
#자바처럼 변수를 선언 해줄 필요가 없다. self를 붙이면 된다.
#무조건 매개 변수명은 self를 넣어준다.

member1= BusinessCard()

#클래스 인스턴스를 통한 메서드 호출
member1.set_info("Yuna Kim", "yunakim@naver.com", "Seoul") 
member1.name
#'Yuna Kim' 
member1.email
#'yunakim@naver.com' 
member1.addr
#'Seoul'
'''

#생성자추가
class BusinessCard: 
        def __init__(self, name, email, addr): #일반 함수 set_info : 3가지 값을 전달 받아서 name,email,addr에 값을 준다
                self.name = name 
                self.email = email 
                self.addr = addr

        def print_info(self):
            print("----------")
            print("NAme",self.name)
            print("email",self.email)
            print("addr",self.addr)
            print("----------")
            
# 생성자에 전달되는 값이 없으면 오류
#member1= BusinessCard()
member1= BusinessCard("Yuna Kim", "yunakim@naver.com", "Seoul")
member1.print_info()

###self 이해하기####
class Foo:
    def func1():
        print("function 1")

    def func2(self):
        print("function 2")
'''
func1() 메서드의 첫번 째 인자가 self가 아님에도
클래스를 정의 할 때 에러가 발생하지 않는다는 점
'''
f=Foo()
#NAme Yuna Kim
#email yunakim@naver.com
#addr Seoul

"""
Foo 클래스의 func2 메서드는
메서드의 인자가 self 뿐이므로
실제 메서드를 호출할 때는 인자를 전달할 필요가 없다.

func2 메서드의 첫 번째 인자를 self 지만
호출할 때는 아묵서도 전달하지 않는 이유는
첫 번째 인자인 self에 대한 값은
파이썬이 자동으로 넘겨주기 때문
"""

f.func2()
#function 2

''' func1 처럼
메서드를 정의할 떄부터 아무 인자도 없는 경우에는
인스턴스를 통해 func1()을 호출하면 오류가 발생

'func1() 인자는 없지만 하나를 받았다'는 오류 발생
'''

'''self의 정체를 좀더 확실하 밝혀보기 위해
Foo클래스를 수정 해 파이썬 내장 함수인 id()를 이용해
인스턴스가 메모리에 할당된 주소 값을 확인
'''
print("----------")
print("f = Foo() => ", id(f))
#f = Foo() =>  59880472
#인스턴스의 메모리 주소 확인
"""
실행 결과를 살펴보면 42315162 라는 값이 출력됨을 확인할 수 있다.

Foo 클래스를 정의할 때 id(self)를 출력하게 했는데
id(self)의 값이 바로 61068096 인 것
"""
print("----------")
f2=Foo()
print("f2 = Foo() => ", id(f2))
f.func2()
#f2 = Foo() =>  51160112
#function 2
"""
f2를 통해 func2 메서드를 호출해보면 57730192가 출력됐습니다.
이 값은 바로 f2가 가리키고 있는 객체를 의미한다.
"""

'''
파이썬의 클래스는 그 자체가 하나의 네임스페이스이기 때문에
인스턴스 생성과 상관없이
클래스 내의 메서드를 직접 호출 할 수 있다.
'''
print("----------")
Foo.func1()
#function 1
'''
func1()을 호출 했지만 앞서 인스턴스를 통해 메서드를 호출 했던 것과는 달리
오류가 발생하지 않는다.
왜냐하면 인스턴스.메서드() 형태로 호출한 것과 달리
이번에는 클래스 이름.메서드() 형태로 호출했기 때문
'''

#Foo.func2() 로 호출하면 self값을 전달 못해서 에러 발생
"""
클래스 이름을 통해 func2() 메서드를 호출하려고 하면
self 위치에 인자를 전달해야 한다고 파이썬 인터프리터가 알려주낟.
>>> 모드에서 테스트

self 위치에 인자를 전달하지 않고 메서드를 호출하면 오류 발생

오류 메시지:
 func2() missing 1 required positional argument:'self'

오류 메시지를 확인하면
 func2()를 호출할 때 인자를 하나 빼먹읐음을 알 수 있다.
 즉, 인자를 하나 전달해야 하는데 전달하지 않아서 오류가 발생한 것.
"""

 

class Stock:
    market = "kospi"

print(dir())

"""
2개의 언더바로 시작하는 것은 파이썬에서 이미 사용 중인 특별한 것들

이를 제외하고 보면 조금 전에 정의했던 Stock 클래스의 이름이 포함된 것을 확인할 수 있다.

파이썬에서는 클래스가 정의되면 하나의 독립적인 네임스페이스가 생성된다.
그리고 클래스 내에 정의된 변수가 메서드는
그 네임스페이스 안에 파이썬 딕셔너리 타입으로 저장된다.

Stock 클래스는
Stock 이라는 네임스페이스 안에 'market':'kospi'라는 값을 가진 딕셔너리를 포함한다.
"""

# 파이썬 클래스 네임스페이스

"""
Stock 클래스의 네임스페이스를 파이썬 코드로 확인하려면
클래스의 __dict__ 속성을 확인.
"""

print("Stock.__dict__ => ", Stock.__dict__)

"""클래스가 독립적인 네임스페이스를 가지고
클래스 내의 변수나 메서드를 네임스페이스에 저장하고 있으므로
다음과 같이 클래스 내의 변수에 접근할 수 있는 것이다.
"""

print("Stock.market =>", Stock.market)


s1 = Stock() 
s2 = Stock()

print("s1 = Stock() =>", id(s1))
print("s2 = Stock() =>", id(s2))

"""
생성된 s1, s2 인스턴스가 네임스페이스에 있는지 코드를 통해 확인.
dir() 내장함수의 반환값을 확인하면
s1, s2가 Stock과 마찬가지로 존재하는 것을 확인할 수 있다.
"""

print(dir())



"""
s1과 s2인스턴스의 네임스페이스는 현재 비어있는 것을 확인할 수 있다.
"""

print("s1.__dict__ =>", s1.__dict__)
print("s2.__dict__ =>", s2.__dict__)

"""
s1 인스턴스에 market 이라는 변수를 추가한 후, 다시 __dict__ 속성을 확인해보면
'market':'kosdaq' 이라는 키:값 쌍이 추가된 것을 볼 수 있다.
"""

s1.market='kosdaq'
print("s1.__dict__ =>", s1.__dict__)
print("s2.__dict__ =>", s2.__dict__)




# 파이썬 클래스 네임스페이스

"""
Stock 클래스의 네임스페이스를 파이썬 코드로 확인하려면
클래스의 __dict__ 속성을 확인.
"""

print("Stock.__dict__ => ", Stock.__dict__)

"""
클래스가 독립적인 네임스페이스를 가지고
클래스 내의 변수나 메서드를 네임스페이스에 저장하고 있으므로
다음과 같이 클래스 내의 변수에 접근할 수 있는 것이다.
"""

print("Stock.market =>", Stock.market)


s1 = Stock() 
s2 = Stock()

print("s1 = Stock() =>", id(s1))
print("s2 = Stock() =>", id(s2))

"""
생성된 s1, s2 인스턴스가 네임스페이스에 있는지 코드를 통해 확인.
dir() 내장함수의 반환값을 확인하면
s1, s2가 Stock과 마찬가지로 존재하는 것을 확인할 수 있다.
"""

#print(dir())



"""
s1과 s2인스턴스의 네임스페이스는 현재 비어있는 것을 확인할 수 있다.
"""

#print("s1.__dict__ =>", s1.__dict__)
#print("s2.__dict__ =>", s2.__dict__)

"""
s1 인스턴스에 market 이라는 변수를 추가한 후, 다시 __dict__ 속성을 확인해보면
'market':'kosdaq' 이라는 키:값 쌍이 추가된 것을 볼 수 있다.
"""

#s1.market='kosdaq'

#print("s1.__dict__ =>", s1.__dict__)
#print("s2.__dict__ =>", s2.__dict__)

###############

"""
만약 s1.market, s2.market과 같이 인스턴스를 통해 market이라는 값에 접근하면?
"""
#print("s1.market =>", s1.market)
#print("s2.market =>", s2.market)

"""
s2 인스턴스를 통해 변수에 접근하면
파이썬은 먼저 s2 인스턴스의 네임 스페이스에서 해당 변수가 존재하는지 찾는다.


만약 s2의 네임스페이스에 해당 변수가 존재하지 않으면
s2 인스턴스의 클래스 네임스페이스로 가서 다시 변수를 찾게 된다.
"""

"""
 
즉,
    
s2.market 이라는 문장이 실행되면
Stock 클래스의 네임스페이스에 있는
'market':kospi''
키:값 쌀에서 'kospi'라는 문자열을 출력하게 된다.

"""

  
# 클래스 변수와 인스턴스 변수


"""
은행 계좌를 클래스로 표현

Account 클래스
생성자(__init__) : 클래스의 인스턴스가 생성될 때 자동으로 호출되는 함수
소멸자(__del__) : 클래스의 인스턴스가 소멸될 때 자동으로 호출되는 함수

"""


 

#클래스 상속#
class Parent:
    def can_sing(self):
        print("Sing a song")

father = Parent()
father.can_sing()

class LuckyChild(Parent):
    pass

child1 = LuckyChild()
child1.can_sing()

class UnLuckyChild:
    pass

child2=luckyChild2()
child2.can_sing()
child2.can_sing()

#### 파일 읽기 #####

"""
open('파일경로/파일명.확장자','모드')

경로: '\\' 또는 '/'
파일을 읽기 모드로 열려명 r 을
텍스트 파일인 경우에는 t
"""

f = open("C:\\rStudy\\20200410\\list.TXT","rt", encoding='UTF8')

lines = f.readlines()

print("lines => ", lines)

"""
출력된 후 빈 줄이 하나씩 존재
print()는 문자열을 출력할 때 자동으로 줄바꿈을 하는데
기존에 lines라는 리스트에 있는 문자열에도
줄 바꿈을 의미하는 값인 '\n'가 들어 있기 때문.
"""

for line in lines:
    print(line)

"""
lines 리스트에 있는 원소에서 \n 기호를 제거함으로써 중복으로 줄바꿈되지 않도록
코드를 작성
"""

for line in lines:
    print(line, end="")


################ 파일 쓰기 #############
f = open('sel_list.TXT', 'wt')

f.write('삼전\n')
f.write('하이닉스\n')
f.close()

 

 

 

 

파이참 설치

 

파이썬->기본

파이썬->주식 기본

         -> 함수/클래스

         ->UI

파이썬->데이터처리

         ->분석

         ->시각화

 

파이썬->deep

         ->챗봇

Deep->python

       ->keras

       ->텐서플로우

 

1. 파이썬 소개

인스톨 나우 해준다.

https://www.python.org 

불러오는 중입니다...

https://docs.python.org/3.8/tutorial/index.html 

 

The Python Tutorial — Python 3.8.2 documentation

The Python Tutorial Python is an easy to learn, powerful programming language. It has efficient high-level data structures and a simple but effective approach to object-oriented programming. Python’s elegant syntax and dynamic typing, together with its int

docs.python.org

https://docs.python.org/ko/3.8/tutorial/index.html 

불러오는 중입니다...

IDLE를 실행 해준다.

NEW File 실행

run-> F5

 

요즘은 플라스크로 웹개발을 한다.

 

 

터틀 그래픽

- 화면에서 거북이를 이용하여 그림을 그리는 기능. 거북이가 펜을 가지고 있고, 사용자가 화면에서 거북이를 움직이면 그림이 그려진다. 

 

import turtle
t=turtle.Turtle()

#커서 모양을 거북이 모양으로 바꿔달라.
t.shape("turtle")

t.forward(100)
t.left(90)
t.forward(100)

j

터틀 데모 코드를 확인 할 수 있다.

 

스크립트(script mode) 모드 

코드가 복잡해지면 인터프리터 모드는 번거롭다 

*인터프리터: 원시 언어의 명령을 번역 실행하는 프로그램

텍스트 에디터를 이용하여 명령어들을 파일에 저장한 후에  파일을 읽어서 명령어들을 하나씩 실행하는 방법이 있다.  명령어들이 저장된 파일을 소스 파일(source file) 

예)

소스파일을 만들 때 뒤에 _이니셜을 해준다.

 

 

다크모드로 바꿔주기

Options-> Settings->IDLE Dark 로 바꿔줌

 

함수 오류

 

1) 프로그램은 컴퓨터에 내리는 명령으로 이루어지는 작업지시서.  
2) 다양한 종류의 프로그래밍 언어가 있고 파이썬도 프로그래밍 언어의 일종.  
3) 파이썬은 http://www.python.org 웹사이트에서 다운로드받아서 설치할 수 있다.  
4) IDLE은 파이썬으로 프로그램을 작성하기 위한 개발 환경이다.  
5) 파이썬에서 산술 계산을 하는 연산자에는 +, -, *, /가 있다.  
6) print()는 화면에 문자열이나 계산 결과를 출력할 수 있다. 
7) 스크립트 모드를 사용하면 코드를 파일에 저장하였다가 한꺼번에 실행할 수 있다

 

 

import turtle
colors=["red","purple","blue","green","yellow","orange"]
t=turtle.Turtle()

turtle.bgcolor("black")
t.speed(0)# 숫자가 크면 느려진다.
t.width(3)
length=10

while length<500: # 500 보다 작을 때 까지 반복시켜라
    t.forward(length) # 조건이 만족 되면 앞으로 10 전진시킨다.
    t.pencolor(colors[length%6]) #선 색을 변경 시킨다(pencolor())
    t.right (89) # 시계 방향으로 89도 틀어라
    length += 5 # 이동거리를 5 더해라
    
    
#터틀 그래픽의 명령어 단축 가능  
forward( ) => fd( ) 
left( ) => lt( ) 
right( ) => rt( ) 

 

 

2. 변수소개

 

사용자로부터 정수 입력 받기(input())

파이썬에서 사용자로부터 무엇인가를 입력받을 경우 사용. 

사용자의 입력을 무조건 문자열 형태로 반환.                

연산을 위해 정수로 변환할 경우 int( ) 로 감싸야 한다.

 

3. 연산자

#몇 각형을 그리겠습니까?

import  turtle
t = turtle.Turtle()
t.shape("turtle")
n = int(input("몇각형을 그리시겠어요?: "))

for i in range(n): #입력 수 만큼 반복한다.
    t.forward(100) # 반복되는 문장을 들여쓰기 하여 적는다.
    t.left(360//n)
# 커피 가게 매출계산

americano_price=2000
cafelatte_price=3000
capucinos_price=3500

americanos = int(input("아메리카노 판매 개수:"))
cafelattes=int(input("카페라떼 판매 개수:"))
capucinos=int(input("카푸치노  판매 개수:"))

sales=americanos *americano_price
sales=sales+cafelattes*cafelatte_price
sales=sales+capucinos*capucinos_price

print("총 매출은", sales,"입니다.")
weigth = float(input("몸무게를 kg단위로 입력하시오 :"))
heigth = float(input("키를 미터 단위로 입력하시오 :"))

bml=(weigth/(heigth**2)) # 파이썬은 제곱을 **로 입력한다.
print("당신의 BML=",bml)
#알고리즘의 가장 기초 단계
# 자동판매기 프로그램
money=int(input("투입된 돈 : "))
price=int(input("물건 값:"))

change=money-price
print("거스름돈:",change)
coin500s=change//500 #500으로 나누어서 몫이 500원짜리의 개수
change-change%500 # 500으로 나눈 나머지를 계산한다.
coin100s=change//100 #100으로 나누어서 몫이 100짜리의 개수

print("500원 동전의 개수:",coin500s)
print("100원 동전의 개수:",coin100s)

 

파이썬으로 무엇을 할 수 있는가?

 

시스템 유틸리티 제작 
파이썬은 운영체제(윈도우, 리눅스 등)의 시스템 명령어들을 이용할 수 있는 각종 도구를 갖추고 있기 때문에 이를 바탕으로 갖가지 시스템 유틸리티 1를 만드는 데 유리하다. 실제로 여러분은 시스템에서 사용 중인 서로 다른 유틸리티성 프로그램들을 하나로 뭉쳐서 큰 힘을 발휘하게 하는 프로그램들을 무수히 만들어낼 수 있다. 

 

GUI 프로그래밍 
GUI(Graphic User Interface) 프로그래밍이란 쉽게 말해 윈도우 창처럼 화면을 보며 마우스나 키보드로 조작할 수 있는 프로그램을 만드는 것이다. 파이썬으로 GUI 프로그램을 만드는 것은 다른 언어를 이용해 만드는 것보다 훨씬 쉽다. 대표적인 예로 파이썬 프로그램을 설치할때 함께 설치되는 기본 모듈인 Tkinter(티케이인터)를 이용해 만드는 GUI 프로그램을 들 수 있다. 실제로 Tkinter를 이용한 파이썬 GUI 프로그램의 소스 코드는 매우 간단하다. Tkinter를 이용하면 단 5줄의 소스 코드만으로도 윈도우 창을 띄울 수 있다. 놀랍지 않은가! 
※ 파이썬에는 wxPython, PyQT, PyGTK 등과 같이 Tkinter보다 빠른 속도와 보기 좋은 인터페이스를 자랑하는 것들도 있다. 


C/C++와의 결합 
파이썬은 접착(glue) 언어라고도 부르는데, 그 이유는 다른 언어들과 잘 어울려 다른 언어와 결합해서 사용할 수 있기 때문이다. C나 C++로 만든 프로그램을 파이썬에서 사용할 수 있으며, 파이썬으로 만든 프로그램 역시 C나 C++에서 사용할 수 있다. 

 

웹 프로그래밍 
일반적으로 익스플로러나 크롬, 파이어폭스와 같은 브라우저를 이용해 인터넷을 사용하는데, 누구나 한 번쯤 웹 서핑을 하면서 게시판이나 방명록에 글을 남겨 본 적이 있을 것이다. 그러한 게시판이나 방명록을 바로 웹 프로그램이라고 한다. 파이썬은 웹 프로그램을 만들기에 매우 적합한 도구이며 실제로 파이썬으로 제작된 웹사이트는 셀 수 없을 정도로 많다. 


수치 연산 프로그래밍 
사실 파이썬은 수치 연산 프로그래밍에 적합한 언어는 아니다. 수치가 복잡하고 연산이 많다면 C같은 언어로 하는 것이 더 빠르기 때문이다. 하지만 파이썬에는 Numeric Python이라는 수치 연산 모듈이 제공된다. 이 모듈은 C로 작성되었기 때문에 파이썬에서도 수치 연산을 빠르게 할 수 있다. 


데이터베이스 프로그래밍 
파이썬은 사이베이스(Sybase), 인포믹스(Infomix), 오라클(Oracle), 마이에스큐엘(MySQL), 포스트그레스큐엘(PostgreSQL) 등의 데이터베이스에 접근할 수 있게 해주는 도구들을 제공한다. 
또한 이런 굵직한 데이터베이스를 직접 이용하는 것 외에도 파이썬에는 재미있는 모듈이 하나 더 있다. 바로 피클(pickle)이라는 모듈이다. 피클은 파이썬에서 사용되는 자료들을 변형없이 그대로 파일에 저장하고 불러오는 일들을 맡아 한다. 이 책에서는 외장 함수에서 피클을 어떻게 사용하고 활용하는지에 대해서 알아본다. 


데이터 분석, 사물 인터넷 
파이썬으로 만들어진 판다스(Pandas)라는 모듈을 이용하면 데이터 분석을 더 쉽고 효과적으로 할 수 있다. 데이터 분석을 할 때 아직까지는 데이터 분석에 특화된 "R"이라는 언어를 많이 사용하고 있지만, 판다스가 등장한 이후로 파이썬을 이용하는 경우가 점점 증가하고 있다. 사물 인터넷 분야에서도 파이썬은 활용도가 높다. 한 예로 라즈베리파이(Raspberry Pi)는 리눅스 기반의 아주 작은 컴퓨터이다. 라즈베리파이를 이용하면 홈시어터나 아주 작은 게임기 등 여러 가지 재미있는 것들을 만들 수 있는데 파이썬은 이 라즈베리파이를 제어하는 도구로 사용된다. 예를 들어 라즈베리파이에 연결된 모터를 작동시키거나 램프에 불이 들어오게 하는 일들을 파이썬으로 할 수 있다.

 

파이썬으로 할 수 없는 일 

시스템과 밀접한 프로그래밍 영역 
파이썬으로 도스나 리눅스 같은 운영체제, 엄청난 횟수의 반복과 연산을 필요로 하는 프로그램 또는 데이터 압축 알고리즘 개발 프로그램 등을 만드는 것은 어렵다. 즉, 대단히 빠른 속도를 요구하거나 하드웨어를 직접 건드려야 하는 프로그램에는 어울리지 않는다. 

 

모바일 프로그래밍 
파이썬은 구글이 가장 많이 애용하는 언어이지만 파이썬으로 안드로이드 앱(App)을 개발하는 것은 아직 어렵다. 안드로이드에서 파이썬으로 만든 프로그램들이 실행되도록 지원하긴 하지만 이것만으로 앱을 만들기에는 아직 역부족이다. 아이폰 앱을 개발하는 것 역시 파이썬으로는 할 수 없다. 

 

조건문 if

반복문 for

반복문 while

 

파이썬의 함수

 

 

파이썬

1)리스트

interest = ["삼성전자", "LG전자", "네이버"] 
interest[0]
#삼성전자
interest[1]
#LG전자
interest[2]
#네이버

daishin = [9130, 9150, 9150, 9300, 9400] # 정수
daishin = [9130.0, 9150.0, 9150.0, 9300.0, 9400.0] # 실수
mystock = ['Naver', 5000] # 문자와 숫자 리스트 가능
mystock = [] # 빈 리스트를 만든다.

 

인덱싱

daishin = [9130, 9150, 9150, 9300, 9400] 
daishin[-1] # 리스트의 뒤 쪽부터 마지막 번째
#9400

리스트 슬라이싱

 kospi_top10 = ['삼성전자', 'SK하이닉스', '현대차', '한국전력', '아모레퍼시픽', '제일모직', 
'삼성전자우', '삼성생명', 'NAVER', '현대모비스']
 kospi_top5 = kospi_top10[0:5] # 0번째부터 4번째까지
 kospi_top5 
 
 kospi_top10[5:] #5번부터 마지막까지
 #['제일모직', '삼성전자우', '삼성생명', 'NAVER', '현대모비스']

 kospi_top10[5:-1] 

데이터 삽입하기(append)

 kospi_top10 = ['삼성전자', 'SK하이닉스', '현대차', '한국전력', '아모레퍼시픽', '제일모직', 
'삼성전자우', '삼성생명', 'NAVER', '현대모비스'] 
kospi_top10.append('SK텔레콤')
kospi_top10 

#['삼성전자', 'SK하이닉스', '현대차', '한국전력', '아모레퍼시픽', '제일모직', '삼성전자우', '삼성생
명', 'NAVER', '현대모비스', 'SK텔레콤'] 

데이터 삽입하기(insert)

원하는 곳에 삽입 할 수 있다.

 kospi_top10 = ['삼성전자', 'SK하이닉스', '현대차', '한국전력', '아모레퍼시픽', '제일모직', 
'삼성전자우', '삼성생명', 'NAVER', '현대모비스']
 kospi_top10.insert(3, 'SK 텔레콤') 
 kospi_top10 
 
 #['삼성전자', 'SK하이닉스', '현대차', 'SK 텔레콤', '한국전력', '아모레퍼시픽', '제일모직', '삼성전
자우', '삼성생명', 'NAVER', '현대모비스'] 

데이터 개수를 확인하기(len)

kospi_top10 = ['삼성전자', 'SK하이닉스', '현대차', 'SK 텔레콤', '한국전력', '아모레퍼시픽', '제일모직', '삼성전
자우', '삼성생명', 'NAVER', '현대모비스'] 
 len(kospi_top10) # 리스트의 개수를 확인하기
 #11

 

데이터 삭제하기(del)

 kospi_top10[-1] 
 #현대모비스
 del kospi_top10[-1] 
 kospi_top10
 #['삼성전자', 'SK하이닉스', '현대차', 'SK 텔레콤', '한국전력', '아모레퍼시픽', '제일모직', '삼성전
자우', '삼성생명', 'NAVER'
 len(kospi_top10)
 #10

2)튜플

1) 리스트는 '[' 와 ']'를 사용하는 반면 튜플은 '('와 ')'를 사용한다.

2) 리스트는 리스트 내의 원소를 변경할 수 있지만 튜플은 변경할 수 없다. 

 

튜플 슬라이싱

 t 
('Samsung', 'LG', 'SK')
 t[0:2] 
 #('Samsung', 'LG')

3)딕셔너리

딕셔너리는 순서가 존재 하지 않는다.

인덱스 번호가 자동 부여 된다.

키(key)와 값(value)이라는 쌍으로 데이터를 구성해서 저장

 cur_price = {} #빈 딕셔너리 만들기
 type(cur_price) # 타입 알아보기
 #<class 'dict'> #딕셔너리 타입
 
 cur_price['daeshin'] = 30000 #키:deashin 값:30,000을 추가 합니다.
 cur_price 
 #{'daeshin': 30000} 
 
 cur_price['Daum KAKAO'] = 80000 
 cur_price
 # {'Daum KAKAO': 80000, 'daeshin': 30000} 
 len(cur_price)
 #2
 
 #추가한 데이터를 얻으려면 키 값을 사용
 cur_price['daeshin'] 
 #30000

딕셔너리 데이터 삽입

cur_price['naver'] = 800000 
cur_price 
#{'Daum KAKAO': 80000, 'naver': 800000, 'daeshin': 30000} 

딕셔너리 데이터 삭제

 del cur_price['daeshin'] 
 cur_price 
 #{'naver': 800000, 'Daum KAKAO': 80000} 

딕셔너리 키값만 불러오기

cur_price = {'Daum KAKAO': 80000, 'naver':800000, 'daeshin':30000} 
cur_price.keys() 
#dict_keys(['naver', 'Daum KAKAO', 'daeshin']) 

#리스트로 만들어서 반환
 list(cur_price.keys()) 
 #['naver', 'Daum KAKAO', 'daeshin'] 
 
#바인딩(묶기)
price_list = list(cur_price.values()) 
price_list
#[800000, 80000, 30000]

#들어있는지 확인하기
'Samsung' in cur_price.keys() 
#False

 

연습문제

 

#"환영합니다.","파이썬의 세계에 오신 것을 환영합니다","파이썬은 강력합니다."를 출력하세요
print("환영합니다")
print("파이썬의 세계에 오신 것을 환영합니다")
print("파이썬은 강력합니다")

print("반갑습니다. 파이썬!!")
print(2*3/10)
print("Hello","World","!!!")
#반갑습니다. 파이썬
#0.6
#Hello World !!!

#파이썬 쉘을 사용하여 한 주가 몇시간에 해당하는 지를 계산하시오
oneweek = 7
hours=24
result=oneweek*hours
print(oneweek*hours)
print( "한 주는 "+oneweek+"이고"+ "시간은"+hours+"입니다."+"따라서 결과는"+result)

#터틀 그래픽에서 거북이를 이동시켜서 다음과 같은 그림을 완성하시오,
#단, forward(), rigth(), left() 만을 이용.
import turtle
T=turtle.Turtle()
t.shape("turtle")
t.forward(100)
t.rigth(100)
t.forward(100)
t.left(100)
t.forward(100)

#터틀 그래픽에서 width( ) 함수를 호출하면 거북이가 그리는 선의 두께를 변경할 수 있다.
#거북이를 이동하여 다음과 같이 두께가 10인 선을 완성
import turtle
T=turtle.Turtle()
t.shape("turtle")
t. width(3)
t.forward(100)
t.rigth(100)

#터틀 그래픽에서 color( ) 함수를 호출하면 거북이가 그리는 선의 색상을 변경할 수 있다.
#색상을 파랑색으로 변경하여 다음과 같이 길이가 100 pixel 인 선을 완성.
import turtle
T=turtle.Turtle()
t.shape("turtle")
t. color("blue")
t.forward(100)

#터틀 그래픽에서 shape( )함수를 사용하면 거북이의 모양을 삼각형, 원, 사각형으로 변경할 수 있다.
#사각형으로 변경하고 100 pixel 길이의 직선완성.

import turtle
T=turtle.Turtle()
t.shape("square")
t.forward(100)

#터틀 그래픽에서 거북이가 이동할 때 선이 그려지지 않게 하려면
#t.up( ) 함수를 이용하여 펜을 들 수 있다.
#반대로 t.down( ) 함수는 펜을 내려놓는 함수.
#거북이를 화면 좌표(100, 200)으로 이동 시키려면 t.goto(100, 200) 와 같이 호출.
#이들 명령어를 조합하여 다음과 같은 그림을 완성.
import turtle
t=turtle.Turtle()
t.shape("turtle")

t.forward(100)
t.up()
t.goto(0,100)
t.down()
t.forward(100)

#터틀 그래픽에서 t.circle(100) 이라고 입력 후, 실행하면 화면에 반지름이 100인 원이 그려진다.
#이들 명령어를 조합하여 화면에 오륜기를 그리는 프로그램 작성
import turtle
t=turtle.Turtle()
t.shape("turtle")
t.speed(100)
t.circle(100)
t.up()
t.goto(100,0)
t.down()
t.circle(100)
t.up()
t.goto(200,0)
t.down()
t.circle(100)
t.up()
t.goto(80,-90)
t.down()
t.circle(100)
t.up()
t.goto(160,-90)
t.down()
t.circle(100)

#사용자한테 이름과 나이를 입력받고, 사용자의 나이가 100살이 되는 연도를
#화면에 출력하는 프로그램작성

name = input("이름을 입력하시오:")
age=int(intput("나이를 입력하시오:"))
year=2020 - age + 100
print(name"씨는" +year+"년에 100살이시네요!")

#사용자로부터 3개의 숫자를 받아서 평균을 계산하고, 결과를 출력하는 프로그램 완성
one=int(intput("첫번째 숫자를  입력하시오:"))
two=int(intput("두번째 숫자를 입력하시오:"))
three=int(intput("세번째 숫자를  입력하시오:"))

result=one+two+three/3

print(one,two,three+"의 평균은 "+result+"입니다.")

#사용자로부터 원의 반지름을 입력 받아서 원의 면적을 구하는 프로그램 완성.
circle=int(intput("원의 반지름을  입력하시오:"))
result=3.141592 * (circle**2)
print("반지름이"+circle+"인 원의 넓이 = "+result)

'''원의 반지름을 변수 radius에 저장. radius의 초기값은 50.
radius 변수를 20씩 증가시키면서 (0, 0) (100, 0) (200, 0) 좌표에 각각 원을 3개 완성.
단, 터틀 그래픽을 이용하고, 반복문은 사용하지 않는다'''

import turtle
t=turtle.Turtle()
t.shape("turtle")
t.speed(100)

radius=50
t.goto(0,0)
t.down()
t.circle(radius)
t.up()

radius=50+20
t.goto(100,0)
t.down()
t.circle(radius)
t.up()

radius=50+20+20
t.goto(200,0)
t.down()
t.circle(radius)


#삼각형의 한 변의 길이를 side 변수로 나타낸다.
#side 변수의 초기값은 100. side 변수를 이용하여 화면에 삼각형을 완성.
mport turtle
t=turtle.Turtle()
t.shape("turtle")

side=100
t.speed(100)
t.forward(side)
t.left(120)
t.forward(side)
t.left(120)
t.forward(side)
t.left(120)
#5번 문제에서 삼각형의 한 변의 길이를 side 변수로 표시.
#만약 삼각형 한변의 길이를 200으로 변경한다면 5번 코드에서 어디만 수정하면 되는가?
side=200

#다음과 같은 그림을 그리는 프로그램을 작성.
#이 때 작은 사각형의 한 변의 길이는 side 변수에 저장하고, 거북이가 회전하는 각도는 angle 변수에 저장.
import turtle
side = 100
ang = 90 #회전 각도
t=turtle.Turtle()
t.shape("turtle")

t.fd(side)
t.rt(ang)
t.fd(side)
t.rt(ang)
t.fd(side)
t.rt(ang)
t.fd(side)

t.fd(side)
t.rt(ang)
t.fd(side)
t.rt(ang)
t.fd(side)

t.fd(side)
t.lt(ang)
t.fd(side)
t.lt(ang)
t.fd(side)

t.fd(side)
t.lt(ang)
t.fd(side)
t.lt(ang)
t.fd(side)
t.lt(ang)
t.fd(side)

#사용자로부터 두 개의 정수를 입력 받아서 정수의 합, 차, 곱, 평균, 큰 수, 작은 수를 계산하여
#화면에 출력하는 프로그램을 작성
#파이썬이 제공하는 max(x, y) / min(x, y) 함수를 사용
x=int(intput("첫번째 숫자를  입력하시오:"))
y=int(intput("두번째 숫자를 입력하시오:"))

a=x+y
b=x-y
c=x*y
d=x+y/2

e=max(x, y)
f=min(x, y)

ptint(a,b,c,d,e,f)


#원기둥의 부피를 계산하는 프로그램을 작성.
#원기둥의 부피 공식 : V=원주율*반지름의 제곱*높이
radius=int(intput("반지름을 입력하시오:"))
heigth=int(intput("높이를 입력하시오:"))
cylinder=3.14**radius*heigth

#사용자로부터 정수를 입력 받아서 정수의 자리수의 합을 계산하는 프로그램 작성.
#예) 1234를 입력하였다면 1+2+3+4를 계산.
# 나머지 연산자와 나눗셈 연산자를 사용.

x=int(intput("첫번째 숫자를  입력하시오:"))

sum = 0
sum += num % 10
num //= 10
sum += num % 10
num //= 10
sum += num % 10
num //= 10
sum += num % 10
num //= 10

print("자리수의 합:", sum)

 

파이썬 제어문

day1 = 10000  
day2 = 13000 
(day2- day1) == (day1 * 0.3) 
#True

cur_price = 9980 
cur_price >= 5000 and cur_price < 10000 
#True
((day2- day1) == (day1 * 0.3)) or ((day2-day1) > (day1 * 0.292)) 
#True

파이썬 if문

#"위키북스의 현재가가 10,000원 이상이면 10주 매수
wikibooks_cur_price = 11000 
if wikibooks_cur_price >= 10000: 
print("Buy 10") 
#Buy 10 

#파이썬에서는 들여쓰기를 통해 코드 블록을 표현합니다
if wikibooks_cur_price >= 10000: 
   			print("Buy 5") 
    		 print("Buy 5") 
      		 print("Buy 5") 
#Buy 5 
#Buy 5 
#Buy 5 

파이썬 if~else

wikibooks_cur_price = 11000 
 if wikibooks_cur_price >= 10000: 
   print("Buy 10") 
   else: 
    print("Holding") 
#Buy 10

파이썬 if~elif~else 문

현재가가 1,000원 미만이면 호가 가격은 1원, 
그렇지 않고 현재가가 1,000원 이상이고 5,000원 미만이면 호가 가격단위는 5원, 
그렇지 않고 현재가가 5,000원 이상이고 10,000원 미만이면 호가 가격단위는 10원, 
그렇지 않고 현재가가 500,000원 이상이면 호가 가격단위는 1,000원 
price = 7000 
if price < 1000:
 	  bid = 1 
elif price >= 1000 and price < 5000: 
 		bid = 5 
elif price >= 5000 and price < 10000: 
 		bid = 10       
elif price >= 500000: 
  		bid=1000
 
 bid
 #10

 

파이썬 for

#1부터 10까지 출력하기
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]: 
print(i) 
#1
#2
#3
...

list(range(1,10))
#[1, 2, 3, 4, 5, 6, 7, 8, 9] 

for i in range(0, 11): 
		  print(i) 
#1
#2
#3
...
for와 리스트
interest_stocks = ["Naver", "Samsung", "SK Hynix"] 
for company in interest_stocks
  	print("%s: Buy 10" % company)
    
#Naver: Buy 10 
#Samsung: Buy 10 
#SK Hynix: Buy 10 

#문자열이 출력될 위치에 %s로 나타내고 실제로 출력될 문자열은 % 기호 뒤에 변수명을 쓴다
#for와 딕셔너리
interest_stocks = {"Naver":10, "Samsung":5, "SK Hynix":30} 

for company, stock_num in interest_stocks.items(): 
		 print("%s: Buy %s" % (company, stock_num)) 
#SK Hynix: Buy 30 
#Naver: Buy 10 
#Samsung: Buy 5

for company in interest_stocks.keys(): 
			 print("%s: Buy %s" % (company, interest_stocks[company])) 
#SK Hynix: Buy 30 
#Naver: Buy 10 
#Samsung: Buy 5            
#이중 for문 작성
apart2 =[[101,102,103,104],[201,202,203,204],[301,302,303,304],[401,402,403,404]]
for i in range(len(apart2)):
    for j in range(len(apart2)):
        if apart2[i][j] == 203:
            continue
        else:
            print("Newspaper delivery :", apart2[i][j])

 

연습문제

#문제 2-1 다음(Daum)의 주가가 89,000원이고 네이버(Naver)의 주가가 751,000이라고 가정하고,
#어떤 사람이 다음 주식 100주와 네이버 주식 20주를 가지고 있을 때  그 사람이 가지고 있는 주식의 총액을 계산하는 프로그램을 작성하세요.
 daum = 89000
 naver = 751000
 total = daum * 100 + naver * 20
 print(total)

#문제 2-2 문제 2-1에서 구한 주식 총액에서 다음(89000)과 네이버(751000)의 주가가  각각 5%, 10% 하락한 경우에 손실액을 구하는 프로그램을 작성하세요.
daum = 89000
naver = 751000
loss = (daum * 0.05 * 100) + (naver * 0.1 * 20)
print(loss)

#문제 2-3 우리나라는 섭씨 온도를 사용하는 반면 미국과 유럽은 화씨 온도를 주로 사용합니다.
#화씨 온도(F)를 섭씨 온도(C)로 변환할 때는 다음과 같은 공식을 사용합니다.
#이 공식을 사용해 화씨 온도가 50일 때의 섭씨 온도를 계산해 보세요.  C = (F-32)/1.8
f = 50
c = (f-32) / 1.8
print(c)

#화면에 "pizza"를 10번 출력하는 프로그램을 작성하세요.
for pizza in range(10):
    print("pizza")

#문제 2-5 월요일에 네이버의 주가가 100만 원으로 시작해  3일 연속으로 하한가(-30%)를 기록했을 때 수요일의 종가를 계산해 보세요.
mon_start_price = 1000000
mon_end_price = mon_start_price * 0.7
tue_start_price = mon_end_price
tue_end_price = tue_start_price * 0.7
wed_start_price = tue_end_price
wed_end_price = wed_start_price * 0.7
print(wed_end_price+"원") 

#문제 2-6 다음 형식과 같이 이름, 생년월일, 주민등록번호를 출력하는 프로그램을 작성해 보세요.
#이름: 파이썬 생년월일: 2014년 12월 12일 주민등록번호: 20141212-1623210
name = input("이름입력: ")
birth = input("생년월일 입력: ")
idnum = input("주민번호입력: ")

print("이름 :",name)
print("생년월일 :",birth)
print("주민번호 :",idnum)

#문제 2-7 s라는 변수에 'Daum KaKao'라는 문자열이 바인딩돼 있다고 했을 때
#문자열의 슬라이싱 기능과 연결하기를 이용해 s의 값을 'KaKao Daum'으로 변경해 보세요.
s = 'Daum KaKao'
s = s[5:] + ' ' + s[0:4]
print(s)

#문제 2-8 a라는 변수에 'hello world'라는 문자열이 바인딩돼 있다고 했을 때  a의 값을 'hi world'로 변경해 보세요.   
a = 'hi ' + a[6:]
print(a)

#문제 2-9 x 라는 변수에 'abcdef'라는 문자열이 바인딩돼 있다고 했을 때  x 의 값을 'bcdefa'로 변경해 보세요.  
 x = 'abcdef'
 x = x[1:]+x[0]
 print(x)
'''문제 3-1 2015년 9월 초의 네이버 종가는 표 3.2와 같습니다.
09/07 의 종가를 리스트의 첫 번째 항목으로 입력해서
naver_closing_price라는 이름의 리스트를 만들어보세요.

표 3.2 네이버 종가  
날짜 요일 종가
09/11 금 488,500
09/10 목 500,500
09/09 수 501,000
09/08 화 461,500
09/07 월 474,500 '''
 
naver_closing_price = [474500, 461500, 501000, 500500, 488500]

#문제 3-2 문제 3-1 에서 만든 naver_closing_price 를 이용해  해당 주에 종가를 기준으로
#가장 높았던 가격을 출력하세요.
#(힌트: 리스트에서 최댓값을 찾는 함수는 max()이고, 화면에 출력하는 함수는 print()입니다.)
findmax=max(naver_closing_price)
print(findmax)

#문제 3-3 문제 3-1 에서 만든 naver_closing_price 를 이용해
#해당 주에 종가를 기준으로 가장 낮았던 가격을 출력하세요.
#(힌트: 리스트에서 최솟값을 찾는 함수는 min()이고, 화면에 출력하는 함수는 print()입니다.)
findmin=min(naver_closing_price)
print(findmin)

#문제 3-4 문제 3-1 에서 만든 naver_closing_price 를 이용해  해당 주에서 가장 종가가
#높았던 요일과 가장 종가가 낮았던 요일의 가격 차를 화면에 출력하세요.
result=findmax-findmin
 print(result)

 #문제 3-5 문제 3-1 에서 만든 naver_closing_price 를 이용해
 #수요일의 종가를 화면에 출력하세요.
print("수요일 종가: ", naver_closing_price[2])

#문제 3-6 문제 3-1 의 표 3.2를 이용해 날짜를 딕셔너리의 키 값으로,
#종가를 딕셔너리의 값으로 사용해 naver_closing_price2 라는 딕셔너리를 만드세요.
naver_closing_price2={'09/07':474500, '09/08':461500, '09/09':501000, '09/10': 500500, '09/11':488500}

 

#문제 4-1 아래와 같은 패턴의 별(*)을 출력하는 프로그램을 작성해 보세요.
#참고로 print('*', end='')와 같이 print 함수를 사용하면 줄바꿈 없이 화면에 출력할 수 있습니다.
for i in range(5):
    print('*', end='')

'''문제 4-2 아래와 같은 패턴의 별(*)을 출력하는 프로그램을 작성해보세요.
(힌트: 중첩 루프 사용)  
*****
*****
*****
***** '''

for j in range(4):
    print("")
    for i in range(5):
        print('*', end='')

#문제 4-3 아래와 같은 패턴의 별(*)을 출력하는 프로그램을 작성해보세요.
*
**
***
****
*****

for j in range(5):
    print("") 
    for i in range(j+1):
        print('*', end='')

#문제 4-4 아래와 같은 패턴의 별(*)을 출력하는 프로그램을 작성해 보세요.
        *****
        ****
        ***
        **

#문제 4-5 아래와 같은 패턴의 별(*)을 출력하는 프로그램을 작성해 보세요.
x=5
for i in range(1,x+1):
    for j in range(x+1-i):
        print(" " , end="")
    for j in range(2*i-1):
        print("*",end="")
    print()

#문제 4-7 아래와 같은 패턴의 별(*)을 출력하는 프로그램을 작성해 보세요.  
for j in range(5):
    for i in range(j):
        print(' ', end='')
    for i in range(2*(5-j)-1):
        print('*', end='')
    print("")

#문제 4-9 중첩 루프를 이용해 신문 배달을 하는 프로그램을 작성하세요.
#단, 아래에서 arrears 리스트는  신문 구독료가 미납된 세대에 대한 정보를 포함하고 있는데,
#해당 세대에는 신문을 배달하지 않아야 합니다.  
apart = [[101, 102, 103, 104],[201, 202, 203, 204],[301, 302, 303, 304], [401, 402, 403, 404]]
arrears = [101, 203, 301, 404]
for i in apart:
    for j in i:
        if j in arrears:
            continue
        else:
            print("Newspaper delivery :", j)
class Stock:
    market = "kospi"

print(dir())

"""
2개의 언더바로 시작하는 것은 파이썬에서 이미 사용 중인 특별한 것들

이를 제외하고 보면 조금 전에 정의했던 Stock 클래스의 이름이 포함된 것을 확인할 수 있다.

파이썬에서는 클래스가 정의되면 하나의 독립적인 네임스페이스가 생성된다.
그리고 클래스 내에 정의된 변수가 메서드는
그 네임스페이스 안에 파이썬 딕셔너리 타입으로 저장된다.

Stock 클래스는
Stock 이라는 네임스페이스 안에 'market':'kospi'라는 값을 가진 딕셔너리를 포함한다.
"""

# 파이썬 클래스 네임스페이스

"""
Stock 클래스의 네임스페이스를 파이썬 코드로 확인하려면
클래스의 __dict__ 속성을 확인.
"""

print("Stock.__dict__ => ", Stock.__dict__)

"""클래스가 독립적인 네임스페이스를 가지고
클래스 내의 변수나 메서드를 네임스페이스에 저장하고 있으므로
다음과 같이 클래스 내의 변수에 접근할 수 있는 것이다.
"""

print("Stock.market =>", Stock.market)


s1 = Stock() 
s2 = Stock()

print("s1 = Stock() =>", id(s1))
print("s2 = Stock() =>", id(s2))

"""
생성된 s1, s2 인스턴스가 네임스페이스에 있는지 코드를 통해 확인.
dir() 내장함수의 반환값을 확인하면
s1, s2가 Stock과 마찬가지로 존재하는 것을 확인할 수 있다.
"""

print(dir())



"""
s1과 s2인스턴스의 네임스페이스는 현재 비어있는 것을 확인할 수 있다.
"""

print("s1.__dict__ =>", s1.__dict__)
print("s2.__dict__ =>", s2.__dict__)

"""
s1 인스턴스에 market 이라는 변수를 추가한 후, 다시 __dict__ 속성을 확인해보면
'market':'kosdaq' 이라는 키:값 쌍이 추가된 것을 볼 수 있다.
"""

s1.market='kosdaq'
print("s1.__dict__ =>", s1.__dict__)
print("s2.__dict__ =>", s2.__dict__)




# 파이썬 클래스 네임스페이스

"""
Stock 클래스의 네임스페이스를 파이썬 코드로 확인하려면
클래스의 __dict__ 속성을 확인.
"""

print("Stock.__dict__ => ", Stock.__dict__)

"""
클래스가 독립적인 네임스페이스를 가지고
클래스 내의 변수나 메서드를 네임스페이스에 저장하고 있으므로
다음과 같이 클래스 내의 변수에 접근할 수 있는 것이다.
"""

print("Stock.market =>", Stock.market)


s1 = Stock() 
s2 = Stock()

print("s1 = Stock() =>", id(s1))
print("s2 = Stock() =>", id(s2))

"""
생성된 s1, s2 인스턴스가 네임스페이스에 있는지 코드를 통해 확인.
dir() 내장함수의 반환값을 확인하면
s1, s2가 Stock과 마찬가지로 존재하는 것을 확인할 수 있다.
"""

#print(dir())



"""
s1과 s2인스턴스의 네임스페이스는 현재 비어있는 것을 확인할 수 있다.
"""

#print("s1.__dict__ =>", s1.__dict__)
#print("s2.__dict__ =>", s2.__dict__)

"""
s1 인스턴스에 market 이라는 변수를 추가한 후, 다시 __dict__ 속성을 확인해보면
'market':'kosdaq' 이라는 키:값 쌍이 추가된 것을 볼 수 있다.
"""

#s1.market='kosdaq'

#print("s1.__dict__ =>", s1.__dict__)
#print("s2.__dict__ =>", s2.__dict__)

###############

"""
만약 s1.market, s2.market과 같이 인스턴스를 통해 market이라는 값에 접근하면?
"""
#print("s1.market =>", s1.market)
#print("s2.market =>", s2.market)

"""
s2 인스턴스를 통해 변수에 접근하면
파이썬은 먼저 s2 인스턴스의 네임 스페이스에서 해당 변수가 존재하는지 찾는다.


만약 s2의 네임스페이스에 해당 변수가 존재하지 않으면
s2 인스턴스의 클래스 네임스페이스로 가서 다시 변수를 찾게 된다.
"""

"""
 
즉,
    
s2.market 이라는 문장이 실행되면
Stock 클래스의 네임스페이스에 있는
'market':kospi''
키:값 쌀에서 'kospi'라는 문자열을 출력하게 된다.

"""

  
# 클래스 변수와 인스턴스 변수


"""
은행 계좌를 클래스로 표현

Account 클래스
생성자(__init__) : 클래스의 인스턴스가 생성될 때 자동으로 호출되는 함수
소멸자(__del__) : 클래스의 인스턴스가 소멸될 때 자동으로 호출되는 함수

"""
#클래스 상속#
class Parent:
    def can_sing(self):
        print("Sing a song")

father = Parent()
father.can_sing()

class LuckyChild(Parent):
    pass

child1 = LuckyChild()
child1.can_sing()

class UnLuckyChild:
    pass

child2=luckyChild2()
child2.can_sing()
child2.can_sing()

#### 파일 읽기 #####

"""
open('파일경로/파일명.확장자','모드')

경로: '\\' 또는 '/'
파일을 읽기 모드로 열려명 r 을
텍스트 파일인 경우에는 t
"""

f = open("C:\\rStudy\\20200410\\list.TXT","rt", encoding='UTF8')

lines = f.readlines()

print("lines => ", lines)

"""
출력된 후 빈 줄이 하나씩 존재
print()는 문자열을 출력할 때 자동으로 줄바꿈을 하는데
기존에 lines라는 리스트에 있는 문자열에도
줄 바꿈을 의미하는 값인 '\n'가 들어 있기 때문.
"""

for line in lines:
    print(line)

"""
lines 리스트에 있는 원소에서 \n 기호를 제거함으로써 중복으로 줄바꿈되지 않도록
코드를 작성
"""

for line in lines:
    print(line, end="")


################ 파일 쓰기 #############
f = open('sel_list.TXT', 'wt')

f.write('삼전\n')
f.write('하이닉스\n')
f.close()

 

파이참 설치

stock price.xlsx
0.01MB
ml_탐색적 데이터 분석_평가_guide.ipynb
0.02MB
20200323 파이썬 판다스 데이터프레임 병합.html
0.28MB
20200323 파이썬 그룹연산.html
0.34MB
stock valuation.xlsx
0.01MB

 

분석 프로세스
	분석기획
    	데이터 수집	
        	탐색적 분석
            	모델링 및 평가
                	활용
              
 

 

데이터프레임 병합

데이터프레임 병합

  • merge()함수는 sql의join명령과 비슷한 방식으로 어떤 기준에 의해 두 데이터 프레임을 병합한 개념
  • 기준이 되는 열이나 인덱스를 키라고 부름
  • 키가 되는 열이나 인덱스는 반드시 양쪽 데이터프레임에 모두 존재함.
import pandas as pd

#fileth1 = 

# 주식 데이터를 가져와서 데이터프레임 만들기
df1 = pd.read_excel('stock price.xlsx')
df2 = pd.read_excel('stock valuation.xlsx')

print(df1)
print()
print(df2)
print()

 

# 데이터프레임 합치기 - 교집합
#on='None', how ='inner' 옵션이 기본값으로 적용
#on='None' 옵션은 두 대이터프레임에 공통으로 속하는 모든 열의 기준(키)로 병합한다

merge_inner = pd.merge(df1,df2)
print(merge_inner)

 

Q. df1,df2의 합집합을 구한 후 출력하세요.

#데이터프레임 합치기 =  왼쪽 데이터프레임 기준, 키값 분리
#how_left :왼쪽 df의 키열에 속하는 데이터 값 기준으로 병합
#left_on, rigth_on : 좌우 df에 각각 다르게 키를 지정 . id_x id_y구분하여 표시

merge_left = pd.merge(df1,df2, how='left',left_on = 'stock_name', right_on='name')
print(merge_left)

 

# df1에서 불린 인덱싱과 결합하여 원하는 데이터 찾기
price =  df1[df1['price']<50000]
print(price.head())

# df1에서 불린 인덱싱과 결합하여 원하는 데이터 찾기
price =  df1[df1['price']<50000]
print(price.head())

 

 

#df2에서 가격 조건 만족하는 데이터 찾기
value = pd.merge(price, df2)
display(value)

Q. df2에서 per 가 30 보다 크고 pbr이 0.8보다 큰 데이터를 모두 출력하세요

pcon = df2[(df2.per > 30) & (df2.pbr > 0.8)]
print(pcon)

데이터프레임 결합

  • 판다스 join() 메소드는 merge()함수를 기반으로 만들어졌기 때문에 기본 작동 방식이 서로 비슷
  • join() 메소드는 두 데이터프레임의 '행 인덱스'를 기준으로 결합하는 점에서 merge와 차이가 있으나 on=keys 옵션 설정하면 열을 기준으로 결합
import pandas as pd
# 주식 데이터를 가져와서 데이터프레임 만들기
df1 = pd.read_excel('stock price.xlsx', index_col='id')
df2 = pd.read_excel('stock valuation.xlsx', index_col='id')

display(df1.head())
display(df2.head()

# 데이터프레임 결합(join)
# df1의 행 인덱스를 기준으로 결합하는 how='left' 옵션이 기본 적용
df3 = df1.join(df2)
display(df3)

 

그룹 연산

  • 복잡한 데이터를 어떤 기준에 따라 여러 그룹으로 나누어서 관찰 할 수 있으며 이런 방식으로 분할처리하는 것은 그룹연산이라 함
  • 그룹연산은 데이터를 집계, 변환, 필터링을 하는데 효율적이면 판다스 GROUPBY()메소드를 사용한
  • 그룹 객체 만들기(분할)
  • 그룹연산 메소드(적용 - 결합)
import pandas as pd
import seaborn as sns
#titanic 데이터셋에서 age, sex, 등 5개 열을 선택하여 데이터프레임 만들기
titanic = sns.load_dataset('titanic')
df = titanic.loc[:, ['age','sex','class','fare','survived']]

print('승객 수 : ', len(df))
display(df.head())

 

# Class 열을 기준으로 분할( 1개 열을 기준)
grouped = df.groupby(['class'])
print(grouped)
list(grouped)

 

#그룸 객체를 iteration 으로 출력 : head() 메소드로 첫 5행만 출력
for key, group in grouped:
    print('* key:', key)
    print('* number:', len(group))
    print(group.head())

 

# 연산 메소드 적용
average =  grouped.mean()
print(average)

stat =  grouped.max()
stat

 

Q.'Third'그룹만을 선택해서 group3 이름으로 저장하고 통계요약표를 출력하세요.

 

#개별 그룸 선택하기
group3 = grouped.get_group('Third')
print(group3.head())

group3.describe()

 

#class 열 sex열을 기준으로 분할(여러 열을 기준으로 분할)
grouped_two = df.groupby(['class','sex'])

Q. group_two 그룹 객체를 for문을 사용, iteration으로 출력하세요

# grouped_two 그룹 객체를 iteration 으로 출력
for key, group in grouped_two:
    print('* key:',key)
    print('* number:',len(group))
    display(group.head())

 

Q. grouped_two 그룹 객체에 연산 메소드 적용, 각 그룹의 평균값을 구한 후 출력하세요.

# grouped_two 그룹 객체를 연산메소드 적용
average_two =  grouped_two.mean()
print(average_two)
df.corr()

 

적용 - 결합

  • 데이터 집계(egg), 변환(transform), 필터링(filter),객체에 함수 매핑(apply)
import pandas as pd
import seaborn as sns

#titanic 데이터셋에서 age, sex등 5개 열을 선택하여 데이터프레임 만들기
titanic = sns.load_dataset('titanic')
df = titanic.loc[:,['age','sex','class','fare','survived']]

#class 열을 기준으로 분할
grouped = df.groupby(['class'])
#각 그룹에 대한 모든 열의 표준편차를 집계하여 데이터프레임으로 전환
# 각 그룹에 대한 모든 열의 표준편차를 집계하여 데이터프레임으로 변환
std_all = grouped.std() # 표준편차를 그룹으로 저장
display(std_all)
print(type(std_all))

 

(Z = X-μ/σ) Z-score : 평균값에서 표준편차의 몇배 정도 떨어져 있다는 것을 평가하는 수치

  • 분자 : 개별 데이터가 평균으로부터 얼마나 떨어져 있는가
  • Z-score : 그 떨어진 정도가 그 집단의 표준편차의 몇 배 인가

표준 정규분포로 환산했을 경우

  • 표준편차 ±1(1시그마)배의 범위 내에 약 68% 데이터가 들어감
  • 표준편차 ±2(2시그마)배의 범위 내에 약 95% 데이터가 들어감
  • 표준편차 ±3(3시그마)배의 범위 내에 약 99% 데이터가 들어감
# 각 그룹에 대한 fare 열의 표준편차를 집계하여 시리즈로 반환
std_fare = grouped.fare.std()
display(std_fare)
print(type(std_fare))

Q.최대값-최소값을 반환하는 사용자함수를 정의하고 agg() 함수에 인수로 전달하여 그룹별로 집계하여 agg_minmax 이름으로 저장 후 처음 5개 행을 출력하세요.

 

# 그룹 전체에 agg() 메소드 적용 - 사용자 정의 함수를 인수로 전달
def min_max(x): # 최대값-최소값
    return x.max() - x.min()

# 각 그룹의 최대값과 최소값 차이를 계산하여 그룹별로 집계
agg_minmax = grouped.agg(min_max)
print(agg_minmax.head())

# 여러 함수를 각 열에 동일하게 적용하여 집계
agg_all = grouped.agg(['min','max'])
display(agg_all.head())

Q. grouped 에 각 열마다 다른 함수를 적용하여 agg_sep 이름으로 저장하고 출력

('fare'는 'min', 'max', 'age'는 'mean')

 

#각 열마다 다른 함수를 적용하여 집계
agg_sep=grouped.agg({'fare':['min','max'],'age':'mean'})
print(agg_sep.head())

import pandas as pd
import seaborn as sns

#titanic 데이터셋에서 age, sex등 5개 열을 선택하여 데이터프레임 만들기
titanic = sns.load_dataset('titanic')
df = titanic.loc[:,['age','sex','class','fare','survived']]

#class 열을 기준으로 분할
grouped = df.groupby(['class'])

Q. 데이터 개수가 200개 이상인 그룹만을 필터링 하여 데이터 프레임으로 반환하여 grouped_filter이름으로 저장후 처음 5개 행을 출력하시오

 

# 데이터 개수가 200개 이상인 
grouped_filter = grouped.filter(lambda x : len(x) >=200) # 그룹의 길이가 200 이상인 것을 조건으로 filtering 하라는 의미
display(grouped_filter.head())
print(type(grouped_filter))

 

 

Q. age 열의 평균이 30보다 작은 그룹만을 필터링하여 데이터 프레임으로 반환하여 age_fileter 이름으로 저장후 끝에서 5개 행을 출력하시오

 

#age 열의 평균이 30보다 작은 그룹만을 필터링 하여 데이터프레임으로 반환.
age_filter = grouped.filter(lambda x : x.age.mean()<30)
print(age_filter.head())
print()
print(type(age_filter))

Q. Class 각 그룹별 요약 통계정보를 집계 출력하세요

  • 소스 : sns.load_dataset('titanic')
  • 컬럼 선택 : ['age','sex','class','fare','survived']
titanic = sns.load_dataset('titanic')
df = titanic.loc[:,['age','sex','class','fare','survived']]
grouped = df.groupby(['class'])

# 집계 : 각 그룹별 요약 통계정보를 집계
agg_grouped = grouped.apply(lambda x : x.describe())
display(agg_grouped)

 

Z-score를 계산하는 사용자 함수 정의

def z_score(df):
    return (df-df.mean()) / df.std()

age_zscore = grouped.age.apply(z_score)    #기본값 axis=0
print(age_zscore.head())

 

 

from scipy.stats import zmap
import numpy as np
test = np.array([-0.33, -0.31, 0.55, 0.05, 0.93])
ctrl = np.array([[-0.65, 1.09, -1.67, -0.32, 1.26],
               [0.39, 0.68, -0.28, -0.75, -0.72]])
zmap(test,ctrl)

test2 = np.expand_dims(test, axis=0)
test2 = np.concatenate((test2, ctrl))
zmap(test2,ctrl)
# z = (x - x.mean(axis=0)) / x.std(axis=0)

 

 

# 필터링 : age 열의 데이터 평균이 30보다 작은 그룹만을 필터링하여 출력!!!!!!!!
age_filter = grouped.apply(lambda x : x['age'].mean() < 30)
display(age_filter) # First 만 30보다 크기 때문에 False
for x in age_filter.index:
    if age_filter[x]==True:
        age_filter_df = grouped.get_group(x)
        display(age_filter_df.head())

 

import pandas as pd
import seaborn as sns
#titanic 데이터 셋에서 age, sex등 5개 열을 선택하여 데이터프레임 만들기
titanic = sns.load_dataset('titanic')
df = titanic.loc[:,['age','sex','class','fare','survived']]

#class 열을 기준으로 분할
grouped = df.groupby(['class'])
# 그룹 객체에 연산 메서드 적용
gdf = grouped.mean()
print(gdf)
print()
print(type(gdf))

 

Q. class값이 first인 행을 선택하여 출력하시오

 

#Class 값이 first 인 행을 선택하여 출력
print(gdf.loc['First'])

피벗

  • 피벗 데이블을 구성하는 4가지 요소(행 인덱스, 열 인덱스, 데이터 값, 데이터 집계함수)에 적용할 데이터 프레임의 열을 각각 지정하여 함수의 인자로 전달
import pandas as pd
import seaborn as sns

# IPython 디스플레이 설정 변경
pd.set_option('display.max_columns',10)    #출력할 최대 열의 개수
pd.set_option('display.max_colwidth',10)   #출력할 열의 너비
# titanic 데이터셋에서 age, sex 등 5개 열을 선택하여 데이터프레임 만들기
titanic = sns.load_dataset('titanic')
df = titanic.loc[:, ['age','sex','class','fare','survived']]
display(df.head())

 

# 행, 열, 값, 집계에 사용할 열을 1개씩 지정 - 평균집계
pdf1 = pd.pivot_table(df, # 피벗할 데이터프레임
                     index='class', # 행 위치에 들어갈 열
                     columns='sex', # 열 위치에 들어갈 열
                     values='age', # 데이터로 사용할 열
                     aggfunc='mean') # 데이터 집계 함수
print(pdf1.head())

pdf2 = pd.pivot_table(df,                 # 피벗할 데이터프레임
                     index='class',       # 행 위치에 들어갈 열
                     columns='sex',       # 열 위치에 들어갈 열
                     values='survived',        # 데이터로 사용할 열
                     aggfunc=('mean','sum'))      # 데이터 집계 함수

display(pdf2.head())

+ Recent posts