분류 전체보기

Backend의 구성

  • 종류 : 웹서버, DB서버, 웹 프레임 워크(장고, asp 등)가 있다.
  • 기능
    웹서버 : DB에서 받은 정보를 -> 데이터(HTML 등)로 전송해준다
    DB서버 : Mysql, Oracle, MongoDB 등 정보를 저장한다.
    스크립트 엔진 : php, jsp, asp 등 요청을 분석해주는 프로그램
    프레임워크 : 웹/db/스크립트 엔진을 한번에 개발할 수 있게해주는 편리한 도구

    ex> 장고의 아키텍쳐 구조
    image

    ex>웹 프레임워크 장고를이용한 크롤링 사이트의 구조
    image
    구글 compute Engine이라는 클라우드 서비스 위에다가
    리눅스환경인 Ubuntu를 os로 설치하고
    python을 통해 1) 크롤러로 주기적으로 정보를 긁어와 Mysql에 저장하고   +  2) 장고라는 웹 프레임워크로 저장된 db를 띄워준다.
    - 성능의 걱정이 없다면, 웹서버와 db는 필요없다.

기본 단축키

image


주요 기능 단축키

image



실습

  • [ctrl+d] 는 바로 위에있는 셀의 값을 복사해온다.(수식일 경우, 수식통째로 복사)
    imageimage

  • [ ctrl + 세미콜론(;) ]은  오늘의 날자가 상수로 자동 입력된다.
    image

  • [ shift+F3 ] 을 통해, 함수마법사를 불러와서,  범주 > 모두 를 선택해 [TODAY] 함수를 입력해보자.
    imageimageimage
    image
    [ ctrl + ; ]는 상수 인데 비해, [ shift+F3 ] = TODAY()는 매일매일 바뀌는 함수식이 된다.

선택 및 이동의 실습

  • 데이터가 있는 셀을 선택한 상태에서,  [Ctrl+shift + *]를 누르면 뭉쳐져있는 데이터들이 전체선택된다.
    imageimage


    imageimage



    imageimage
    데이터가 없는 곳에서 ctrl+shift+*를 누르면, 아무 반응이 없다.

  • 셀을 선택한 상태에서, [ shift + space ]행을 선택
    imageimage

    셀을 선택한 상태에서, [ ctrl + space ]열을 선택
    imageimage

    이렇게, 행 선택/ 열 선택은 < 행 or 열을 삭제 할 때, 가장 많이 사용된다>
    [ shift + space ] -> [ctrl + (-) ] : 행 삭제
    [ ctrl+ space ] -> [ctrl + (-) ] : 열 삭제


  • [ ctrl+ 방향키 ]는 데이터가 있는 구간에서, 끝으로 이동하기 때문에 < shift와 같이써서, 데이터가 있는 행/열을 선택할 수 있다>
    imageimage

  • [Ctrl + PgUP / PgDn ] 은 시트를 쉽게 이동할 수 있다.
    imageimage


주요 기능 단축키 실습

  • [ Ctrl + shift + L ]은 자동필터를 붙히거나 해제한다. 메뉴에서는 홈 탭> 정렬 및 필터 > 필터 에 위치해있다.
    셀만 선택한 상태에서 해도, 뭉쳐있는 데이터 전체에 대해, 가장 위에 있는 행에다가 역삼각형의 필터를 붙혀준다.
    imageimage

  • [ Ctrl + L ]은 자동필터와 혼동하기 쉬운 [표 만들기] 단축키이다.
    모습을 보면, 자동필터처럼, 첫 행에 필터가 생긴다. 하지만 일반 데이터테이블과 차이점있다.

    imageimage

    자동필터만 달아준 것과 달리, 표 아래의 행에 데이터를 추가하면,  표에 대한 행으로 확장되어 추가된다.
    문제는 자동필터처럼 단축키를 다시 눌러 복구 되는 것은 안된다.
    imageimage

  • [ ctrl + 1]을 누르면 셀 서식 상자가 나타난다.
    image

  • [ ctrl + F3 ]은 이름관리자 단축키이다. 새로 만든 엑셀에는 텅 비어있는게 정상.
    image


빠른 실행도구 모음 사용하기

순서대로 alt + 1,2,3 로 단축키가 지정되므로, 순서를 잘 정해서 넣어야한다.
추가하는 방법은

  1. 좌측상단의 빠른실행도구 모음 옵션키를 눌러 [ 기타명령 ]으로 간다
  2. [사용자 지정]탭에서, 명령 선택을 [모든 명령]으로 바꾼 뒤, 원하는 것을 추가한다.
  3. 추가된 빠른실행도구의 순서를 조정한다.
  4. 다시 옵션키를 눌러 [ 리본메뉴 위에 표시]를 선택해, 보기 편하게 위치를 바꿔준다.
    imageimageimage


빠른실행도구 모음에 유용하게 쓸 수 있는 기능들

  1. 값만 붙여넣기(ctrl + alt+ v)
  2. 병합하고 가운데 맞춤 <->  셀분할  :  특정셀을 묶어서 병합하고 <--> 풀어주는 기능
  3. 글꼴 크기 크게/작게(파포에 있지만 엑셀에는 단축키가 없다)
  4. 시트행 삭제
  5. 시트 삭제, 시트이름 바꾸기
  6. 모든 테두리, 굵은 상자 테두리
  7. 이동옵션
  8. 틀 고정 / 틀고정 취소
  9. 인쇄 미리보기 및 인쇄

image


  • 셀서식이 있는 직위라는 셀을 복사한 다음, 빈 셀에서 [alt+1]을 통해 값 붙여넣기를 실행해보자
    imageimageimage

  • [alt+2]를 통해서 병합하고 가운데 맞춤을 해보자.
    imageimageimage

    원래대로 풀기 위해선 [alt+3]으로 병합풀기를 해보자.
    image

  • [alt+4]로 글자크기를 키워보자 [alt+5]는 글자크기 작게
    image

  • [alt+6]로 행 삽입/ [7]으로 행삭제를 해보자.
    image

  • [alt+8]로 shee3시트를 삭제해보자.(되돌리기 안됨)
    imageimage

  • [alt+9]로 시트이름을 바꿔보자.
    image

  • 10은 단축키가 없다 그다음 단축키인 [alt+09]를 통해 모든테두리를 쳐보자.
    그다음 단축키인 [alt+08]로 굵은 테두리를 쳐보자.
    imageimage

  • 그 다음 빠른실행도구모음인 [ 이동옵션 ]을 클릭해보자.
    자동필터와 관련해서 [화면에 보이는 셀만(y)] 옵션이 자주 쓰일 것이다.
    image

    다음으로 [틀 고정]
    image

    인쇄 미리보기
    image


다른기능을 추가하고 싶다면, 리본메뉴들 중에서 우클릭해서 [빠른실행도구 모음 추가]로 추가해주면 된다.

commit으로 버전을 만들었으나, 코드의 변화만 볼 수 있지, 과거의 프로젝트 상태로 돌아갈 순 없다.

  • 새 파일을 만들어보자. sublimeText를 켜고, 루트폴더인 opentutorials_git에 우클릭으로 [readme.md]파일을 만들어보자.
    image

  • 소스트리(버전관리)로 들어가보면, [ Log/Histroy ]탭에는 uncommitted changes가 감지되었고
    unstaged files파일에, 생성하고 수정한 readme.md파일이 감지되었다. 아이콘이 물음표인 것을 기억하자.
    image

    index.html 파일의 body태그안에 수정하고 소스트리를 보자. unstaged files에 index.html로 걸려있지만
    아이콘이 연필모양이다.
    image

    image
    이 2개 아이콘이 다른 의미는 버전관리(소스트리)에서는 다르게 인식하고 있다는 것인데,
    index.html파일의 [주황색연필]아이콘은 git에 의해 추적되고 있는 파일로서, commit으로 버전을 만들어 저장소에 보관이 가능하다.
    readme.md파일의 [보라색물음표]아이콘은 git에게 파일을 추적하고, 관리하라고 명령하기 전의 파일이다.
    - stage위로 올리고 -> [최초커밋]을 통해, 버전을 만들어야지 [git의 추적]이 시작된다.


  • 새 파일을 stage위에 올린 뒤, commit버튼을 눌러 버전을 만들자.
    이 때, commit은 stage위에 올라와있는 readme.md파일만 commit이 된다.(index.html은 안됨)
    imageimageimage

    마지막 버전확인시, [초록색+]는 이 버전에서 추가한 파일이라는 뜻이다.
    다시 uncomiited changes를 더블클릭해 돌아와보면, unstage에는 index.html만 있다.
    image



  • 이제 변화가 생겨 unstage에 감지된 index.html과 readme.md를 stage에 올리지않고 다시 수정해보자.
    index는 h1으로 큰제목의 태그를 달고, readme는 문자몇개 수정한다.
    그리고 2개를 한꺼번에 stage에 올리고, commit해보자.
    image
    하나의 버전에는 여러개의 파일의 변경사항을 모두 포괄할 수 있다.

  • 다시 2개 파일을 수정한 뒤, 각각 따로 stage에 올려서 commit하여 버전을 만들어보자
    비록 2개 파일의 변동사항이 있지만, 하나의 파일 수정사항에 대한 버전을 만들 수 있다.
    imageimage

    readme.md파일은 여전히 commit되지 않은 체, unstage에 남아있다.
    image

    unstaged와 staged 공간의 차이가 드러난다.
    -unstage : 수정된 모든 파일들의 목록이 표시되는 공간
    -stage : commit시 만들어질 버전에 합류할 파일들만 모아놓은 공간. 중간단계!
    staged라는 중간공간을 통해서 변경사항들 중에서, 필요한 or 완결된 or 연관된 파일들만 모아서 하나의 버전(commit)으로 만들 수 있다!!


[git]에서는 소스트리의
unstaged를 [workingcopy]
staged에 올리는 작업을 [add]
staged를 [index 혹은 staging area]
버전들이 표시되는 타임라인을 [repository]라고 부른다.

즉, working copy에 있는 수정된 파일들을 add해서 index 혹은 staging area에 올려놓고,
commit을 통해 하나의 버전을 만들어 repository에 저장한다.
image


  • 하나의 파일이라도, 중간단계인 staging area에 있는 상태에서, 다시 수정되면 working copy에 감지되어 올라온다.
    image

웹환경을 이해하기 위한 요소

  1. server, client의 관계
  2. http라는 약속을 통해,
  3. 서버<->클라이언트간에 request와 reponse를 통해 대화를 한다.
  4. 웹환경 개발 1 : Frontend(html, css, javascript로 구성된 웹 페이지) 사용자는 이것을 웹브라우저를 통해 본다.
  5. 웹환경 개발 2 : Backend (웹서버, 데이터베이스서버, 웹 프레임워크로 구성) 사용자의 요청에 백엔드서버에서 데이터를 웹브라우저로 던져준다.


서버와 클라이언트

image

데스크탑, 모바일 등은 클라이언트에 속하고 <--> internet <--> server 의 관계에 있다.

클라이언트에서 이 서버에 접속하기 위해서는 서버주소(url)을 통해서 접속하게 되는데, 이 url은 내부적으로 ip : port 형식으로 변환이 된다.
예를 들어서, www.naver.com이라는 url은 내부적으로 192.168.0.1(ip-물리적 서버주소) : 80 (port-서버의 각 서비스에 접근경로)로 구성되어 있다.

서버라는 것은, 특별한 서비스를 제공하는 컴퓨터(PC)이다.
서버의 특별한 서비스의 종류에는 웹서버(80) / 데이터베이스서버(mysql:3306) / DNS서버(1023, 53) / FTP서버(21) / ssh서버(22)/ 메일서버(110,25,143)으로 각 정해진 port가 있다.

컴퓨터에 웹서버를 구성해놓으면, 외부에서 접근할 수 있게 html코드를 던져준다.


HTTP

HyperText Transfer TProtocol(HTTP) - 하이퍼 텍스트 트랜스퍼 프로토콜은 하나의 약속이다.

하나의 서버가 있고, 다양한 브라우저들이 요청(request)를 보내는데,
각 브라우저마다 다른언어로 요청을 보낸다면, 서버는 그 요청을 알아듣지 못할 것이다.
image
이러한 현상을 막기 위한 것이 바로 프로토콜(약속)이다.

우리가 인터넷을 사용한다는 것은, 규정된 약속, 표준, 프로토콜을 지켜 웹서버에 요청한다는 것이다.
HTTP는 서버(웹)와 클라이언트(PC,모바일 등의 웹브라우저)이 대화하기 위한 약속인 것이다.


Request, Response

image

Request : 웹브라우저가 url 등 주소를 통해서 서버로의 요청하는 것이다. 이 request에는 GETPOST가 있다.

  • GET방식 - url을 사용하여 서버에서 정보를 가져오는 방식(게시판 보기)
    image
    위의 주소에서 php?까지는 도메인이며 /  bo_table은 변수 / = use는 GET할 데이터를 요청한다.
    - 위의 주소전체는 GET방식에서 Request를 의미한다.
    - 북마크 기능은 GET방식의 url request를 저장하는 것.

  • POST방식 - 사용자로부터 정보를 받아, 서버에 입력하거나 수정하는 방식(게시판 글쓰기)
    image
    위와 같은 form형식으로, 서버의 정보를 입력 또는 수정하는 POST방식의 request

Response : 서버로부터의 응답으로서, 클라이언트(웹브라우저)에 html코드 등을 넘겨준다.


웹환경 개발1 - Frontend(HTML, css, javascript)

사용자가 웹브라우저를 통해 서버에 request(get방식의 url/post방식의 입력수정)를 할 때, 편리하게 환경을 만들어주는 것

  • HTML(HyperText Markup Language) : 요청이 올 때, 서버가 뿌려주는 html코드는, 단순한 데이터로 생각하자
    image
  • CSS : 데이터(html)를 꾸며주는 것
  • JavaScript : 객체기반의 스크립트 프로그래밍언어로, 어떤 동작(클릭시 변화/팝업 등)을 만들어준다.

    https://www.w3schools.com/js/tryit.asp?filename=tryjs_myfirst
    로 들어가서, 자바스크립트 튜토리얼에서 버튼클릭의 구조를 살펴보자.
    image
    버튼을 누르는 동작을 하게 되면 demo라는 엘리먼트를 가져와서 동작하게 한다. 가져오는 demo의 동작은 시간을 뿌려주는 Date()다.
    image


셀과 시트

image_thumb49


셀의 데이터 다루기

  1. 편집하기 : 입력값을 수식입력줄에 입력후 enter

  2. 삭제하기 : 시트 행삭제, 시트 열삭제, 셀 1개만 삭제 [ shift + 자동채우기 위로 드래그]
    * del키를 눌러서 삭제하는 것은 cell삭제가 아니라, 셀이 가진 데이터를 삭제한다.
    image_thumb47
    그냥 자동채우기 핸들 위로 드래그 : del처럼 셀 데이터만 삭제
    image_thumb53

    shift 누른채 자동채우기 핸들 위로 드래그 : 셀 1개가 삭제, 아래칸이 위로 밀려온다.
    image13_thumb3

    열삭제 : 열 이름에 우클릭후 삭제
    image16_thumb3

    셀 삭제 속 메뉴를 이용해 열 삭제
    image28_thumb3

    행삭제 : 행 숫자에 우클릭 후 삭제
    image22_thumb4
    셀 삭제 속 메뉴를 이용해  행삭제
    image25_thumb3


  3. 추가하기 : 시트 행/열/셀 삽입[ ctrl + (+) ], 시트 행/열/셀 삭제 [ ctrl+ (-) ]
    행 숫자 or 열이름에 우클릭으로 행/열을 삽입할 수 있다.
    단축키로는 ctrl + [+]를 눌러서  셀 삽입/ 행삽입(기존 아래로 한칸 밈) /열삽입(기존 오른족으로 한칸 밈)
    ctrl + [-]를 눌러서 셀 삭제 / 행삭제 / 열삭제

  4. 복사하기 : ctrl+c/v ,   ctrl+ alt + v(선택하여 붙혀넣기) , ctrl+ 셀 경계드래그
    *** 엑셀에서의 복사/ 붙혀넣기는 서식까지 같이 가져간다. 그러므로 붙히기시 항상 붙여넣기옵션이 따라붙는다.
    image31_thumb3

    ctrl+alt+v를 통해 [값만] 붙여넣을 수 있는 옵션을 미리 띄울 수 있다.
    image34_thumb

    image37_thumb3


채우기 핸들

채우기핸들을 드래그해서 내릴 때,
- 숫자의 경우 : 데이터 그대로 복사
- 문자열의 경우 : 일련번호로 채우기
  *ctrl을 누른채로(++) 드래그시 반대로 행동한다. 즉, 숫자의 경우 일련번호로 채움 / 문자열의 경우 데이터 그대로 복사
  (  + : 채우기핸들,  ++ : ctrl누른 채우기핸들 / 미리보기도 같이 나타난다. *함수식으로 된 경우, 일련번호는 안됨)
  cf)shift를 누른채로 드래그시는 다른 행동이 나타난다. shift+채우기 위로 드래그 :  셀 삭제 / 아래로 드래그 : 셀 삽입?
   image43_thumb9

실습


image46_thumb3
위와 같이 순번을 차례대로 채우고 싶다.

먼저 아무것도 안누르고 채우기핸들 드래그시는 그냥 데이터만 복사한다.
image49_thumb3
이 때, 자동채우기 옵션이 따라오는데, 이것을 선택해서 일련번호로 채울 수 있다.
image52_thumb3
image58_thumb5
image61_thumb3

단축키(ctrl)를 누른체 자동채우기(스샷을 보면 +에 +가 하나 더있는 상태)를 아래로 드래그하면, 일련번호로 채워진다.
image68_thumb3
image71_thumb3


문자열의 경우, 아무것도 안누르고 자동채우기핸들 드래그시는 일련번호가 나온다.
image74_thumb3image77_thumb3

**간혹 필요에 의해 순번의 간격이 1이 아닌 경우에는, 셀1개가 아닌, 간격이 주어진 2개의 셀을 선택한 상태에서 자동채우기 핸들을 하면 된다.
  ctrl누를 필요없이 차이만큼 연속된 데이터가 나타난다.

shift를 누른상태에서 자동채우기핸들 아래로 드래그시   아래로내려간 칸만큼 셀이 삽입된다.
image80_thumb3image83_thumb3
빈 셀을 선택한 상태에서 shift + 채우기핸들 아래로 드래그시, 빈셀이 그만큼 삽입된다.
image86_thumb4image89_thumb3
반대로 , shift+채우기핸들 위로 드래그는, 원래 선택된 셀까지는 삭제 되나  //// 그 위로 넘어가면 셀이 삽입되는 현상 ㅠ

시트의 경우 추가하게 되면, 해당 시트의 왼쪽에 추가된다.
image92_thumb
아래 추가버튼을 클릭해서 쉽게 추가할 수도 있다.
image95_thumb3
삭제시 컨트롤을 누른상태에서 여러개 선택하여 한꺼번에 삭제가 가능하다.

시트 복사의 경우, 이동/복사 메뉴를 선택한 상태에서, [복사본 만들기]를 체크해야한다.
image98_thumb

자주 쓰이는 형식들

  1. 관리형 : 데이터가 한 행(record)씩 쌓여가는 것
  2. 집계형 : 관리형 데이터를 집계하여 통계량을 확인하는 데이터
  3. 참조목록형 : 정해진 정보를 참조할 수 있도록 구성한 것( 상품에 대한 단가나 배송료 등 미리 정해진 것)

기본 데이터의 입력

엑셀은 셀(cell)단위로 데이터를 다루고, 들어갈 수 있는 것은 [ 값 혹은 식 ]이 들어간다.

  1. ( 또는 상수) : 숫자 문자열(숫자문자열의 경우 '를 먼저 입력) / 날짜(대쉬-로 연결), 시간(콜론(:)으로 연결) / 조건값
  2. (=으로 시작) : 수식(=4칙 연산 등) / 함수식(=sum(,)함수 등)

값의 입력은 기본적으로 [enter]이나, 여러셀이 블록지정 되어있을 때는, [ctrl +enter]로 일률적으로 입력시킬 수 있다.


실습

  • 기본적으로 숫자는 우측정렬 / 문자열은 좌측정렬이다.
    만약 숫자를 문자열 형식으로 저장하고 싶다면 '를 붙힌상태에서 숫자를 기입하자.
    image

  • 아래처럼 숫자123앞에 '를 넣어서 문자열 형식으로 입력하면, 문자열들처럼 좌측정렬이 됨과 동시에, 초록마커가 생긴다
    image

  • 분수를 입력할 때에는,  1/2을 입력하면 (/)가 날짜로 인식된다.
    이 때, 대분수처럼 생각하면서 1/2을 0과 1/2로 생각하여 [ 0 1/2]을 입력해보자.
    image
    image
    image
    image


  • 날짜를 입력할 땐 대쉬를 사용한다. 만약 3월 14일을 의미하는 03-14를 입력하면 년도도 자동으로 입력된다.
    image
    image

  • 시간 입력시 콜론:을 이용한다. 시간을 입력하면, 수식입력란에 자동으로 AM PM이 붙게 된다
    image
    image

  • 수식( =사칙연산)을 입력해 나온 결과값과 일반 숫자값과 비교하기 위해서는 [ ctrl + grave(`)키 ] 를 눌러서 확인할 수 있다.
    수식을 입력했다면, 수식입력란에 해당 수식이 나온다.
    image
    image
    image


  • 함수식(=sum)을 입력할 때도, 기본 숫자데이터와 비교하기 위해선 [ctrl+ grave]를 이용한다.
    수식입력란에 보면, 함수식이 나와있다.
    image
    image
    image

1. [윈도우키 + R]로 실행창을 켜서 [  netplwiz  ]를 입력한다.


2. 나타나는 사용자계정 설정창에, 암호입력하여 로그인하는 체크박스를 [체크해제]후 적용을 클릭하자


3. 이제 암호없이 자동로그인을 하기 위해, 비밀번호 인증하라고 나온다. 기존에 사용하던 비밀번호를 입력해서 인증해주자


4. 계정의 암호를 제거했다면, 이제 윈도우설정 > 사용자정보 > 계정으로 가서
  마이크로소프트 로그인을 -> 로컬 계정으로 로그인하도록 하자.

  비번을 제거한 로컬계정으로 로그인하게 되어, 비밀번호도 제거했으니 자동로그인 될 것이다.


5. 제거 확인은 win키 + L 을 눌려서 확인하자

Git을 이해하기 위하여, 예제부터 이해하기


Git 저장소(프로젝트의 메인폴더) 만들기

  • 언어를 영어로 바꿔주자.
    소스트리를 켜고,  도구 > 옵션 > 언어를 english로 바꾸자. 참고할 대부분의 자료들은 영어로 되어있기 때문이다.
    재실행해야지 바뀌어 진다.
    image

    [ create]버튼을 눌러서 repository( 저장소 )를 만든다. 한 프로젝트의 디렉토리(폴더)이다. 그것을 git에서는 저장소라 부른다.
    타입은 git으로 고정해두고, destination path 프로젝트의 디렉토리가 어디에 생성할 것인지 지정하는 것이다.
    나는 데스크톱의 cho폴더(C:\Users\cho)에서 폴더에 [ opentutorials_git] 라는 저장소(프로젝트의 폴더)를 만들 것이다.
    image

    소스트리에 프로젝트 폴더(저장소)가 생성된 것을 확인할 수 있다(탭의 이름)
    image


소스트리로 버전관리 해보기

  • SublimeText의 루트폴더를 추가해주자.
    project > Add folder to Projects > 소스트리에서 만든 저장소(프로젝트의 최상위폴더)를 선택
    image

  • 저장소에 수동으로 새로운 파일을 추가해보자.
    저장소(프로젝트 폴더)에서 우클릭으로 생성해도 된다. 여기서는 서브라임텍스트를 이용해서, 지정한 root_폴더에서 파일(index.html)을 생성해보자. 아래 그림과 같이 소스트리에서 해당파일이 [unstaged files ]의 목록에 자동으로 생성된다.
    image
    즉, 저장소(프로젝트 폴더)에서 일어나는 일(파일생성, 삭제 등)을 계속 주시하고 있다가, 변화를 알아채고 바로 띄워준다.

  • 버전관리를 해보자.
    보라색의 물음표의 파일 우측상단에 [Stage All] 이나 [Stage Selected]를 클릭해보자. 아래그림과 같이  [ Staged files]로 올라가면서 초록색 플러스아이콘으로 바뀐 것을 확인할 수 있다.
    image

    이제 초록색 플러스아이콘인 Staged된 index.html을 선택한 뒤, 좌측상단의 Commit 버튼을 눌러보자.
    커밋을 적는 란이 생긴다.  파일을 생성했다고  커밋을 남겨보자.
    커밋이란 ? 버전하나를 만드는 행위이다. ( 만약 커밋사용자의 정보가 없다면 Tools 에 들어가 지정해주자)
    커밋 후 확인은 하단의 [Files Status]탭을 [Log /History]탭으로 바꾸어주면 된다. (혹은  [ BRANCHES ] > master 에 들어가면 확인할 수 있다.)
    image
    commit을 통해서 버전을 최초로 만들었다.

  • 새로운 버전을 추가하기 위해서 파일을 수정해보자.
    index.html파일을 수정했더니 소스트리에 [Uncommiteed changes]가 관찰되었다.
    image
    image

    commit을 통해 새로운 버전을 만들었는데, uncomiited changes는 아직 버전을 만들지 않은 변화가 있다는 뜻이다.
    버전을 만드는 방법은 [Unstaged files] 를 Stage 하여 —>  [ Staged files]에 올린 뒤 –> [commit버튼]을 눌러 버전 정보를 작성해주는 것이다. 방금 한 작업인 html태그 추가를  적어주면서 commit을 눌러 버전을 만들어주자.
    imageimageimage

    아래그림 처럼, BRANCHES에서 새로운 버전(commit)이 생성된 것을 확인할 수 있다.
    커밋 후 확인은 하단의 [Files Status]탭을 [Log /History]탭으로 바꾸어주면 된다.
    image

  • 버전들을 탐색해보자.
    위에서 만든 commit들(버전들)을 확인해보자. 처음에는 내용이 없는 html파일을 생성했으므로, 
    우측에는 아래와 같이 텅빈 화면으로 나타난다.
    image

    2번째 버전에서는 html을 추가한 것에 대해 [ 녹색으로 이전버전에 비해 추가된 코드를 표시 ]해 주고 있다.
    image

    3번째 버전에서는 body태그를 추가하였다. 녹색으로 추가된 부분이 표시 될 것이다.
    image


파일의 변형 –> commit으로 버전으로 만듬 –> 버전 탐색의 과정이었다.

소스트리 : 명령어 기반으로 사용하기 쉽지않은 git을, 그래픽 환경에서 쓸 수 있게 해주는 프로그램.


git 설치

  • 구글에서 git download를 검색하여, 공식사이트에서 다운 받고,  default설정으로 설치한다.
    image

  • 설치하고 난 뒤, 시작메뉴에 보면 Git Bash 아이콘이 생긴다. 클릭해서 열어보면, 유닉스/리눅스 환경과 비슷한 환경에서 윈도우를 제어할 수 있다. [ git ]이라고 쳐서 명령어들이 출력되면 정상적으로 설치 된 것이다.
    image
    image


sourceTree 설치하기

  • 구글에서 sourcetree download를 검색해서 default로 설치한다.
    설치과정에서 Atlassian에 가입을 했고, 구글아이디를 이용하였다.
    image
    image

    동시에 비트버킷에도 가입하였다. 위에서 사용한 Atlassian계정으로 연결하고 비트버켓 닉네임은 nittaku로 하였다.
    image
    image

1. 버전 관리란?

2018. 3. 13. 21:08

버전 관리 시스템(Version Control System)

버전 : 의미있는 변화들 = 기능개선 및 버그 수정
버전관리 시스템 : 이러한 변화들을 관리하는 방법론 ( 이전버전으로 바로 돌아갈 수 있다 !)


유사 버전관리 시스템

제품설명서 :
- 제품설명서1을 복사해놓고 수정하여 제품설명서2를 만든다. 마음에 안들면 되돌릴 수 있다.
image

위키피디아 : 집단지성으로 전 세계사람들이 협업하여 백과사전을 작성
- [ 역사보기 ] 탭의 하나하나의 행이 하나의 버전이라 볼 수 있다. 악의적인 편집에 대해 예전버전으로 되돌릴 수 있다.

DropBox : 구글드라이브나 네이버N드라이브처럼, 파일을 올릴 수 있는 클라우드서버 제품
- subversion과 같은 버전관리시스템의 장점만 모아서 일반인들도 사용할 수 있는 제품이다.
- More > Previous versions를 통해 버전 관리를 확인할 수 있고 –> restore버튼으로 예전버전으로 되돌릴 수 있다.
image
image


git을 못쓰겠다면, dropbox구글드라이브를 반드시 사용할 것!

groupby() )
(1) 기준열로 그룹화한 결과물로 - > 그룹화기준 딕셔너리를 만들어 -> 키값대입으로 1개의 그룹화결과물을 구하고
(2) 그룹화결과물마다, 통계함수가 아닌 , 따로 적용할 어떠한 def 함수가 존재할 때,
(3) 그룹화결과물 .apply(def함수) 로 계산한다.

pivot_table ) 
(1) 추출열 / index로 가져올 기준열1/ columns로 가져올 기준열2/ 통계함수 가 명확하고 한방에 그룹화할 때

데이터분석 해석)
(1) 각 ~별 => 기준열
(2) ~의 합/평균/비중 계산하기  => 기준열
(2) A+B열 중 A만 or B만 언급 => 기준열로 간주하고, 나중에 열인덱싱 ( ex> 남아의 출생횟수 ==> 성별을 기준열로 하고 남자열만 인덱싱 )
(3) 전체A 중 B를 가진 => A열을 기준열로 간주하고, 나중에 B열 인덱싱
(4) 특정 ~를 가진 => 그룹화후 인덱싱 & 만약 행인덱싱이 필요하다면 sum()함수의 총합이 달라지므로, 미리 비중계산후 행인덱싱

상위 TOP100 / 상위 ~% 구하기 )
(1) groupby()로 그룹화기준 딕셔너리를 통한 1개 그룹화결과물로 착안하여 , sort_values로 내림차순 + iloc로 정수 행인덱싱 [ :100]의 사용자함수 정의
(2) groupby().apply( 사용자정의함수 ) 적용 : 강제로 그룹화시켰야만, 상위100개가 노출됨
(3) pivot_table로 손쉽게 그룹화시켜서 각 그룹당 상위100 확인



필요 라이브러리 import

%matplotlib nbagg
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


파일 읽기 + 헤더를 새로운 것으로 지정해주기(기존 csv데이터와 다른이름의 헤더 주기)

pd.read_csv를 이용하여, (notebook작성위치 기준)파일을 불러오면서, 헤더옵션을 주어 새로운 헤더를 지정해주자.(갯수는 동일하게)

names = pd.read_csv("data/us-baby-names/NationalNames.csv", sep="," ,
                     header=0, names=["id", "name", "year", "sex", "births"])

image


  • 데이터 확인하기 ( head()와, shape 관찰하기)


데이터 분석1 – 각 연도별, 성별(남/여)의 총 출생횟수 계산하기 –> 시각화  by 피벗테이블

각 연도별-> 기준열1 “year”
성별(남/여)의 –> 기준열2 “sex”
총 출생횟수 –> 추출열 + sum()통계함수 “births” / “sum

  • groupby()를 이용한다면, names.groupby( [ 기준열1, 기준열2 ] ) [ 추출열 ] .sum()이겠지만
    피벗테이블을 이용해서 데이터그룹화해보자.
    totol_births = names.pivot_table(values="births", index="year", columns="sex", aggfunc=sum)
    totol_births.head()
    image


  • line plot을 그려보자.( index-> x축 / values의 범위 –> y축 /  columns –> 선의 갯수 = 범례의 갯수)
    ax = total_births.plot()
    image
  • plot의 제목을 붙혀주자.
    ax.set_title("Total births by year and sex")
    image



데이터 분석2 – 각 (연도, 성별 기준의) 그룹내에서,
                  각 이름(행)의 출생횟수가 전체에서 차지하는 비중(%)을 나타내는 열 추가하기 by groubpy()함수

피벗테이블을 사용하지 않고, groupby()함수를 사용해서 계산을 해보자.

앞서 22강에서는, 기준열에 대한 데이터그룹화 직후의 결과물( 추출열 적용x, 통계함수적용x)을 보기 위해서는
데이터그룹화 결과물에 list()를 입혀서  [ (기준열성분a, 기준열에a를 가진 dataFrame ) ,  ( b : DataFrameB) , ( c : dfC )] 형태로 나누어지고,
그 list에다가 dict()를 입혀서 { a : a포함 df , b : b포함 df, c: c포함df }의 딕셔너리 형태로 가져와서 볼 수 있었다.
그리고 그 딕셔너리에 [키인덱싱]을 통해서, 해당 키성분을 가진 df를 추출할 수 있었다.


여기서는 2개의 기준열을 가지고 groupby하여 딕셔너리 형태로 뽑아보자. 키가 2개가 될 것이고, 키 2개 성분을 가지는 df가 밸류가 될 것이다.

  • year와 sex열을 기준열로 하여,  groupby함수의 그룹화결과물을 딕셔너리형태로 담아보자.
    이 때, 딕셔너리이므로, head()가 아니라 keys()를 통해,   기준열2개-> 2개의 key ( year, sex)형태의 키들을 살펴볼 수 있다.
    grouped_names_dict = dict(  list(  names.groupby( ["year", "sex"])  )  )
    grouped_names_dict.keys()

    image

  • 기준열 2개로 groupby()한 그룹화결과물을 ---> 딕셔너리로 저장했다면, 보고싶은 2개의 키를
    딕셔너리에 [키 인덱싱]하는데, (key1, key2 ) 순으로 넣어주면 해당 dataFrame을 볼 수 있다.
    예를 들어, 2011년도 남자(M)아이에 해당하는 names데이터프레임만 보고 싶다면,
    해당 딕셔너리의 (2011, ‘M’) 키를 가진 –> 밸류(df)만 가져오면 된다.
    추출열 없이, 전체 names중에 기준을 가지는 행들의 모든 열이 나타나기 때문에,  아이의 name과 출생횟수도 바로 볼 수 있다.

    grouped_sample = grouped_names_dict[ (2011, "M" )]
    grouped_sample.head(10)
    image
    my) dataFrame을 groupby()를 통해서, 딕셔너리형태로 그룹화결과물만 가지고 있다면,
    names라는 df 중, 딕셔너리에서 키값만 인덱싱하면, 원하는 기준으로 자료를 뽑아낼 수 있다.
    굳이 통계함수를 적용안시켜도되며 & 기준열중 원하는 값만을 가지는 것을 바로 뽑아낼 수 있다.
    추출열 없이, 전체 names중에 기준을 가지는 행들의 모든 열이 나타나기 때문에, 
    다른 열의 정보인 아이의 name과 출생횟수도 바로 볼 수 있다.
    (나는 이 딕셔너리를 키값인덱싱으로 개별 결과물을 알 수 있는 그룹화 기준 딕셔너리 라고 부를 것이다.
    이 그룹화 기준 딕셔너리에 키값으로 인덱싱하여 –> 각각의 그룹화된 df을 얻을 것이다)

    참고로,, 그룹화기준 딕셔너리 생성 –> 키값인덱싱으로 그룹화된 결과물 1개를 살펴보기 위함 일뿐?
    결과물 1개를 봐야지.. 집계함수를 정의할 수 있어서?

  • 이제 1개의 그룹화결과물 df에 대해 출생비율을 계산하여 새로운열로 추가해줄 사용자 정의 함수를 정의한다.
    기준열에 2개에 대한 기준값을 –> 그룹화 기준 딕셔너리에 키값 2개( year, ‘M’ or ‘F’) 를 인덱싱하여하여 얻을 수 있는 DataFrame을 인자로 받아
    해당 추출된 df의 births열을 따로 빼낸 뒤 –>
    [ births열 변수  / births열 변수 .sum()총합 ]의 비율계산하여 –>
    새로운 “prop”열을 df에 추가하는 함수다.

    def add_prop(agg_df):
         agg_births = agg_df["births"]
         agg_df["prop"] = agg_births / agg_births.sum()
         return agg_df
    image


  • 이제 사용자 정의 집계함수를 적용시키려면, 그룹화기준 딕셔너리에 키값을 입력해서 얻는 1개의 그룹화 결과물이 아니라,
    groubpy로 그룹화시킨 것에 추출열이 없는 전체 dataFrame에 .apply()를 이용해서 사용자 정의함수를 적용한다.

    names_with_prop = names.groupby( ["year","sex"]).apply(add_prop)
    names_with_prop.head()
    image
    pivot_table기준열을 index / columns로 가져와서 보기가 편해던 반면에,
    groupby는 기본적으로, 열로 유지된 상태의 데이터라 보기 쉽지 않다.
    하지만, [ 그룹화기준딕셔너리로 1개의 결과물 본 뒤-> 각 그룹화 결과물을 전체로 한 비율을 계산해줄 함수정의 –> 함수 적용으로 새로운 열로 추가 ]가 가능하다.
    ( my) 각 그룹화결과물을 전체로 하였으니,, 각 비율은 그룹화했을 때, 합이 1이다. 전체데이터에서 prop열을 보면, 합이 1이 아니고, 섞여있다)


데이터 분석3 – 각 연도, 성별 그룹내에서,  출생횟수(births) 기준 TOP1000 이름 추출하기 by groupby()

상위 TOP 1000 등을 계산하려면, 데이터분석2에서 계산한 prop(비율)열을 먼저 계산되어 있어야한다.?????
위에서 return받은 데이터 names_with_prop을 이용하자.
image

  • 각 그룹화결과물을 전체로한 비율을 열로 추가한 데이터 names_with_prop을 가지고, 또 [ 그룹화기준 딕셔너리 ]를 만들자.
    < 결국에는 groupby로 그룹화한 데이터를 다룰 것이다. 그 전에  딕[키값인데싱]으로 1개의 결과물을 미리 볼 수 있다 >
    grouped_names_with_prop_dict = dict( list( names_with_prop.groupby(["year", "sex"]) ) )

    하나의 샘플을 미리 보자.
    grouped_sample = grouped_names_with_prop_dict[(2011, "M")]
    grouped_sample.head()
    image


  • 이제 우리는, 그룹화기준 딕셔너리를 통해 1개의 그룹 결과물을 보고서 –> 각 그룹 별 상위 1000개의 데이터를 추출해야한다.
    1개의 그룹화 결과물에 대해서births열로 내림차순으로 정렬하고,  .iloc[ :10]을 통해,  10번째 행까지만 뽑아보자!

    grouped_sample.sort_values(by="births", ascending = False).iloc[:10]
    image
    (기존의 데이터가 원래 내림차순으로 정렬되어있던 데이터라서,, 동일한 것처럼 보인다)

  • 위의 1개 결과물에 대한 것에 착안을 해서 ---> 그룹화기준딕셔너리를 만들 때 쓴, 전체 데이터 names_with_prop에 대해서
    1개의 결과물에 적용한 과정을 그대로의 수행하는 사용자 정의함수를 정의하자.
    (1) births열 내림차순정렬 + 1000번째 행까지만 인덱싱하여—> top1000_df 변수에 저장
    (2) top1000_df변수를 return함

    def get_top1000(agg_df) :
         top1000_df = agg_df.sort_values(by="births", ascending = False ).iloc[:1000]
         return top1000_df
    image


  • 정의한 함수를 groupby()한 그룹화결과물에 (통계함수대신) .apply()로 적용한다.
    각 연도, 성별을 기준으로 그룹화된 각 DataFrame에서 births 상위 1000명개씩 끊어서 name행들이 추출될 것이다.

    top1000_names = names_with_prop.groupby(["year", "sex"]).apply(get_top1000)
    top1000_names.head()
    image
    다 보이진 않지만, 1880년도, Female 아이들 중 상위1000개 나타나고 그다음, Male의 상위1000개만 나타날 것이다.


  • 확인을 위해, 전체 데이터인 names_with_prop 의 행인덱싱.loc[]의  조건으로 ( year열 == 2011) & ( sex열 == “M” )을 주어,
    2011년에 태어난 M인 아이들의 수
    shape를 통해 총 몇 행이 있는지 확인하고
    각 그룹결과물 별 top1000데이터 top1000_names의 행인덱싱에 조건을 주어 shape를 확인해보자.
    (.loc[ 인덱스명 ,  칼럼명 ]으로 인덱싱하는것이 보통이나, 행인덱싱란에  df[“특정열”] ==특정성분 형태로 조건을 넣을 수도 있다)
    names_with_prop.loc[ (names_with_prop["year"] == 2011) & ( names_with_prop["sex"] == "M")].shape

    top1000_names.loc[ (top1000_names["year"] == 2011) & (top1000_names["sex"] == "M" )].shape

    image
    사용자정의함수를 이용해서, 각 그룹화결과물에 대해, births열을 내림차순후, 상위1000개만 뽑은 것을 확인할 수 있다.



(데이터분석3에 이은 것)

데이터분석 4 – 각 연도에 따른, 성별의 전체 출생횟수 대비 TOP 1000이름들의 출생횟수 비중의 합 산출하기 by 피벗테이블

각 연도별 각 성별의, 전체 출생횟수 대비, 상위 top1000개의 출생횟수 비중이, 어떻게 변화되었는지 알아보자.
이전에, 각 (연도, 성별)별 그룹의 전체 출생횟수 대비, 각 이름들의 출생횟수 비중을 의미하는 “prop”열을 만들어놨었다.
이 것을 이용해 pivot_table을 만들면 굉장히 편할 것이다.

먼저 top1000_names.head() 를 통해 데이터를 다시한번 살펴보자.  각 연도별/성별별 그룹마다 상위1000개의 행들만 나타나있다.
image


  • 먼저, top1000_names에서, pivot_table을 이용하여, 
    prop열을 추출열로 하고,
    year열을 index로 가져오는 기준열1
    sex열을 columns로 가져오는 기준열2
    통계함수는 sum을 적용한다.
    연도별 / 성별별 / 비중들의 합이 되므로, 이전에 각 그룹별로 전체 비중을 계산했으니, 각각 1으로 찍혀야하나,
    상위 출생횟수 1000개씩 골라냈으므로, 1이되거나 1이 좀 못될 것이다.
    즉, [ 각 연도/성별별 그룹마다 전체대비 비중계산prop 추가 –> 각 그룹별 TOP 1000개씩 인덱싱 –>
          각 연도/성별별 그룹의 상위1000개, prop열 추출 = 자동으로 전체대비 상위1000개차지하는 비중의 합을 계산 ]
    빨간색은 데이터분석2번 –> 파란색은 데이터분석3번 –> 보라색은 지금 한 것이다.

    top1000_props = top1000_names.pivot_table(values="prop", index="year", columns="sex", aggfunc="sum")
    top1000_props.head(10)
    image

  • 이제 각 연도별/성별별/ 전체출생횟수대비, 상위1000개의 출생횟수비중의합을 라인플롯으로 그려보고 수정해주자.

    ax = top1000_props.plot() 을 통해 그리고
    ax.set_xticks( range(1880, 2020, 10))    ---------> 파이썬의 range정수 리스트 생성
    ax.set_yticks( np.arange(0, 1.3, 0.1)) 을 통해서,  ---> 넘파이의 np.arangearray리스트로 실수/ 행렬까지 가능
    x축은 1880년부터 2020년 전까지, 10의 간격으로 / y축은 0부터 1.3전까지 0.1간격으로 주자.

    image
    간단히 해석해보면)
    1880년도 같은 경우, 비중이 1이다.  1880년에 태어난 아이들의 이름은,, 거의 상위1000개 아름안에 다 들어간다.
    그러나 시간이 흐를 수록, 상위1000개의 이름의 비중이 줄어든다.
    즉, 시간이 지남에 따라 인기는 이름의 비중은 내려가고, 이름에 개성이 생기고 있다.



데이터 분석 5 – 각 연도에 따른, 특정 이름들의 , 출생횟수 변화 추이 분석하기 by 피벗테이블

top1000개 중 몇개의 이름들만 대상으로 하여, 연도에 따른 출생횟수 변화추이를 분석하자.
기존의 top1000_names를 그대로 이용할 것이다. (각 연도별/성별별/ 탑1000개의 이름데이터들이 나와있다)
top1000_names.head()
image
피벗테이블을 활용할 것이므로, 해석을 하자면
각 연도에 따른 –> 기준열1 (index)
특정 이름들의 –> 기준열2(columns)  + 특정이름이라는 것은,,  비 인기이름들은 연도별로,, 출생횟수가 아예 없는 것도 있으니 NaN으로 뜬다
                                                                           그것들 베재하고 인기있는 것들만 살펴보자.
출생횟수 –> 추출열(values)
변화 –> 통계함수(aggfunc)는 sum으로해서,, 이름별,, 출생횟수의 합으로 변화를 살펴야한다

  • top_names_births = top1000_names.pivot_table(values="births", index="year", columns="name", aggfunc="sum")
    top_names_births.head()
    image
    이름이 7031가지나 되고 그것이 columns으로 나타난다


  • 위의 7031가지 이름들 중에, 열인덱싱으로, 특별한 이름 4개만 가져와보자.
    top_names_births_subset = top_names_births[ ["John", "Harry", "Mary", "Marilyn"] ]
    top_names_births_subset.head()
    image


  • top_names_births_subset 을 가지고 라인플롯을 그려보자.
    이 때, plot()의 인자로, subplots =True를 주게 되면, 하나의 ax(axes좌표평면)에 각 칼럼들=각 라인들이 subplot안에 독립되어 그려진다.

    ax = top_names_births_subset.plot( subplots = True , fontsize = 8)
    image
    간단한 해석 )  나머지이름들은 20세기 전체적으로 인기가 있었는데 반면, Marilyn은 20세기 중반에 반짝 인기 있다가 사라졌다.



데이터분석 6 – 남아의 이름 마지막글자에 따른 출생횟수가, 연도에 따라, 어떻게 변화하였는지 분석하기 by 람다/피벗테이블

저명한 연구자에 따르면, 지난 100년동안 남아아이름의 마지막글자의 분포가 급격하게 변화하였다고 알려왔다. 그것을 조사해보자.
처음 사용한 데이터 names에다가,  람다함수를 정의한 뒤, 적용해볼 것이다.
image

  • 먼저 람다함수를 하나 정의해줄 것이다.
    어떤 시리즈(열1개)에 대하여, 각 성분(x)의 마지막 글자( x[-1])를 추출하여 반환하는 함수다.
    get_last_letter = lambda x: x[-1]

  • names의 name열 에다가 .apply()를 통해 람다함수를 적용하게 되면, 각 이름의 마지막 글자만 추출된 열(시리즈)이 생성될 것이다.

    names["name"].apply(get_last_letter).head()
    image

    이것을 names의 새로운 열로 추가해주자.
    names["last_letters"]= names["name"].apply(get_last_letter)
    names.head()
    image


  • (람다함수로 마지막글자 추출후반환 정의 –> name열에 적용-> 새로운 열로 추가)의 과정을 거쳐
    이제 name의 마지막글자를 새로운 열로 추가한 names데이터를 가지고  피벗테이블사용할 것이다.
    < groupby는 그룹화기준 딕셔너리를 통해, 1개의 그룹화결과물을 보고, 사용자정의 def함수를 적용시킬 때 사용했고
      pivot_table은 2개의 기준열을 index, columns로 가져오면서, 통계함수를 빠르게 적용시킬 때 사용했었다.>

    남아이름 마지막글자에 따른 출생횟수가, 연도에 따라, 어떻게 변화(총합)하였는지 분석 이므로
    추출열 = 출생횟수 / index 기준열1 = 마지막글자열 /  columns 기준열2 = 남아(성별) - 기준열3 = 연도(계층적컬럼)/ 통계함수 = sum

    names.pivot_table(values = "births", index ="last_letters", columns = ["sex", "year"] , aggfunc = "sum")
    image


  • 남아에 대한 정보만 필요하므로 크게 잘라내기 위해, 성별을 연도보다 컬럼의 상위계층으로 두었었다.
    (나중에 남자 / 여자 따로 plot으로 나타낼 것이다. )
    위 피벗테이블을 새로운 변수 last_letters_table에 먼저 담아둔다.
    last_letters_table = names.pivot_table(values = "births", index ="last_letters", columns = ["sex", "year"] , aggfunc = "sum")

  • 연도가 너무 많으므로 df.reindex()함수를 사용해서 특정컬럼만 골라낼 수 있다. 이 때 계층적 컬럼이므로 level인자도 같이주어야한다
    (13강에서는 reindex(columns = [  , , ]를 통해, 기존 있던 칼럼들은 다 기입하되, 순서만 다르게 주어서, 칼럼 순서바꾸기로 쓰였었다.)

    three_years_subtable = last_letters_table.reindex(columns=[1910, 1960, 2010] , level ="year")
    three_years_subtable
    image


  • 이 때, three_years_subtable에 .sum()함수를 적용하면 기본적으로 가장 하위층의 각 열마다 총합을 구해준다.
    즉, 성별에 따라 / 각 연도별 / 마지막글자 a부터~z까지의 총 출생횟수의 합이 나온다.
    이것을 구하는 이유는, a~z까지 전체 출생횟수에 대한 각 a, b, c 들의 비중을 구하기 위해서다.
    three_years_subtable.sum()
    image

    이제 전체에 대한 비중을 구하는 식인 three_years_subtable / three_years_subtable.sum()를 계산하여
     비중 dataframe을 따로 변수에 저장한다.

    three_years_letters_prop = three_years_subtable / three_years_subtable.sum()
    three_years_letters_prop.head()
    image
    결과적으로 얻은 결과물은,
    각 성별 / 연도에 따른, 마지막글자를 a~z로 가진 아이의 출생횟수의 상대적 비중을 산출한 것이다.


  • 이번에는 ax = df.plot()으로 바로 안그리고, figure를 생성하면서 plot을 그려보자.
    figure와 axes를 만들고, figure안에 subplot을  2x1의 2개로 만든다.

    fig, axes = plt.subplots( 2, 1)
    image
    이 때, 한 fig에 대해서 subplot이 2개면 –> axes1차원 리스트의 형태로 2개가 반환된다. axes[0]과 axes[1]

  • 첫번 째 axes인  axes[0]을 plot()함수의 ax인자로 주어 그리되,
    열인덱싱으로 M(남아)만 / 바플롯 / 첫번째 axes / title도 동시에 준다.
    (계층적 인덱스라도, 가장 상위계층인 M/ F열은 바로 인덱싱하면된다 ㅋ)

    three_years_letters_prop["M"].plot(kind="bar", ax=axes[0], title="Male")
    image


    F열에 대해서도 똑같이 그리되, 2번째 좌표평면에다가 / title을 바꿔서 그려준다.

    three_years_letters_prop["F"].plot(kind="bar", ax=axes[1], title="Female")
    image

    글자가 겹쳐보일 때는, plt.tight_layout() 를 적용해준다.
    image
    간단히 분석)
    여아(Female)의 경우 – 마지막글자가 e인 아이가 태어난 횟수는 시간이 50년씩 흐름에 따라 감소를 했다.
    남아의 경우에는 – 마지막 글자가 n인 아이가 50년씩 지나면서 거의 2배이상 증가했다.


데이터분석 7 – 특정 몇개의 글자에 대해, 연도에 따른 ,남아 출생횟수의 비중의 시간적변화를 분석해보자.

현재까지 구해진 last_letters_table 데이터를 이용할 것이다.

last_letters_table.head()
image


  • three_years_subtable에 적용했던 것처럼,
    데이터의 각 열방향의 총합( df.sum() )을 전체로 보고 –> 각 성분의 letters의 비중을 구하는 방식으로
    각 성별에 따른 / 모든 각 연도별(각 열별) 마지막글자 a~z까지의 출생횟수 총합에 대한 각 마지막글자 a,b,c,들의 출생횟수 비중을 구한다.

    letters_prop = last_letters_table / last_letters_table.sum()
    letters_prop.head()
    image


  • 이제 .loc []행인덱싱을 통해서 마지막글자가 d, n, y인 애들만 추출하고 / 열인덱싱의 경우에는 남아인 M열(계층중 상위계층)만 인덱싱하자.

    dny_prop = letters_prop.loc[["d", "n", "y"], "M"]
    image

    행이 짧고 열이 너무 기므로(1880~2014) 행과 열을 바꾸는 함수 .tranpose()를 적용시켜보자.
    dny_prop.transpose()
    image

    transpose()한 것을 바로 lineplot()을 그려보자
    dny_prop.transpose().plot()
    image
    간단한 해석) d와 y로 끝나는 남자아이는 비중의 변화가 별로 없던 것에 비해
    n으로 끝나는 남자아이의 출생횟수 변화는   1960년이 넘어가면서부터   비중이 드라마틱하게 늘어났다.


< pivot_table을 이용하면 아주 쉽고 빠르게 통계량을 구할 수 있다는 것에 주목하자>


groupby() 그룹화)

각 ~별 -> 기준열
~~ 의  -> 기준열2
~~의 평균/합 을 계산 -> 추출열
평균/합 -> 마지막에 적용할 통계함수


pivot_table)

values : 추출열 / index : index로 가져올 기준열1 / columns : 칼럼으로 가져올 기준열2 / aggfunc : 통계함수(문자열)  / fill_value = 0 : NaN을 0으로

정적웹페이지를 [ 크롤링 ] –> [스크래핑] –> pipelines를 이용하여 데이터변형



동적웹페이지를 [ 스크래핑 ]까지만 하기


[ 파이썬 3.6 ]에서도 한방에 scrapy가 설치 가능하다.

  1. scrapy 설치 ( 각종 lxml 등 패키지와 함께 설치된다)
    [ conda install -c conda-forge scrapy ]
    https://doc.scrapy.org/en/latest/intro/install.html#installing-scrapy

  2. selenium 설치
    [ pip install -U selenium ]
    https://pypi.python.org/pypi/selenium




동적 웹페이지 웹 스크래핑 하기(scrapy+selenium)

동적 웹페이지인  premierleague.com를, scrapy + selenium을 활용하여,
2015/16 최종 순위표 url  : https://www.premierleague.com/tables?co=1&se=42&mw=-1&ha=-1 를 웹크롤링 해보자.


준비하기

  • 먼저, Prompt(1) scrapy shell용Prompt(2) jupyter notebook을 켜놓는다.

  • 접속하려는 url을 띄우고, 어떤 정보를 가져올지 생각해놓는다.
    순위/이름/경기수/승/무승부/패 / 골 득점/실점/골득실차/점수를 가져올 것이다.
    image


시작하기

  • 크롤링폴더인 web_da로 가서 scrapy startproject 프로젝트명 을 통해 크롤러의 새 프로젝트를 생성한다.
    scrapy startproject epl_crawler
    생성된 크롤러프로젝트는 jupyter로 확인한다

  • items.py를 열어서 item클래스를 정의해주자. item클래스에다가 각종 필드를 입력한다.
    image

  • spider폴더에 새로운 text-> epl_spider.py를 생성하여, Spider를 정의해주자.
    scrapy 및 epl_crawler폴더의 items.py의 EPLItem 클래스를  import해서 쓴다.
    (1) EPLSpider를 정의한다. 이 때,  크롤러이름 / 전체도메인 / 시작url을 정의한다.
    image
    (2) parse()함수를 정의한다. 이 때, parse()함수를 정의하기 위해서는 [크롬개발자도구 + shell]을 먼저 이용한다.

  • 해당 웹사이트를 shell에서 실행시켜놓고, 크롬개발자도구로 해당 웹사이트를 살펴봐야한다.
    image
    총 20개의 리스트가 있고, 각 item(행)에 속한 요소들을 가져올 것이다.
    20개의 리스트 상의 규칙성을 찾아, 한 item(행) 전체를 가져오게 할 것이다.
    (이전시간에는 상세페이지에서, 제목, 평점, 장르 각각의 xpath를 따로 구했는데,
    여기서는 리스트의 한 item를 먼저 가져올 것이다.)

    (1) 총 20개 리스트에서 한 item(행)의 요소 아무거나 [ctrl+shft+c]로 클릭한 뒤 타고 올라가보자.
        <tr> 요소들 중에서, class이름이 expandable인 것만 제외한 것을 구하면 된다.
       먼저, 첫번째 줄의 <tr>요소의 xpath를 가져와보자. 역시나 빈칸으로 셀렉터가 안가져와진다.
    image

    (2) 뒤에서부터 계층별로 살펴보면 된다.
    이 때, 맨 마지막 <tr>계층에서는 실제값을 가진 item이 “tableDark”와 “tableMid” 2가지 값을 가진 반면에 item이 없는 <tr>계층은 “expandable”만 있었다.
    tr의 인덱싱[] 란에,  tr[ not(@class="expandable") ]을 통해, 실제 필요한 class를 가져올 수 있게 되었다.
    그리고 각 계층을 따라올라가면서 필요없는 계층은 삭제해주고, 틀린인덱싱도 순서대로 세서 바르게 인덱싱시켜줘야한다.
    response.xpath('//*[@id="mainContent"]/div[2]/div[3]/div/div/div/table/tbody/tr[not(@class="expandable")]  ')
    image
    (3) 파이썬리스트 형태로 얻어진 item의 셀렉터리스트들을 rows라는 변수에 저장한 뒤,
       rows[0] 인덱싱으로 하나의 row만 따본다.
    rows = response.xpath('//*[@id="mainContent"]/div[2]/div[3]/div/div/div/table/tbody/tr[not(@class="expandable")]')
    row = rows[0]
    이 때, row에는 하나의 <tr>요소의 xpath셀렉터가 담겨있고, 
    .xpath( ‘./ ~~~ ’)로 추가할 <tr>요소 밑의 몇번째 <td>요소를 가져오냐에 따라서, 각 데이터값이 정해진다.
    <전체 item의 셀렉터리스트이므로, parse함수의 for문의 인자로 들어갈 것이다.>
    image
  • 첫번 째 [순위]의 경우, tr요소 밑-> 2번째 td 밑 –> span요소의 text로서 숨겨져 있었다.
    row(첫번째 item의 <tr>까지의 셀렉터)에 해당자식들까지 xpath를 추가한 다음, [0].extract()로 셀렉터->만 뽑아내보자.
    row.xpath('./td[2]/span/text()')[0].extract()
    image

  • 이제 [경기수]를 찍어내보자.  전체리스트[rows]의 첫번째[0] item의 <tr>요소 셀렉터인 row변수에,
    4번째 td요소까지 간 다음, text를 뽑으면 될 것이다.
    row.xpath('./td[4]/text()')[0].extract()
    1위팀의 경기 수 이므로, 38경기가 나와야하는데, shell에서는 29경기가 찍힌다.
    이것이 바로, 기본 정적페이지를 띄워놓고 –> 동적으로 웹페이지를 수정하는 [동적웹페이지]의 특징이기 때문이다.
    찍힌 29경기수는, 아직 refresh되기전의 1위팀의 경기수이고,
    다 로딩이 되어 동적으로 수정된 것의 1위팀 경기수는 38이다.
    image
    <이러한 동적웹페이지 크롤링이 불가능한 것은 scrapy만 사용한 한계이다.>


Selenium을 이용하여,   scrapy의 동적 웹페이지 스크래핑의 한계 극복하기

현재 띄워놓은 scrapy shell을 [ctrl+d]로 종료하고, 다시 shell을 띄우자.

shell에서 사용했던, response안에는 [정적웹페이지]의 응답정보를 담고 있다. 그러므로, scrapy의 response 대신
selenium에서 제공하는 webdriver모듈을 import한 다음,
[ webdriver모듈 + 크롬드라이버의 절대경로(tab으로 자동완성) ]를 통해, 크롬브라우저를 생성하여 browser 변수에 할당한다.
새로운 크롬브라우저가 실행이 된다.
from selenium import webdriver
browser = webdriver.Chrome("C:/Users/cho/chromedriver.exe")
image

  • response.url 을 통해, shell에 띄운 크롤링할 웹페이지의 url만 얻는다(response의 정보 이용x  .xpath (x))
    image

  • 이제 browser에 .get(  url  )함수를 이용해서, 새롭게 띄워진 브라우저에 크롤링할 웹페이지를 띄우도록 만든다.
    browser.get(response.url)
    image

  • 이제 scrapy의 response.text와 같이,
    현재 browser에 띄워진 웹페이지전체 html소스코드를 String형태로 담기 위해 아래코드를 실행한다.
    html = browser.find_element_by_xpath('//*').get_attribute('outerHTML')
    image
    <브라우저.get()함수 호출 후 – 충분한 시간간격(5초)가 있어야지 – 동적으로 생성된 컨텐츠가 포함된 html코드가 얻어진다>

  • selenium을 통해 얻어진 동적웹사이트의 html코드는 스트링으로 밖에 얻을 수 없다.
    그러므로, String을 –> scrapy의 Selector로 변환하는 과정이 필요하다.
    (1) scrapy의 selector.py의  Selector클래스import해야한다.
    from scrapy.selector import Selector

    (2) Selector클래스의 객체를 생성하고, 인자 text=에다가 String형 html코드 변수 를 넣어준다.
    selector = Selector(text = html)

    이 때, 소문자 selector
    띄워진 html코드를 selector 형태로서 가지고 있게 되므로,
    srcapy의 웹사이트 응답정보 변수이면서, parse()함수의 인자로 들어가는 response와 완전히 동일한 것
    이다.

    (my : response는 웹사이트에 대한 응답으로서, 전체 html코드를 셀렉터형태로 가지고 있었고,
           selenium을 통해 얻은 동적웹페이지의 전체 html코드의 문자열을 –> Selector객체에 담게 되면, response와 같은 놈이 된다!)
    image

  • 이제 browser에 띄워진 웹사이트에서, 크롬개발자도구를 이용하여, 원하는 부분의 xpath를 얻고 selector.xpath로 추가하면 된다.
    (broswer에 띄워진 것을 크롬개발자도구로 선택하여, xpath를 추출한 뒤, 셀렉터에서 얻으니까 한방에 얻어진다..
    맨끝의 td의 인덱싱으로 각각 필요한 정보를 바로 뽑아낼 수 있다.
    대신 한 item(행)만을 추출은 안된다. for문에 들어갈 전체item 리스트는 뒤에서 따라올라가는 식으로 잡아야할듯)

    1위팀의 이름xpath셀렉터 )
    selector.xpath('//*[@id="mainContent"]/div[2]/div[1]/div[3]/div/div/div/table/tbody/tr[1]/td[3]/a/span[3]')
    1위팀의 이름text()추출)
    selector.xpath('//*[@id="mainContent"]/div[2]/div[1]/div[3]/div/div/div/table/tbody/tr[1]/td[3]/a/span[3]/text()')[0].extract()
    1위팀의 경기수text()바로 추출)
    selector.xpath('//*[@id="mainContent"]/div[2]/div[1]/div[3]/div/div/div/table/tbody/tr[1]/td[4]/text()')[0].extract()
    image


여기까지 정리하자면,
원래 spider.py 속의 parse(self, response)함수에서, response변수에 얻어진 <정적컨텐츠가 포함된 웹페이지 셀렉터형태의 html>는 사용하지 않을 것이고, selenium webdriver를 사용하여 해당 url의 웹페이지를 직접 불어들인 뒤, <동적컨텐츠까지 포함되어 로딩된 html코드>를 사용하여 selector객체를 생성하고, 이를 이용해서 웹 스크래핑을 할 것이다.

  • 이제 scrapy shell –> selenium webdriver –> scrapy Selector 객체에 담긴 데이터를 이용해서
    ( 기존 scrapy shell –> 직접 웹페이지띄움 –> scrapy response )
    epl_spider.py의 EPLSpider클래스의 parse()함수를 채워야한다.
    그전에, 먼저 [epl_spider.py]에서 selenium의 webdriver를 사용할 수 있도록 각종 설정을 해줘야한다. 
    (우리가 shell에서 selenium webdriver를 import하고 사용한 것은, xpath를 알아내기 위함이다.
    이 알아낸 것들을 이용해서 ---> 결국에는 [ epl_spider.py ]에서 다 작동시켜야한다.)

    (1)[ epl_spider.py ]에  selenium의 webdriver모듈을 import해준다.
        from selenium import webdriver
    (2) EPLSpider클래스의 생성자 __init__(self): 함수오버라이딩 해야한다.
    (기존 pipelines클래스만 생성자 오버라이딩해서, csv쓰고, 첫행 기입)
    - 먼저 생략되있던 scrapy의 Spider클래스를 초기화해준다.(오버라이딩 하기전에, 기존 내부적으로 자동호출되는 초기화함수코드)
        scrapy.Spider.__init__(self)
    - 이제 spider클래스가 호출될 때 작동할 초기화 부분에,  broswer변수 생성 및 크롬드라이브 호출이 되도록 한다.
        self.browser = webdriver.Chrome("C:\Users\cho\chromedrive")
    image

  • 이제 parse(self, response) : 를 채워보자.
    (1) self.browser변수에 동적 웹페이지를 불러올 것인데, get함수의 인자에는
          기존 scrapy의 response 이용해서, url주소만! 을 얻어온다.
    *** time.sleep(5)를 통해 웹페이지가 동적컨텐츠를 모두 로딩할때까지의 시간을 줘야한다!
        < 크롬broswer를 통해 get으로 웹사이트 다시한번 띄우기 < ---충분한시간필요(5초)-----> html코드를 담기>
    *** import time
        from scrapy.selector import Selector
        < Selector 클래스 및, time모듈을  spider에도 import해줄 것! 강의에서는 안해줬는데, 에러남!>
    (2) 이전에 shell에서 했던 것처럼,  browser변수를 이용해서, 전체 html코드를 문자열으로 불러와 html변수에 담고
         Selector객체를 생성해 html문자열 변수를 인자로 넣어서, selector형태로 담아준다.
    (3) selector에 .xpath(‘ 전체 item의 리스트를 담는 xpath’)를 넣어, for문에서 각 item으로 꺼내쓰도록 한다.
      (이 때, 각 item(행)이 webdriver에서 안찍히더라도, 타고 올라가서 확인할 수 있고, 바로 xpath가 뽑힌다
       주의 할점은, 각 item(행)을 의미하는 <tr>가  xpath에서 tr[1]로부터 차근차근 시작하는 것이 아니라,
       <tr>의 속성중 클래스 이름이 “expandable”이 아닌 것을 리스트로 가져와야한다는 것을 알아챈 뒤,
       /tr[  not (@class= “expandable” ) ] 으로 인덱싱할줄 알아야하는 것
    이다.)
    (4) for문에서는 전체item리스트를 담은 변수(rows)를 인자로 넣고, row로 하나씩 꺼내본다.
        for문안에서, [items.py]에 정의해둔 EPLItem객체를 생성하고,
        객체의 각 필드에 꺼낸 row에 .xpath경로를 추가해서 세세한 text()를 [0].extract()추출한 것을 담아준다.
    (5) spider의 parse함수에서 item객체에 데이터를 넣은 뒤, yield로 반환했다.
    image

다시한번 정리하자면)
EPLSpider클래스에서 다시한번 생성자를 오버라이딩해서, 기본코드 + 크롬브라우저를 띄우도록 했고,
parse함수에서 크롬브라우저를 이용해서  다시한번 해당 웹페이지url을 불러온다. (scrapy에서 기본적으로 shell에서 한번 불러오므로)

  • 이제 크롤링을 하기 위해서, shell은 종료하고, 크롤링 프로젝트 1번째 폴더로 이동해야한다.
    cd epl_crawler

  • 크롤링을 시작한다. –o를 옵션을 통해서 pl.csv로 저장하도록 해보자.
    scrapy crawl PremierLeague -o pl.csv

<시작시 각종에러>
1. chrome driver의 절대경로는 폴더할때 쓰이는 \(W) 가 아니라 반대방향 / (쉬프트옆 문자)로 표시할 것.
2. items.py 의 scrapy.Item를 item 소문자로 잘못적었음.
3. shell에서는 해줬었던 Selector 클래스 및, time모듈 을  spider에도 import해줄 것
import time
from scrapy.selector import Selector

4. 전체리스트의 경로 수정
5. parse함수대로 데이터가 나오지 않는다. 수정하고 싶다면 pipeline을 이용할 것!

image

image

+ Recent posts