<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>SandwichBox</title>
        <link>https://velog.io/</link>
        <description>데이터 직무로 먹고 살고 싶은 사람</description>
        <lastBuildDate>Fri, 14 Jun 2024 11:39:35 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>SandwichBox</title>
            <url>https://velog.velcdn.com/images/julia-jh319/profile/bd7b1f90-0b79-4c66-8e44-711fb1f5054a/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. SandwichBox. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/julia-jh319" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[010. 데이터 취업 스쿨 스터디 노트_10주차_Git]]></title>
            <link>https://velog.io/@julia-jh319/010.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B810%EC%A3%BC%EC%B0%A8Git</link>
            <guid>https://velog.io/@julia-jh319/010.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B810%EC%A3%BC%EC%B0%A8Git</guid>
            <pubDate>Fri, 14 Jun 2024 11:39:35 GMT</pubDate>
            <description><![CDATA[<h1 id="10주차">10주차</h1>
<h2 id="수강한-분량">수강한 분량</h2>
<p>Git에 가입하고, Github과 Local을 연결하는 내용, Local 내부에서 충돌이 일어나는 내용을 다루는 법을 공부했다.</p>
<h1 id="각-강의별-학습한-핵심-내용-정리">각 강의별 학습한 핵심 내용 정리</h1>
<h1 id="git">Git</h1>
<h2 id="버전관리">버전관리</h2>
<ul>
<li>버전관리 시스템(형상관리)<ul>
<li>Configuration Management Systems</li>
<li>Version Control Systems</li>
</ul>
</li>
<li>버전관리<ul>
<li>Source Data + History</li>
<li>협업, 작업추적, 복구 등이 가능</li>
</ul>
</li>
<li>Git 등장 배경<ul>
<li>Local Version Control Systems<ul>
<li>파일 버전 관리 시스템</li>
<li>내 컴퓨터에서 버전 관리 기능 &gt; 하드 날아가면 전체 코드 사라짐</li>
<li>버전은 관리되지만, 협업은 여전히 어려움</li>
</ul>
</li>
<li>Centralized Version Control Systems<ul>
<li>중앙 관리 시스템</li>
<li>협업이 가능해짐</li>
<li>commit 하는 순간 배포되어 다수에게 버그 유발 가능(서버로 바로 commit)</li>
<li>인터넷이 안되면 작업이 불가능</li>
<li>자신만의 version history를 가질 수 없음</li>
</ul>
</li>
<li>Distributed Version Control Systems<ul>
<li>분산 버전 관리 시스템</li>
<li>commit 하더라도 개인저장소 내에 적용됨(다른 개발자에게 영향 없음)</li>
<li>원하는 순간 배포(push) 가능</li>
<li>오프라인에서도 작업 가능</li>
<li>자신만의 version history를 가짐</li>
</ul>
</li>
</ul>
</li>
<li>버전 관리 시스템 종류<ul>
<li>CVCS<ul>
<li>CVS<ul>
<li>1980년대 만들어진 형상관리 시스템</li>
<li>commit 중 오류 발생 시 Rollback이 되지 않는 등의 문제</li>
<li>이후 SVN으로 대체됨</li>
</ul>
</li>
<li><strong>SVN</strong><ul>
<li>subversion.apache.org</li>
<li>2000년대 만들어졌고, 현재까지 두루 사용 중</li>
</ul>
</li>
</ul>
</li>
<li>DVCS<ul>
<li>Mercurial</li>
<li><strong>Git</strong><ul>
<li>git-scm.com</li>
<li>SVM보다 빠른 속도, 많은 기능 지원</li>
<li>현재 많은 기업이 사용 중</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Git  기반의 서비스<ul>
<li>Github<ul>
<li>github.com</li>
<li>git을 호스팅해주는 웹 서비스, 협업을 위한 기능을 제공</li>
<li>소스코드 보안이 중요한 경우 사용을 기피함</li>
</ul>
</li>
<li>Gitlab<ul>
<li>gitlab.com</li>
<li>설치형 버전관리 시스템<ul>
<li>소스코드 보안이 중요한 기업에서 주로 사용</li>
</ul>
</li>
<li>클라우드 버전 관리 시스템<ul>
<li>10명 이하 부료(Githunb과 유사)</li>
</ul>
</li>
<li>Issue tracker, Git Remote Repository, API, Team, Group 기능 제공<h2 id="git-가입">Git 가입</h2>
</li>
</ul>
</li>
</ul>
</li>
<li>git global configuration<ul>
<li><code>git config --global user.name &lt;username&gt;</code></li>
<li>`git config --global user.email. <email></li>
</ul>
</li>
<li>가져올 때는 LF를 CRLF로 변경하고 보낼때는 CRLF를 LF로 변경<ul>
<li><code>git config --global core.autocrlf true</code></li>
</ul>
</li>
<li>line ending<ul>
<li>CR<ul>
<li><code>\r</code></li>
</ul>
</li>
<li>LF<ul>
<li><code>\n</code></li>
</ul>
</li>
<li>window<ul>
<li>CR + LF</li>
</ul>
</li>
<li>Unix or Mac<ul>
<li>LF</li>
</ul>
</li>
<li>OS가 상이한 사용자가 같은 Git Repository를 작업할 때, 코드에서 변경된 내용이 없어도 CRLF 차이로 인해 commit이 발생할 수 있음</li>
</ul>
</li>
<li>Editor<ul>
<li><code>git config --global core.editor &lt;editor&gt;</code></li>
</ul>
</li>
<li>전체 설정 확인<ul>
<li><code>git config --list</code></li>
</ul>
</li>
<li>항목별 설정 확인<ul>
<li><code>git config &lt;key&gt;</code><h2 id="git-용어">Git 용어</h2>
</li>
</ul>
</li>
<li>Repository<ul>
<li>소스코드가 저장되어 있는 여러 개의 Branch가 모여있는 디스크상의 물리적 공간</li>
<li>Local Repository</li>
<li>Remote Repository</li>
</ul>
</li>
<li>Checkout<ul>
<li>특정 시점이나 Branch의 소스코드로 이동하는 것</li>
<li>Checkout 대상<ul>
<li>Branch</li>
<li>Commit</li>
<li>Tag</li>
</ul>
</li>
<li>과거 여러 시점의 코드로 이동 가능</li>
</ul>
</li>
<li>Stage<ul>
<li>작업할 내용이 올라가는 임시저장영역</li>
<li>내용중 commit에 반영할 파일만 선별하여 commit을 수행할 수 있음</li>
</ul>
</li>
<li>Commit<ul>
<li>작업할 내용을 Local Repository에 저장하는 과정</li>
<li>각각의 commit은 의미있는 변경단위, 변경에 대한 설명을 commit log로 남김</li>
<li>commit을 아끼지 말기 &gt; 게임의 save point</li>
<li>commit단위, commit log format이 정해진 회사 혹은 팀 있음(빌드 서버를 사용하는 경우)</li>
</ul>
</li>
<li>Tag<ul>
<li>임의의 commit 위치에 쉽게 찾아갈 수 있도록 붙여놓은 이정표</li>
<li>Tag가 붙은 commit은 commit id (version) 대신 tag name으로 쉽게 checkout 가능</li>
</ul>
</li>
<li>Push<ul>
<li>Local Repository의 내용 중, Remote Repository에 반영되지 않은 commit을 Remote Repository로 보내는 과정</li>
<li>Push하는 순간 다른 개발자들도 영향을 받음, 검증된 코드만 Push하기</li>
</ul>
</li>
<li>Pull<ul>
<li>Remote Repository에 있는 내용 중, Local Repository에 반영되지 않은 내용을 가져와서 Local Repository에 저장하는 과정</li>
<li>다른 팀원이 변경하고 Push한 내용을 Local Repository에 가져올 수 있음</li>
<li>Push 과정에서 Conflict가 일어나 Push가 거절된 경우, Pull을 통해 Remote Repository의 변경 내용을 Local Repository에 반영하여 Conflict를 해결한 뒤 다시 Push를 시도해야 함</li>
</ul>
</li>
<li>Branch<ul>
<li>특정 시점 (commit 단위)에서 분기하여 새로운 commit을 쌓을 수 있는 가지를 만드는 것</li>
<li>개발의 주축이 되는 branch를 master branch 혹은 main branch라고 함</li>
<li>모든 branch는 최종적으로 다시 master branch에 merge되는 형식으로 진행됨</li>
</ul>
</li>
<li>Merge<ul>
<li>Branch의 반대개념으로 하나의 Branch를 다른 Branch와 합치는 과정</li>
<li>Merge되는 두 Branch는 주종관계가 성립 &gt; dev Branch를 main Branch에 merge</li>
<li>Merge되는 과정에서 Conflict가 발생한 경우, Diff를 수정하여, Conflict를 해결한 뒤 Merge를 진행할 수 있음<h2 id="local-repository">Local Repository</h2>
</li>
</ul>
</li>
<li>Working Directory(작업공간)<ul>
<li>실제 소스 파일, 생성한 파일들이 존재</li>
</ul>
</li>
<li>Index(Stage)<ul>
<li>Staging Area(준비영역)의 역할, git add한 파일들이 존재</li>
</ul>
</li>
<li>HEAD<ul>
<li>최종 확정본, git commit한 파일들이 존재</li>
</ul>
</li>
<li>Local Repository 생성<ul>
<li>원하는 디렉토리로 이동한 후, <code>git init</code>을 실행하면 git이 활동을 시작</li>
<li><code>ls -all</code><ul>
<li>내부에 있는 모든 파일들을 보여줌</li>
<li><code>-all</code> 옵션으로 숨겨진 것 또한 보여줌</li>
</ul>
</li>
<li><code>touch &lt;file_name.확장자&gt;</code><ul>
<li>빈 파일을 생성</li>
</ul>
</li>
<li><code>git status</code><ul>
<li>git에 존재하는 파일 확인</li>
</ul>
</li>
</ul>
</li>
<li>version 관리<ul>
<li><code>git add &lt;filename&gt;</code><ul>
<li>Working Directory에서 변경된 파일을 Index(Stage)에 추가</li>
</ul>
</li>
<li><code>git commit -m &quot;commit에 대한 설명&quot; &lt;filename&gt;</code><ul>
<li>Index(Stage)에 추가된 변경사항을 HEAD에 반영 (확정)</li>
</ul>
</li>
</ul>
</li>
<li>Remote Repository 생성<ul>
<li>Github Token 생성<ul>
<li>보안상의 이유로 Remote Repository 접속 시 비밀번호 대신 Token 사용</li>
</ul>
</li>
</ul>
</li>
<li>Remote Repository 등록<pre><code>  - `git remote add origin https://githup.com/&lt;repository&gt;.git`
  - `git remote add origin https://&lt;username&gt;:&lt;token&gt;@githup.com/&lt;repository&gt;.git`
      - 매번 아이디와 비밀번호 입력 없이 연결 가능</code></pre><ul>
<li><code>git remote -v</code><ul>
<li>remote repository 정보 확인</li>
</ul>
</li>
</ul>
</li>
<li>Remote Repository에 변경 내용 push<ul>
<li>HEAD에 반영된 변경내용을 Remote Repository에도 반영하기 위해서는 Git Push를 사용</li>
<li><code>git push origin &lt;branchname&gt;</code></li>
</ul>
</li>
<li>Remote Repository에서 Pull 하기<ul>
<li><code>git pull origin &lt;branchname&gt;</code></li>
</ul>
</li>
<li>파일 읽기<ul>
<li><code>cat &lt;filename.확장자&gt;</code></li>
</ul>
</li>
<li>파일 쓰기<ul>
<li><code>cat &gt; &lt;filename.확장자&gt;</code><h2 id="remote-repository">Remote Repository</h2>
</li>
</ul>
</li>
<li>README file<ul>
<li>프로젝트에 대한 설명, 사용방법, 라이센스, 설치방법 등에 대한 내용을 기술하는 파일</li>
<li>나, 직장동료, 프로그램 사용자를 위해 존재</li>
</ul>
</li>
<li>.gitignore<ul>
<li>Git 버전 관리에서 제외할 파일목록을 지정하는 파일</li>
<li>사용자가 원하지 않는 파일들을 자동으로 commit 대상에서 제외시켜 줌</li>
</ul>
</li>
<li>Default Branch<ul>
<li>main<ul>
<li>Remote에서 시작한 경우</li>
</ul>
</li>
<li>Master<ul>
<li>Local에서 시작한 경우</li>
</ul>
</li>
<li>branch 이름을 수정할 수도 있지만 아주 초반이 아니라면 신중한 것이 좋다</li>
<li>Default Branch 이름을 설정에서 아주 바꾸는 법이 있다</li>
</ul>
</li>
<li>Git Clone<ul>
<li>앞서 폴더를 만들고<ul>
<li>Git Init으로 해당 폴더를 초기화</li>
<li>Remote Repository 등록</li>
<li>Remote Repository 내용을 Pull하는 모든 과정을 <strong>Git Clone</strong>으로 수행</li>
</ul>
</li>
<li><code>git clone https://github.com/&lt;repository&gt;.git</code></li>
<li><code>git clone https://&lt;username&gt;:&lt;token&gt;@githup.com/&lt;repository&gt;.git</code><pre><code>  - 매번 아이디와 비밀번호 입력 없이 연결 가능</code></pre></li>
</ul>
</li>
<li>Branch<ul>
<li>조회<ul>
<li>Local에서 조회<ul>
<li><code>git branch</code></li>
</ul>
</li>
<li>Remote 조회<ul>
<li><code>git branch -r</code></li>
</ul>
</li>
<li>Local, Remote 함께 조회<ul>
<li><code>git branch -a</code></li>
</ul>
</li>
</ul>
</li>
<li>생성<ul>
<li><code>git branch &lt;branchname&gt;</code></li>
<li>특정 branch를 remote인 origin에 올리겠다<ul>
<li><code>git push origin &lt;branchname&gt;</code></li>
</ul>
</li>
</ul>
</li>
<li>이동<ul>
<li><code>git checkout &lt;branchname&gt;</code></li>
<li>없어 만들고 이동<ul>
<li><code>git checkout -b &lt;branchname&gt;</code></li>
</ul>
</li>
</ul>
</li>
<li>삭제<ul>
<li>내가 머무르고 있는 branch에서는 자신을 삭제할 수 없다</li>
<li>Local에서<ul>
<li><code>git branch -d &lt;branchname&gt;</code></li>
</ul>
</li>
<li>Remote에서<ul>
<li><code>git push origin --delete &lt;branchname&gt;</code><h2 id="log-and-diff">Log and Diff</h2>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Git Graph
  -VScode에서 Git 변화를 그래프 형태로 볼 수 있는 것</li>
<li>Git Log<ul>
<li>branch 별로 변경이력을 볼 수 있음</li>
</ul>
</li>
<li>Git Editor<ul>
<li><code>git config --global core.editor &lt;editorname&gt; --wait</code><ul>
<li><code>--wait</code>옵션은 command line으로 VSCode를 실행시켰을 경우, VSCode 인스턴스 닫을 때까지 command 대기</li>
</ul>
</li>
</ul>
</li>
<li>Git Configuration<ul>
<li><code>git config --global -e</code><ul>
<li>git configuration 파일 열기</li>
</ul>
</li>
<li>Git Diff 설정 추가<pre><code>[diff]
tool = vscode
[difftool &quot;vscode&quot;]
cmd = &quot;code --wait --diff $LOCAL $REMOTE&quot;</code></pre></li>
</ul>
</li>
<li>Git Diff<ul>
<li>Local branch 간 비교<ul>
<li><code>git diff &lt;branch1&gt; &lt;branch2&gt;</code><ul>
<li>Bash 환경에서 확인</li>
</ul>
</li>
<li><code>git difftool &lt;branch1&gt; &lt;branch2&gt;</code><ul>
<li>vscode의 diff 기능을 활용</li>
</ul>
</li>
</ul>
</li>
<li>commit 간 비교<ul>
<li>commithash 앞 7자리만 넣어도 비교 가능</li>
<li><code>git diff &lt;commithash&gt; &lt;commithash&gt;</code><ul>
<li>Bash 환경에서 확인</li>
</ul>
</li>
<li><code>git difftool &lt;commithash&gt; &lt;commithash&gt;</code><ul>
<li>vscode의 diff 기능 활용</li>
</ul>
</li>
</ul>
</li>
<li>마지막 commit과 이전 commit 비교<ul>
<li><code>git diff HEAD HEAD^</code><ul>
<li>Bash 환경에서 확인</li>
</ul>
</li>
<li>`git difftool HEAD HEAD^<ul>
<li>vscode의 diff 기능 활용</li>
</ul>
</li>
</ul>
</li>
<li>마지막 commit과 현재 수정사항 확인<ul>
<li><code>git diff HEAD</code></li>
</ul>
</li>
<li>Local과 Remote 간 비교<ul>
<li><code>git diff &lt;branch&gt; origin/&lt;branch2&gt;</code><h2 id="merge-and-conflict">Merge and Conflict</h2>
</li>
</ul>
</li>
</ul>
</li>
<li>Git Merge<ul>
<li>현재 위치한 branch에 다른 branch를 병합<ul>
<li><code>git merge &lt;branchname&gt;</code></li>
</ul>
</li>
</ul>
</li>
<li>Git Conflict<ul>
<li>Branch를 Merge하는 과정에서 충돌이 생김</li>
<li>Push, Pull 하는 과정에서도 충돌이 날 수 있음</li>
</ul>
</li>
<li><code>git mergetool</code><ul>
<li>conflict 발생 이후 위의 명령어 입력 시, conflict난 파일들이 차례로 열림</li>
<li>내부 문자 의미<ul>
<li><code>&lt;&lt;&lt;&lt;</code><ul>
<li>현재 변화</li>
</ul>
</li>
<li><code>====</code><ul>
<li>구분</li>
</ul>
</li>
<li><code>&gt;&gt;&gt;&gt;</code><ul>
<li>앞으로의 변화</li>
</ul>
</li>
</ul>
</li>
<li>살릴 내용 말고 나머지 다 지우고 저장</li>
<li><code>git status</code>로 확인하면, 파일명.확장자.orig 라는 파일이 생김<ul>
<li>백업용 파일</li>
</ul>
</li>
<li>add, commit하면 정리</li>
<li>이후 merge 중 충돌 관련된 내용 문서가 나옴<h2 id="tag">Tag</h2>
</li>
</ul>
</li>
<li>특정 버전(Commit)에 Tag를 달아놓을 필요가 있을 때 사용<ul>
<li>버전 릴리즈</li>
</ul>
</li>
<li>생성<ul>
<li>현재 버전에 Tag 달기<ul>
<li><code>git tag &lt;tagname&gt;</code></li>
</ul>
</li>
<li>특정 버전에 Tag 달기<ul>
<li><code>git tag &lt;tagname&gt; &lt;commithash&gt;</code></li>
</ul>
</li>
<li>Tag를 Remote Repository에 Push<ul>
<li><code>git push origin &lt;tagname&gt;</code></li>
</ul>
</li>
</ul>
</li>
<li>Tag 목록 보기<ul>
<li><code>git tag</code></li>
</ul>
</li>
<li>Tag 상세 정보<ul>
<li><code>git show &lt;tagname&gt;</code></li>
</ul>
</li>
<li>삭제<ul>
<li><code>git tag --delete &lt;tagname&gt;</code></li>
<li><code>git push --delete origin &lt;tagname&gt;</code><h2 id="readme">README</h2>
</li>
</ul>
</li>
<li>프로젝트에 대한 설명, 사용방법, 라이센스, 설치방법 등에 대한 내용을 기술하는 파일</li>
<li>나, 직장동료, 프로그램 사용자를 위해 존재</li>
<li>Markdown 문법<ul>
<li><code>#</code><ul>
<li>headers</li>
<li>갯수가 많을수록 작아짐</li>
</ul>
</li>
<li><code>&gt;</code><ul>
<li>blockquote</li>
<li>블럭 인용</li>
<li>블럭 내에서 다른 Markdown 요소 포함 가능</li>
</ul>
</li>
<li>목록<ul>
<li><code>1.</code><ul>
<li>순서가 있는 목록<ul>
<li>내림차순으로 자동 정렬</li>
</ul>
</li>
</ul>
</li>
<li><code>*</code>, <code>-</code>, <code>+</code><ul>
<li>순서가 없는 목록<ul>
<li>문자가 달라도 상관 X</li>
<li>하위로 갈수록 표시 모양이 달라짐</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>코드블럭<ul>
<li><code>&lt;pre&gt;&lt;code&gt;{code}&lt;\code&gt;&lt;\pre&gt;</code></li>
<li><code>\```{code}```\</code></li>
</ul>
</li>
<li>수평선<ul>
<li><code>***</code></li>
<li><code>* * *</code></li>
<li><code>*****</code></li>
<li><code>- - -</code></li>
<li><code>------</code></li>
</ul>
</li>
<li>외부 링크<ul>
<li><code>[텍스트](하이퍼링크, &quot;커서 올리면 나오는 글&quot;)</code></li>
</ul>
</li>
<li>자동 연결<ul>
<li><code>- 외부링크: &lt;하이퍼 링크&gt;</code></li>
</ul>
</li>
<li>강조<ul>
<li><code>*기울임*</code></li>
<li><code>_기울임_</code></li>
<li><code>**진하게**</code></li>
<li><code>__진하게__</code></li>
<li><code>~~취소~~</code></li>
</ul>
</li>
<li>이미지<ul>
<li>이미지가 어딘가 업로드되어 있어야 함</li>
<li><code>![Alt text] (/path/to/img.jpg)</code></li>
<li><code>![Alt text] (/path/to/img.jpg &quot;Optional title&quot;)</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="느낀점">느낀점</h2>
<p>그동안 Git을 사용하면서 왜 충돌이 일어날까. 나 혼자 쓰는데?? 하는 부분을 이해할 수 있었다. 모든 충돌은 컴퓨터가 가치판단을 하지 않기때문에 일어나는 것. 내용을 갈아엎는다면, 무조건 충돌을 예상하고 어떻게 수정할 지, 혹은 강제로 바꾸는 것을 익히는 것이 필요할지도.
SQL과 마찬가지로 Git은 command 환경이지만 Bash라 언어가 달랐다. 예전에 끄적거리던 리눅스언어가 생각났다. 그때 좀 더 노력했다면 지금 훨씬 쉬웠을까?</p>
<p><strong>이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[009. 데이터 취업 스쿨 스터디 노트_9주차_SQL]]></title>
            <link>https://velog.io/@julia-jh319/009.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B89%EC%A3%BC%EC%B0%A8SQL</link>
            <guid>https://velog.io/@julia-jh319/009.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B89%EC%A3%BC%EC%B0%A8SQL</guid>
            <pubDate>Fri, 14 Jun 2024 11:35:12 GMT</pubDate>
            <description><![CDATA[<h1 id="9주차">9주차</h1>
<h2 id="수강한-분량">수강한 분량</h2>
<p>SQL, SQL 고급 내용을 공부했다. MySQL, AWS 등을 익혔다.</p>
<h1 id="각-강의별-학습한-핵심-내용-정리">각 강의별 학습한 핵심 내용 정리</h1>
<h2 id="database-설치하기">DataBase 설치하기</h2>
<ul>
<li>MySQL 설치</li>
<li>server</li>
<li>workbench<ul>
<li>server에 접속해 명령을 던지는 프로그램</li>
</ul>
</li>
<li>shell</li>
<li>router</li>
<li>connector<h2 id="database">DataBase</h2>
</li>
<li>DataBase<ul>
<li>여러 사람이 공유하여 사용할 목적으로 체계화해 통합, 관리하는 데이터의 집합체</li>
</ul>
</li>
<li>DBMS<ul>
<li>사용자와 데이터베이스 사이에서 사용자의 요구에 따라 정보를 생성해주고 데이터베이스를 관리해주는 소프트웨어</li>
</ul>
</li>
<li>RDB, Relational Database<ul>
<li>서로간에 관계가 있는 데이터 테이블들을 모아둔 데이터 저장공간</li>
</ul>
</li>
<li>SQL<ul>
<li>데이터베이스에서 데이터를 정의, 조작, 제어하기 위해 사용하는 언어</li>
<li>DDL, Data Definition Language<ul>
<li>CREATE, ALTER, DROP</li>
</ul>
</li>
<li>DML, Data Manipulation Language<ul>
<li>INSERT, UPDATE, DELETE, <strong>SELECT</strong></li>
</ul>
</li>
<li>DCL, Data Control Language<ul>
<li>GRANT, REVOKE, COMMIT, ROLLBACK</li>
</ul>
</li>
</ul>
</li>
<li>root 계정으로 접속<ul>
<li><code>% mysql -u root -p</code></li>
</ul>
</li>
<li>현재 DB 목록 확인<ul>
<li><code>SHOW DATABASES;</code></li>
</ul>
</li>
<li>DB 이름 지정하여 생성<ul>
<li><code>CREATE DATABASE dbname;</code></li>
</ul>
</li>
<li>DB로 이동<ul>
<li><code>USE dbname;</code></li>
</ul>
</li>
<li>DB 삭제<ul>
<li><code>DROP DATABASE dbname;</code><h2 id="user">User</h2>
</li>
</ul>
</li>
<li>사용자 정보는 mysql에서 관리하므로 mysql DB로 이동 후 조회<ul>
<li><code>use mysql;</code></li>
<li><code>SELECT host, user FROM user;</code></li>
</ul>
</li>
<li>User 생성<ul>
<li>현재 PC에서만 접속 가능한 사용자를 비번과 함께 생성<ul>
<li><code>CREATE USER &#39;username&#39;@&#39;localhost&#39; identified by &#39;password&#39;;</code></li>
</ul>
</li>
<li>외부에서 접속 가능한 사용자를 비번과 함께 생성<ul>
<li><code>CREATE USER &#39;username&#39;@&#39;%&#39; identified by &#39;password&#39;;</code></li>
</ul>
</li>
</ul>
</li>
<li>User 삭제<ul>
<li>접근 범위에 따라 이름이 같은 사용자여도 별도로 삭제</li>
<li><code>DROP USER &#39;username&#39;@&#39;localhost&#39;</code></li>
<li><code>DROP USER &#39;username&#39;@&#39;%&#39;</code></li>
</ul>
</li>
<li>User 권한 관리<ul>
<li>권한 확인<ul>
<li><code>SHOW GRANTS FOR &#39;username&#39;@&#39;localhost&#39;</code></li>
</ul>
</li>
<li>권한 부여<ul>
<li>`GRANT ALL ON dbname.* to &#39;username&#39;@&#39;localhost&#39;;</li>
</ul>
</li>
<li>권한 삭제<ul>
<li><code>REVOKE ALL ON dbname.* from &#39;username&#39;@&#39;localhost&#39;;</code></li>
</ul>
</li>
</ul>
</li>
<li>새로고침<ul>
<li><code>FLUSH PRIVILEGES;</code><h2 id="db-요소-및-명령어">DB 요소 및 명령어</h2>
</li>
</ul>
</li>
<li>실습용 데이터 베이스 만들어 두기<ul>
<li><code>CREATE DATABASE zerobase DEFAULT CHARACTER SET utf8mb4</code><ul>
<li>utf8<ul>
<li>다국어</li>
</ul>
</li>
<li>mb4<ul>
<li>이모지 문자 지원<h3 id="table">Table</h3>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Table<ul>
<li>DB 안에서 실제 데이터가 저장되는 형태이고, 행(row)과 열(column)로 구성된 데이터 모음</li>
</ul>
</li>
<li>Table 생성<ul>
<li><code>CREATE TABLE tablename(columnname datatype, columnname datatype, ...);</code></li>
</ul>
</li>
<li>Table 목록 확인<ul>
<li><code>SHOW TABLES;</code></li>
</ul>
</li>
<li>Table 정보 확인<ul>
<li><code>DESC tablename;</code></li>
</ul>
</li>
<li>Table 변경<ul>
<li>아래 문구 뒤에 변경할 내용에 맞추어 다음 문구를 넣는다.</li>
<li><code>ALTER TABLE tablename</code></li>
<li>table 이름 변경<ul>
<li><code>RENAME new_tablename;</code></li>
</ul>
</li>
<li>column 추가<ul>
<li><code>ADD COLUMN columnname databtype;</code></li>
</ul>
</li>
<li>column 데이터 타입 변경<ul>
<li><code>MODIFY COLUMN columnname datatype;</code></li>
</ul>
</li>
<li>column 이름, 데이터 입 변경<ul>
<li><code>CHANGE COLUMN old_columnname new_columnname datatype;</code></li>
</ul>
</li>
<li>column 삭제<ul>
<li><code>DROP COLUMN columnname</code></li>
</ul>
</li>
</ul>
</li>
<li>Table 삭제<ul>
<li><code>DROP TABLE tablename;</code><h3 id="dml">DML</h3>
</li>
</ul>
</li>
<li>INSERT<ul>
<li>데이터 추가</li>
<li><code>INSERT INTO tablename (col1, col2, ...) VALUES (val1, val2, ...);</code></li>
<li>컬럼 이름 순서와 값 순서가 일치하도록 주의</li>
<li>모든 컬럼 값 추가하는 경우 컬럼 이름 생략해도 괜찮음</li>
<li><code>INSERT INTO tablename VALUES (val1, val2, ...);</code></li>
</ul>
</li>
<li>SELECT<ul>
<li>테이블 내 특정 컬럼에 대한 데이터를 조회<ul>
<li><code>SELECT col1, col2 FROM tablename;</code></li>
</ul>
</li>
<li>테이블 내 모든 컬럼에 대한 데이터를 조회<ul>
<li><code>SELECT * FROM tablename;</code></li>
</ul>
</li>
<li>WHERE<ul>
<li>SQL문에 조건을 추가하여 SELECT 뿐 아니라 UPDATE, DELETE에도 사용</li>
<li><code>WHERE condition;</code></li>
</ul>
</li>
</ul>
</li>
<li>UPDATE<ul>
<li>테이블 내 데이터 수정</li>
<li><code>UPDATE tablename SET col1 = val1, col2 = val2, ... WHERE condition;</code></li>
</ul>
</li>
<li>DELETE<ul>
<li>테이블 내 내용 삭제</li>
<li><code>DELETE FROM tablename WHERE condition;</code><h3 id="order-by">ORDER BY</h3>
</li>
</ul>
</li>
<li>정렬</li>
<li><code>SELECT col1, col2 FROM tablename</code></li>
<li><code>ORDER BY col1, col2, ... ASC | DESC;</code><h3 id="비교-연산자">비교 연산자</h3>
</li>
<li>=<ul>
<li>같은</li>
</ul>
</li>
<li><blockquote>
</blockquote>
<ul>
<li>보다 큰(초과)</li>
</ul>
</li>
<li>&lt;<ul>
<li>보다 작은(미만)</li>
</ul>
</li>
<li><blockquote>
<p>=</p>
</blockquote>
<ul>
<li>보다 크거나 같은(이상)</li>
</ul>
</li>
<li>&lt;=<ul>
<li>보다 작거나 같은(이하)</li>
</ul>
</li>
<li>&lt;&gt;<ul>
<li>보다 크거나 작은(같지 않은)</li>
</ul>
</li>
<li>!=<ul>
<li>같지 않은<h3 id="논리-연산자">논리 연산자</h3>
AND 우선순위가 OR 보다 높아 먼저 처리되므로 괄호 활용을 잘 해야한다.</li>
</ul>
</li>
<li>AND<ul>
<li>조건을 모두 만족하면 TRUE</li>
<li><code>SELECT col1, col2 FROM tablename WHERE cond1 AND cond2 AND cond3 ...;</code></li>
</ul>
</li>
<li>OR<ul>
<li>하나의 조건이라도 만족하면 TRUE</li>
<li><code>SELECT col1, col2 FROM tablename WHERE cond1 OR cond2 OR cond3 ...;</code></li>
</ul>
</li>
<li>NOT<ul>
<li>조건을 만족하지 않으면 TRUE</li>
<li><code>SELECT col1, col2 FROM tablename WHERE NOT cond</code></li>
</ul>
</li>
<li>BETWEEN<ul>
<li>조건값이 범위 사이에 있으면 TRUE</li>
<li><code>SELECT col1, col2 FROM tablename WHERE col1 BETWEEN val1 AND val2;</code></li>
</ul>
</li>
<li>IN<ul>
<li>조건값이 목록에 있으면 TRUE</li>
<li><code>SELECT col1, col2 FROM tablename WHERE col1 IN (val1, val2, ...)</code></li>
</ul>
</li>
<li>LIKE<ul>
<li>조건값이 패턴에 맞으면 TRUE</li>
<li><code>SELECT col1, col2 FROM tablename WHERE col LIKE pattern</code></li>
<li><code>%</code><ul>
<li>어떤 문자가 와도 괜찮다</li>
</ul>
</li>
<li><code>_</code><ul>
<li>어떤 문자 한 개<h3 id="union">UNION</h3>
</li>
</ul>
</li>
</ul>
</li>
<li>UNION<ul>
<li>여러 개의 SQL문을 합쳐서 하나의 SQL문으로 만들어주는 방법<ul>
<li><strong>칼럼 갯수가 같아야 함</strong></li>
</ul>
</li>
</ul>
</li>
<li>UNION<ul>
<li>중복된 값을 제거하여 알려준다</li>
</ul>
</li>
<li>UNION ALL<ul>
<li>중복된 값도 모두 보여준다</li>
</ul>
</li>
<li><code>SELECT col1, col2, ... FROM tableA UNION | UNION ALL SELECT col1, col2, ... FROM tableB;</code><h3 id="join">JOIN</h3>
</li>
<li>JOIN<ul>
<li>두 개 이상의 테이블을 결합하는 것</li>
</ul>
</li>
<li>INNER JOIN<ul>
<li>두 개의 테이블에서 공통된 요소들을 통해 결합하는 조인 방식</li>
<li><code>SELECT tableA.col1, tableB.col2, ... FROM tableA INNER JOIN tableB ON tableA.col = tableB.col WHERE condition;</code></li>
</ul>
</li>
<li>LEFT JOIN<ul>
<li>두 개의 테이블에서 공통 영역을 포함해 왼쪽 테이블의 다른 데이터를 포함하는 조인 방식</li>
<li><code>SELECT tableA.col1, tableB.col2, ... FROM tableA LEFT JOIN tableB ON tableA.col = tableB.col WHERE condition;</code></li>
</ul>
</li>
<li>RIGHT JOIN<ul>
<li>두 개의 테이블에서 공통 영역을 포함해 오른쪽 테이블의 다른 데이터를 포함하는 조인 방식</li>
<li><code>SELECT tableA.col1, tableB.col2, ... FROM tableA RIGHT JOIN tableB ON tableA.col = tableB.col WHERE condition;</code></li>
</ul>
</li>
<li>FULL OUTER JOIN<ul>
<li>두 개의 테이블에서 공통 영역을 포함하여 양쪽 테이블의  다른 영역을 모두 포함하는 조인 방식</li>
<li><code>SELECT tableA.col1, tableB.col2, ... FROM tableA FULL OUTER JOIN tableB on tableA.col = tableB.col WHERE condition;</code></li>
<li>MySQL은 동일 쿼리를 제공하지 않고 비슷한 다른 것으로 사용가능<ul>
<li><code>SELECT tableA.col1, tableB.col2, ... FROM tableA LEFT JOIN tableB on tableA.col = tableB.col UNION SELECT tableA.col1, tableB.col2, ... FROM tableA RIGHT JOIN tableB ON tableA.col = tableB.col WHERE condition;</code></li>
</ul>
</li>
</ul>
</li>
<li>SELF JOIN<ul>
<li>가장 많이 사용되며, INNER JOIN과 같은 결과를 낸다.</li>
<li>JOIN되는 table들의 공통되는 데이터를 가져온다.</li>
<li><code>SELECT tableA.col1, tableB.col2, ... FROM tableA, tableB, ... WHERE condition;</code><ul>
<li>기준을 where 절에 명시한다<h3 id="유용한-기능">유용한 기능</h3>
</li>
</ul>
</li>
</ul>
</li>
<li>CONCAT<ul>
<li>여러 문자열을 하나로 합치거나 연결하는 함수</li>
<li><code>SELECT CONCAT(&#39;string1&#39;, &#39;string2&#39;, ...);</code></li>
</ul>
</li>
<li>ALIAS<ul>
<li>칼럼이나 테이블 이름에 별칭 생성</li>
<li><code>SELECT column AS alias FROM tablename</code></li>
<li><code>SELECT col1, col2, ... FROM tablename AS alias</code></li>
<li>as 생략 가능</li>
</ul>
</li>
<li>DISTINCT<ul>
<li>검색한 결과의 중복 제거</li>
<li><code>SELECT DISTINCT co1, co2, ... FROM tablename;</code></li>
</ul>
</li>
<li>LIMIT<ul>
<li>검색결과를 정렬된 순으로 주어진 숫자만큼만 조회</li>
<li><code>SELECT col1, col2, ... FROM tablename WHERE condition LIMIT number;</code><h2 id="aws-rds">AWS RDS</h2>
</li>
</ul>
</li>
<li>AWS RDS, Amazon Relational Database Service<ul>
<li>AWS에서 제공하는 관계형 데이터베이스 서비스</li>
<li>Cloud 상에 Database를 구축한다</li>
</ul>
</li>
<li>AWS RDS 생성<ul>
<li>콘솔 &gt; 서비스 &gt; 데이터베이스 &gt; RDS &gt; 데이터베이스 생성</li>
<li>표준 생성 &gt; MySQL &gt; 프리 티어(무료) &gt; 스토리지 자동 조정 활성화 해제(임계값 초과 시 스토리지 늘어나면 돈 냄) &gt; 퍼블릭 액세스 가능 체크(외부에서 접속할 때 필요) &gt; 자동 백업 비활성화(용량 많이 차지함) &gt; 삭제 방지 활성</li>
</ul>
</li>
<li>외부 접속 설정<ul>
<li>해당 DB &gt; 보안에 VPC 보안 그룹 아래 default 값 눌러 이동</li>
<li>보안 그룹 내 보안 그룹 ID 눌러 보안 페이지로 이동</li>
<li>인바운드 규칙 내 하나를 체크한 후 인바운드 규칙 편집</li>
<li>규칙 추가<ul>
<li>MySQL/Aurora</li>
<li>Anywhere-IPv4</li>
</ul>
</li>
</ul>
</li>
<li>접속<ul>
<li>앤드포인트 및 포트 정보를 활용<ul>
<li><code>% mysql -h &lt;엔드포인트&gt; -P &lt;포트&gt; -u &lt;마스터 사용자 이름&gt; -p</code></li>
</ul>
</li>
<li><code>use mysql</code></li>
<li><code>select host user from user;</code></li>
</ul>
</li>
<li>중지<ul>
<li>DB 체크하고, 작업 &gt; 일시 정지</li>
</ul>
</li>
<li>다시 시작<ul>
<li>DB 내부로 들어와 작업 &gt; 시작<h2 id="sql-file">SQL file</h2>
</li>
</ul>
</li>
<li>SQL File<ul>
<li>SQL 쿼리를 모아놓은 파일</li>
<li>DB, Table을 Restore, back up하는데에 이용함<h3 id="sql-file-실행">SQL File 실행</h3>
</li>
</ul>
</li>
<li>로그인 이후<ul>
<li><code>source /path/filename.sql</code></li>
<li><code>\. /path/filename.sql</code></li>
<li><code>\. filename.sql</code></li>
<li>로그인할 때 맨 뒤에 database 를 적으면 바로 그곳에서 시작한다</li>
</ul>
</li>
<li>외부에서 바로 실행<ul>
<li><code>mysql -u username -p databaseName &lt; /path/filename.sql</code><h3 id="database-backup">Database Backup</h3>
</li>
</ul>
</li>
<li>특정 DB backup<ul>
<li><code>mysqldump -u username -p dbname &gt; backup.sql</code></li>
</ul>
</li>
<li>모든 DB backup<ul>
<li><code>mysqldump -u username -p --all-databases &gt; backup.sql</code><h3 id="database-backup-restore">Database Backup Restore</h3>
</li>
</ul>
</li>
<li>DB를 백업한 SQL File을 실행하여 그 시점으로 복구하거나 이전할 수 있다.<ul>
<li>SQL File 실행하는 방법과 동일함</li>
</ul>
</li>
<li>AWS RDS 서비스가 사용 가능한 상태에서 접속</li>
<li>zerobase로 이동</li>
<li><code>source filename.sql</code><h3 id="database-backup-table-restore">Database Backup Table Restore</h3>
</li>
<li><code>mysqldump -u username -p dbname tablename &gt; backup.sql</code><h3 id="table-schema-backup">Table Schema Backup</h3>
</li>
<li>데이터를 제외하고 테이블 생성 쿼리만 백업</li>
<li>특정 table schema backup<ul>
<li><code>mysqldump -d -u username -p dbname tablename &gt; backup.sql</code></li>
</ul>
</li>
<li>모든 table schema backup<ul>
<li><code>mysqldump -d -u username -p dbname &gt; backup.sql</code><h2 id="python-with-mysql">Python with MySQL</h2>
</li>
</ul>
</li>
<li>ds_study 가상환경에서 진행</li>
<li>테이블은 그대로 두고 내용만 삭제<ul>
<li><code>delete from police_station;</code></li>
</ul>
</li>
<li>라이브러리 설치<ul>
<li><code>pip install mysql-connector-python</code><h3 id="connect">connect</h3>
</li>
</ul>
</li>
<li>연결<pre><code>db변수 = mysql.connector.connect(
  host = &#39;주소&#39;,
  port = 3306,
  user = &#39;admin&#39;,
  password = &#39;*****&#39;,
  database = &#39;zerobase&#39;
)

</code></pre></li>
</ul>
<p>db변수 = mysql.connector.connect(
    host = &#39;localhost&#39;,
    user = &#39;root&#39;,
    password = &#39;*****&#39;,
    database = &#39;zerobase&#39;
)</p>
<pre><code>- 닫기
    - `변수.close()`
### execute
- 커서 생성
    - `커서변수 = db변수.cursor()`
    - `커서변수.execute(&lt;query&gt;);`
- SQL File 실행 코드
    - `파일변수 = open(&quot;filename.sql&quot;).read()`
    - `커서변수.execute(파일변수)`
    - 쿼리가 여러개 존재하는 경우
        - `커서변수.execute(파일변수, multi = Ture)`
### fectch all
- 조회하는 쿼리를 실행할 경우 데이터를 가지고 오는데, 그 데이터를 변수에 담는 함수
- `데이터변수 = 커서변수.fetchall()`
- 읽어올 데이터 양이 많은 경우
    - 커서 변수 선언시, `buffered = True` 옵션을 넣어준다
- 데이터변수의 데이터 타입은 튜플이 여러 개 담긴 리스트
- 데이터변수, 검색 결과를 Pandas의 DF로 변환하여 읽을 수 있다
### csv
- csv에 있는 데이터를 python으로 INSERT 하기
- commit()
    - database에 적용하기 위한 명령
- MySQL.connector execute 공식문서 참조
    - operation 옵션에 query 구문을 쓰고, params 옵션에 query 구문에서 데이터로 받을 부분을 쓰는데, 이때 paramas 옵션을 명시하지 않아도 위치상 두 번째면 paramas 값으로 받는다.
## CONSTRAINT
- 자동 생성된 CONSTRAINT 를 확인
    - `show create table tablename;`
### PPRIMARY KEY
- 테이블의 각 레코드를 식별
- 중복되지 않은 고유값을 포함
- NULL 값을 포함할 수 없음
- 테이블 당 하나의 기본키를 가짐
- 생성
    - 기존 테이블을 수정
        - `ALTER TABLE tablename ADD PRIMARY KEY (col1, col2);`
    - 새로운 테이블에 생성</code></pre><p>CREATE TABLE tablename
(
    col1 datatype NOT NULL,
    col2 datatype NOT NULL,
    ...
    CONSTRAINT constaint_name # 생략가능, 자동 생성됨
        PRIMARY KEY (co1, col2, ...)
);</p>
<pre><code>- 삭제
    - `ALTER TABLE tablename DROP PRIMARY KEY;`
### FOREIGN KEY
- 한 테이블을 다른 테이블과 연결해주는 역할이며 참조되는 테이블의 항목은 그 테이블의 기본키(혹은 단일값)
- 생성
    - 기존 테이블 수정
        - `ALTER TABLE tablename ADD FOREIGN KEY (col) REFERENCES REF_tablename(REF_col);`
    - 새로운 테이블에 생성</code></pre><p>CREATE TABLE tablename
(
    col1 datatype NOT NULL,
    col2 datatype NOT NULL,
    col3 datatype,
    col4 datatype,
    ...
    CONSTRAINT constraint_name
     PRIMARY KEY (col1, col2, ...),
    CONSTRAINT constraint_name # 생략 가능
     FOREIGN KEY (col3, col4, ...) REFERENCES REF_tablename(REF_col)
);</p>
<p>```</p>
<ul>
<li>삭제<ul>
<li><code>ALTER TABLE tablename DROP FOREIGN KEY FK_constraint;</code><h2 id="aggregate-functions">AGGREGATE Functions</h2>
</li>
</ul>
</li>
<li>여러 칼럼 혹은 테이블 전체 칼럼으로부터 하나의 결과값을 반환하는 함수</li>
<li>COUNT<ul>
<li>총 갯수를 계산해주는 함수</li>
<li><code>SELECT COUNT(col) FROM tablename WHERE condition;</code></li>
</ul>
</li>
<li>SUM<ul>
<li>합계를 계산해주는 함수</li>
<li><code>SELECT SUM(col) FROM tablename WHERE condition;</code></li>
</ul>
</li>
<li>AVG<ul>
<li>평균을 계산해주는 함수</li>
<li><code>SELECT AVG(col) FROM tablename WHERE condition;</code></li>
</ul>
</li>
<li>MIN<ul>
<li>가장 작은 값을 찾아주는 함수</li>
<li><code>SELECT MIN(col) FROM tablename WHERE condition;</code></li>
</ul>
</li>
<li>MAX<ul>
<li>가장 큰 값을 찾아주는 함수</li>
<li><code>SELECT MAX(col) FROM tablename WHERE</code></li>
</ul>
</li>
<li>FIRST<ul>
<li>첫 번째 결과값을 리턴하는 함수</li>
</ul>
</li>
<li>LAST<ul>
<li>마지막 결과값을 리턴하는 함<h2 id="조건">조건</h2>
<h3 id="group-by">GROUP BY</h3>
</li>
</ul>
</li>
<li>그룹화하여 데이터를 조회</li>
<li><code>SELECT col1, col2, ... FROM tablename WHERE condition GROUP BY col1, col2, ... ORDER BY col1, col2, ...</code></li>
<li><strong>distinct는 비슷한 효과를 내지만 ORDER BY를 사용할 수 없다</strong><h3 id="having">HAVING</h3>
</li>
<li>조건에 집계함수가 포함되는 경우 WHERE 대신 사용함</li>
<li><code>SELECT col1, col2, ... FROM tablenumber WHERE condition GROUP BY col1, col2, ... HAVING condition (Aggregate Functions) ORDER BY col1, col2, ...</code><h2 id="scalar-functions">SCALAR Functions</h2>
입력값을 기준으로 단일 값을 반환하는 함수</li>
<li>UCASE<ul>
<li>영문을 대문자로 변환하는 함수<ul>
<li><code>SELECT UCASE(string);</code></li>
</ul>
</li>
</ul>
</li>
<li>LCASE<ul>
<li>영문을 소문자로 변환하는 함수</li>
<li><code>SELECT LCASE(string);</code></li>
</ul>
</li>
<li>MID<ul>
<li>문자열 부분을 반환하는 함수</li>
<li><code>SELECT MID(string, start_position, length);</code><ul>
<li>string<ul>
<li>원본 문자열</li>
</ul>
</li>
<li>start<ul>
<li>문자열 반환 시작 위치</li>
<li>첫 글자, 1</li>
<li>마지막 글자, -1</li>
</ul>
</li>
<li>length<ul>
<li>반환할 문자열 길이</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>LENGTH<ul>
<li>문자열의 길이를 반환하는 함수</li>
<li><code>SELECT LENGTH(string);</code></li>
<li>문자열 없음<ul>
<li>0</li>
</ul>
</li>
<li>공백<ul>
<li>1</li>
</ul>
</li>
<li>NULL<ul>
<li>NULL</li>
</ul>
</li>
</ul>
</li>
<li>ROUND<ul>
<li>지정한 자리에서 숫자를 반올림하는 함수(0이 소수점 첫째 자리)</li>
<li><code>SELECT ROUND(number, deciamls_place)</code><ul>
<li>number<ul>
<li>반올림할 대상</li>
</ul>
</li>
<li>decimals<ul>
<li>반올림할 소수점 위치(option)</li>
<li>0<ul>
<li>첫 번째 소수점 위치</li>
</ul>
</li>
<li>-1<ul>
<li>일단위 위치</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>NOW<ul>
<li>현재 날짜 및 시간을 반환하는 함수</li>
<li><code>SELECT NOW()</code>;</li>
</ul>
</li>
<li>FORMAT<ul>
<li>숫자를 천단위 콤마가 있는 형식(문자열)으로 반환하는 함수</li>
<li><code>SELECT FORMAT(number, decimal_place);</code><ul>
<li>number<ul>
<li>포맷을 적용할 문자 혹은 숫자</li>
</ul>
</li>
<li>decimals<ul>
<li>표시할 소수점 위치</li>
<li>잘리면 자동으로 반올림하고</li>
<li>원래보다 더 있으면 0으로 채운다</li>
<li>0<ul>
<li>소수점 표시 X<h2 id="sql-subquery">SQL Subquery</h2>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>하나의 SQL문 안에 포함되어 있는 또 다른 SQL문</li>
<li>메인쿼리가 서브쿼리를 포함하는 종속적인 관계<ul>
<li>서브쿼리는 메인쿼리의 칼럼 사용 가능</li>
<li>메인쿼리는 서브쿼리의 칼럼 사용 불가</li>
<li>서브쿼리는 괄호로 묶어서 사용</li>
<li>단일 행 혹은 복수 행 비교 연산자와 함께 사용 가능</li>
<li>서브쿼리에서는 order by 사용불가</li>
</ul>
</li>
<li>Scalar Subquery<ul>
<li>SELECT 절에서 사용된다</li>
<li>결과는 하나의 칼럼이어야 한다</li>
<li><code>SELECT col1, (SELECT col2 FROM table2 WHERE condition) FROM table1 WHERE condition;</code></li>
</ul>
</li>
<li>Inline view<ul>
<li>FROM 절에서 사용되며, 메인쿼리에서는 인라인 뷰에서 조회한 칼럼만 사용 가능</li>
<li>내가 필요한 값들을 모아둔 결과를 inline view로 활용하는 것</li>
<li><code>SELECT a.col, b.col FROM tableA a, (SELECT col1, col2 from tableB) b WHERE condition;</code></li>
</ul>
</li>
<li>Nested Subquery<ul>
<li>WHERE 절에서 사용</li>
<li>Single Row<ul>
<li>하나의 행을 검색하는 서브쿼리</li>
<li>서브쿼리가 비교연산자와 사용되는 경우, 검색결과는 한 개의 결과값을 가져야 한다</li>
<li><code>SELECT col1 FROM tableA WHERE col1 = (SELECT col2 FROM tableB WHERE condition) ORDER BY col1;</code></li>
</ul>
</li>
<li>Multiple Row<ul>
<li>하나 이상의 행을 검색하는 서브쿼리</li>
<li>IN<ul>
<li>서브쿼리 결과 중에 포함될 때</li>
<li><code>SELECT col1 FROM tableA WHERE col IN (SELECT col2 FROM tableB WHERE condition) ORDER BY col1;</code></li>
<li>JOIN을 써도 괜찮고, 효율도 JOIN이 더 좋음</li>
</ul>
</li>
<li>EXISTS<ul>
<li>서브쿼리 결과에 값이 있으면 반환</li>
<li><code>SELECT col1 FROM tableA WHERE EXISTS (SELECT col2 FROM tableB WHERE condition) ORDER BY col1;</code></li>
</ul>
</li>
<li>ANY<ul>
<li>서브쿼리 결과 중에 최소한 하나라도 만족하면(비교연산자 사용)</li>
<li><code>SELECT col1 FROM tableA WHERE col1 = ANY (SELECT col2 FROM tableB WHERE condition) ORDER BY col1</code></li>
</ul>
</li>
<li>ALL<ul>
<li>서브쿼리 결과를 모두 만족하면(비교연산자 사용)</li>
<li><code>SELECT col1 FROM tableA WHERE col1 = ALL (SELECT col2 FROM tableB WHERE condition) ORDER BY col1</code></li>
</ul>
</li>
</ul>
</li>
<li>Multiple Column<ul>
<li>하나 이상의 열을 검색하는 서브쿼리</li>
<li>서브쿼리 내에 메인쿼리 칼럼이 같이 사용되는 경우</li>
<li><code>SELECT col1 FROM tableA a WHERE (a.col1, a.col2, ...) IN (SELECT b.col1, b.col2, ... FROM tableB b WHERE a.col1 = b.col2) ORDER BY col1;</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="느낀점">느낀점</h2>
<p>SQL 코딩 테스트 연습은 많이 했지만, 직접 DB를 만들고 table을 만들어 내용을 정리하고, 합하고, 그것을 또 AWS에 올리는 것은 처음 해봤다. 처음에는 따라하는것이 벅차서 내용을 이해 못하다가, sql 백업 파일에서 오류가 나면서 갑자기 많은 것이 이해되었다.
잘 안되어야 머리를 굴리는 이유는 무엇일까. 그래도 지금까지 한 공부 중에 가장 재미있다. 직관적이고, 실습 과정이 안전하다고 느껴진다.</p>
<p><strong>이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[007. 데이터 취업 스쿨 스터디 노트_7주차_EDA, 웹크롤링, 파이썬 프로그래밍_2]]></title>
            <link>https://velog.io/@julia-jh319/007.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B87%EC%A3%BC%EC%B0%A8EDA-%EC%9B%B9%ED%81%AC%EB%A1%A4%EB%A7%81-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D2</link>
            <guid>https://velog.io/@julia-jh319/007.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B87%EC%A3%BC%EC%B0%A8EDA-%EC%9B%B9%ED%81%AC%EB%A1%A4%EB%A7%81-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D2</guid>
            <pubDate>Sat, 25 May 2024 04:09:21 GMT</pubDate>
            <description><![CDATA[<h1 id="7주차">7주차</h1>
<h2 id="수강한-분량">수강한 분량</h2>
<p>EDA, 웹크롤링, 파이썬 프로그래밍의 일부분인 웹데이터, 유가분석을 정리했다.</p>
<h1 id="각-강의별-학습한-핵심-내용-정리">각 강의별 학습한 핵심 내용 정리</h1>
<h2 id="웹-데이터-분석">웹 데이터 분석</h2>
<pre><code>cd DS_study/ds_study/WebData
conda activate ds_study
code .</code></pre><p>ctrl + shfit + P</p>
<h3 id="beautiful-soup">Beautiful Soup</h3>
<ul>
<li>tag로 이루어진 문서를 해석하는 python 라이브러리</li>
<li><code>from ba4 import BeautifulSoup</code><ul>
<li>open()<ul>
<li>파일명과 함께 읽기(r) / 쓰기(w) 속성 지정</li>
<li><code>page = open(&quot;파일주소.html&quot;, &#39;r&#39;).read()</code></li>
</ul>
</li>
<li>html.parser<ul>
<li>Beutiful Soup의 html을 읽는 엔진 중 하나</li>
<li><code>soup = BeautifulSoup(page, &quot;html.parser&#39;)</code><ul>
<li>들여쓰기가 잘 안되어있고, 읽기 불편함</li>
</ul>
</li>
</ul>
</li>
<li>prettify()<ul>
<li>html 출력, 들여쓰기를 이쁘게 만들어 주는 기능</li>
<li><code>print(soup.prettify())</code><h4 id="html-기초">html 기초</h4>
</li>
</ul>
</li>
</ul>
</li>
<li><ol start="3">
<li>test_first.html 파일 활용하여 실습 진행</li>
</ol>
</li>
<li>html 언어<ul>
<li>브라우저를 통해 예쁜 화면을 제공함</li>
<li>tag로 이루어져 있음<ul>
<li>html<ul>
<li>웹 페이지를 표현</li>
</ul>
</li>
<li>head<ul>
<li>눈에 보이지 않지만 문서에 필요한 헤더 정보 보관</li>
</ul>
</li>
<li>body<ul>
<li>눈에 보이는 정보를 보관</li>
<li><h2 id="div">div</h2>
</li>
<li>p<ul>
<li>문단</li>
</ul>
</li>
<li>class<ul>
<li>구분 속성</li>
</ul>
</li>
<li>id<ul>
<li>구분 속성</li>
</ul>
</li>
<li><h2 id="a">a</h2>
</li>
<li>href<ul>
<li>주소창</li>
</ul>
</li>
<li>target<ul>
<li><code>_blink</code><ul>
<li>새창</li>
</ul>
</li>
</ul>
</li>
<li>b<ul>
<li>굵게</li>
</ul>
</li>
<li>i<ul>
<li>기울여서</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>특정 태그가 보고 싶을 때<ul>
<li><code>soup.body</code></li>
<li><code>soup[&#39;body&#39;]</code></li>
<li><code>soup.find(&#39;p&#39;)</code><ul>
<li>1개만 찾아줌</li>
</ul>
</li>
<li><code>soup.find_all(&#39;p&#39;)</code><ul>
<li>지정된 태그 모두를 찾아 리스트 형태로 반환</li>
</ul>
</li>
<li>조건을 좁히는 방법으로 class, id를 태그와 함께 추가할 수 있다<ul>
<li><code>soup.find_all(class_=&#39;클래스명&#39;)</code></li>
<li><code>soup.find_all({&#39;class&#39; : &#39;클래스명&#39;})</code><ul>
<li>특정 클래스를 찾는 방법</li>
</ul>
</li>
<li><code>soup.find_all(id_=&#39;아이디명&#39;)</code><ul>
<li>특정 id로 찾는 방법</li>
</ul>
</li>
</ul>
</li>
<li>담아져 있는 내용 출력<ul>
<li><code>soup.find(&#39;p&#39;).text</code><ul>
<li>출력문자가 나옴</li>
<li>공백을 지우기 위해 끝에 <code>.strip()</code>을 붙이면 됨</li>
</ul>
</li>
<li><code>soup.find(&#39;p&#39;).string</code></li>
<li><code>soup.find_all(&#39;p&#39;).get_test()</code><ul>
<li>p로 쌓여있는 실제 출력 글자 가져오는 함수</li>
</ul>
</li>
<li><code>soup.find_all(&#39;a&#39;)[0].get(&#39;href&#39;)</code><ul>
<li>a태그의 첫 번째 요소의 주소값을 가져오기</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>a 태그<ul>
<li>링크</li>
<li><code>&lt;a href = &quot;주소&quot; id = &quot;아이디값&quot;&gt;출력글자&lt;/a&gt;</code><ul>
<li><code>soup.find_all(&#39;a&#39;).[&#39;href&#39;].string</code><ul>
<li>a 태그의 href 속성의 글자를 가져오는 방법</li>
<li>출력 글자가 나옴<h3 id="크롬-개발자-도구">크롬 개발자 도구</h3>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>웹데이터 검출하고 싶은데 html을 잘 모를 때 활용하는 도구</li>
<li>크롬 설정 &gt; 도구 더보기 &gt; 개발자 도구<ul>
<li>필요 데이터 부분 선택하면, 어느 부분인지 태그가 보임</li>
<li><code>&lt;span class=&#39;value&gt;</code>를 기억해야 한다</li>
</ul>
</li>
<li>웹 주소에 접근할 때 필요한 라이브러리<ul>
<li><code>from urllib.request import urlopen</code></li>
<li><code>urlopen(&#39;url주소&#39;)</code>를 beautifulsoup으로 해석하기</li>
<li><code>ulropen(&#39;url주소&#39;).status</code><ul>
<li>응답 상황을 알 수 있다, http 상태코드 반환</li>
<li>200<ul>
<li>정상</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>프롬프트에서 특정 라이브러리 잘 인스톨되었는지 확인<ul>
<li><code>pip list | findstr 라이브러리명</code></li>
</ul>
</li>
<li><strong>requests 라이브러리 깔았는데 임포트되지 않아 오류 내용을 보니 chardet이 없다고 해서 깔고 마저 하니 되었다.</strong> </li>
<li>requests 라이브러리와 urllib.requests.Request는 비슷한 역할을 한다<ul>
<li><code>requests.get()</code></li>
<li><code>requests.post()</code></li>
</ul>
</li>
<li>무언가를 찾는 함수<ul>
<li><code>find</code> 와 비슷한 것 <code>select one</code></li>
<li><code>find_all</code> 와 비슷한 것 <code>select</code></li>
<li>select, select one 의 문법<ul>
<li><code>~~.select(&quot;#아이디명 &gt; li&quot;)</code></li>
<li>class면 . 을 활용</li>
<li>id 면 # 을 활용</li>
<li>만약 띄어쓰기가 존재하면 속성이 여러 개, .으로 이어주기</li>
<li>상, 하위 이동이 간결함<h3 id="위키백과-문서-정보-가져오기">위키백과 문서 정보 가져오기</h3>
</li>
</ul>
</li>
</ul>
</li>
<li>한글로만 이루어진 페이지, 여명의 눈동자 위키백과 웹페이지 활용</li>
<li>한글로 되어있는 웹페이지 주소는 옮길 경우 문자의 나열이 바뀐다.<pre><code>import urllib
from urllib.request import urlopen, Request
</code></pre></li>
</ul>
<p>html = &#39;<a href="http://ko.wikipedia.org/wiki/%7Bsearch_words%7D&#39;">http://ko.wikipedia.org/wiki/{search_words}&#39;</a>
req = Request(html.format(search_words = urllib.parse.quote(&#39;여명의_눈동자&#39;))) # 글자를 URL로 인코딩</p>
<p>response = urlopen(req)</p>
<p>soup = BeautifulSoup(response, &#39;html.parser&#39;)</p>
<p>soup.find_all(&#39;ul&#39;)[15],text.strip().replace(&#39;\xa0&#39;, &#39;&#39;).replace(&#39;\n&#39;, &#39;&#39;)</p>
<h1 id="바꾸고-싶은-문자를-찾아-replace함수에-넣고">바꾸고 싶은 문자를 찾아 replace함수에 넣고</h1>
<h1 id="찾고-싶은-부분의-순서를-찾아-15-자리에-넣는다">찾고 싶은 부분의 순서를 찾아 15 자리에 넣는다.</h1>
<pre><code>#### list 데이터형
- 리스트 변수를 선언할 때 생긴 메모리를 가리키는 주소가 복사됨
- 반복문, 조건문에 적용하는 것이 편함
- 리스트 내부에 리스트를 가질 수 있다
- `isinstance(변수명, list)`
    - 자료형이 list인지 확인 가능
### 시카고 맛집 분석
#### 시카고 맛집 메인페이지 분석</code></pre><p>from bs4 import BeautifulSoup</p>
<p>from urllib.request import Request, urlopen</p>
<h1 id="메인페이지와-서브페이지-분석을-따로-해야할-수-있기-때문에-주소를-두-개로-분리">메인페이지와 서브페이지 분석을 따로 해야할 수 있기 때문에 주소를 두 개로 분리</h1>
<p>url_base = &#39;<a href="https://www.chicagomag.com&#39;">https://www.chicagomag.com&#39;</a>
url_sub = &#39;/Chicago-Magazine/November-2012/Best-Sandwiches-Chicago/&#39;
url = url_base + url_sub</p>
<h1 id="http-403은-서버에서-유저가-문제가-있다고-하는-것">http 403은 서버에서 유저가 문제가 있다고 하는 것</h1>
<h1 id=""></h1>
<p>req = Request(url, headers = {&#39;User-Agent&#39;: &#39;Chrome&#39;})
html = urlopen(req).read()
soup = BeautifulSoup(html, &#39;html.parser&#39;)</p>
<p>soup.prettify()</p>
<p>soup.find_all(&#39;div&#39;, <em>class = &#39;sammy&#39;), len(soup.find_all(&#39;div&#39;, class</em> = &#39;sammy&#39;)) # 갯수확인</p>
<h1 id="select로도-가능">select로도 가능</h1>
<p>soup.select(&quot;.sammy&quot;), len(soup.select(&quot;.sammy&quot;))</p>
<h1 id="전체-코드-긁어오기-위한-샘플-코드-테스트-중">전체 코드 긁어오기 위한 샘플 코드 테스트 중...</h1>
<p>tmp_one = soup.find_all(&#39;div&#39;, &#39;sammy&#39;)[0]
type(tmp_one)</p>
<h1 id="위-값이-bs4elementtag-이면-bs4-요소이므로-bs4-함수를-적용할-수-있다">위 값이 bs4.element.Tag 이면 bs4 요소이므로 bs4 함수를 적용할 수 있다</h1>
<p>tmp_one.find(class_ = &#39;sammyRank&#39;).get_text()
tmp_one.find(&#39;div&#39;, {&#39;class&#39; : &#39;sammyRank&#39;}).get_text()
tmp_one.select_one(&#39;.sammylisiting&#39;).text()
tmp_one.find(&quot;a&quot;)[&#39;href&#39;]
tmp_one.select_one(&quot;a&quot;).get(&#39;href&#39;)</p>
<pre><code>- 크롬 개발자 도구 내 network 탭을 살펴보면 요청과 그에 상응하는 응답이 기록된다
    - Request Headers 토글을 열어보면 user-agent 정보가 있다. 그곳에 나온 정보를 활용하는게 정석이나, 간략하게 Chrome 정도로 사용해도 좋다.
    - req.status 를 보면 200은 응답을 제대로 받았다, 403번은 별로인 상태
- fake-useragent 라이브러리 
    - from fake_useragent import UserAgent
    - UserAgent().ie
        - user-agent에 들어갈 값을 랜덤으로 만들어준다
- type(찾은 요소) = bs4.element.Tag 이면, find 명령을 또 활용할 수 있다는 의미
- 연결되는 홈페이지 주소가 상대경로이기 때문에, 주소를 상위 페이지와 하위 페이지로 구분해 분석하는 것이 용이하다
- re 모듈</code></pre><p>import re</p>
<h1 id="n-혹은-rn이-보이면-분리해라">\n 혹은 \r\n이 보이면 분리해라</h1>
<p>re.split(()&#39;\n|\r\n&#39;), 문자열)</p>
<pre><code></code></pre><p>from urllib.parse import urljoin</p>
<p>url_base = &#39;<a href="https://www.chicagomag.com&#39;">https://www.chicagomag.com&#39;</a></p>
<p>rank = []
main_menu = []
cafe_name []
url_add = []</p>
<p>list_soup = soup.find_all(&#39;div&#39;, &#39;sammy&#39;)</p>
<p>for item in list_soup:
    rank.append(item.find(class_= &#39;sammyRank&#39;).get_text())
    tmp_string = item.find(class_= &#39;sammyListing&#39;).get_text()
    main_menu.append(re.split((&#39;\n|\r\n&#39;), tmp_string)[0])
    cafe_menu.append(re.split((&#39;\n|\r\n&#39;), tmp_string)[1])
    url_add.append(urljoin(url_base, item.find(&#39;a&#39;)[&#39;href&#39;]))
    # 두 번째 인자(주소)가 절대 주소라면 그냥 사용하고, 상대 주소라면 첫 번째 인자(주소)를 붙여서 사용하라</p>
<h1 id="확인용">확인용</h1>
<p>len(rank), len(main_manu), len(cafe_name), len(url_add)
rank[:5], ...</p>
<h1 id="데이터-정리">데이터 정리</h1>
<p>data = {
    &quot;Rank&quot;: rank,
    &quot;Menu&quot;: main_menu,
    &quot;Cafe&quot;: cafe_name,
    &quot;URL&quot;: url_add
}</p>
<p>df = pd.DataFrame(data)</p>
<p>df = pd.Dataframe(data, columns = [&#39;Rank&#39;, &#39;Cafe&#39;, &#39;Menu&#39;, &#39;URL])
df.to_csv(&quot;주소/이름.csv&quot;, sep = &quot;,&quot;, encoding = &#39;utf-8&#39;)</p>
<pre><code>#### 시카고 맛집 하위 페이지 분석
-  Regular Expession_기초
    - .x
        - 임의의 한 문자를 표현
    - x+
        - x가 1번 이상 반복
    - x?
        - x가 존재하거나 존재하지 않는다
    - x*
        - x가 0번 이상 반복
    - x|y
        - x또는 y를 찾는다</code></pre><p>from bs4 import BeautifulSoup
from urllib.request import urlopen</p>
<p>import pandas as pd</p>
<p>df = pd.read_csv(&#39;주소/이.csv&#39;, index_col = 0)</p>
<p>df[&#39;URL&#39;][0]</p>
<p>req = Request(df[&quot;URL&quot;][0], headers = {&#39;User-Agent&#39;: &#39;Chrome&#39;})
html = urlopen(req).read()</p>
<p>soup_tmp = BeautifulSoup(html, &#39;html.parser&#39;)</p>
<p>print(soup_tmp.find(&#39;p&#39;, &#39;addy&#39;))</p>
<h1 id="가격과-주소가-하나의-태그에-들어있다">가격과 주소가 하나의 태그에 들어있다...!</h1>
<p>price_tmp = soup_tmp.find(&#39;p&#39;, &#39;addy&#39;).get_text()</p>
<p>price_tmp = re.split(&quot;.,&quot;, price_tmp)[0]</p>
<h1 id="끝에-group을-해주어야-값만-나온다">끝에 .group()을 해주어야 값만 나온다</h1>
<p>tmp = re.search(&quot;$\d+.(\d+)?&quot;, price_tmp).group()</p>
<h1 id="가-반드시-있어야-하고-숫자가-여러-개-있을-수-있고-이-반드시-와야-하고-숫자-여러개의-것이-있을-수도-있고-없을-수도-있다">$가 반드시 있어야 하고, 숫자가 여러 개 있을 수 있고, .이 반드시 와야 하고, (숫자 여러개)의 것이 있을 수도 있고, 없을 수도 있다.</h1>
<h1 id="가격과-띄어쓰기-포함한-것의-길이-다음은-주소가-나타남">가격과 띄어쓰기 포함한 것의 길이 다음은 주소가 나타남</h1>
<p>price_tmp[len(tmp) + 2:]</p>
<pre><code></code></pre><p>price = []
address = []</p>
<h1 id="코드-작동-유무-확인-위해-세-번만-돌리기">코드 작동 유무 확인 위해 세 번만 돌리기</h1>
<p>for n in df.index[:3]:
    # html = urlopen(df[&#39;URL&#39;][n])</p>
<pre><code>req = request(df[&#39;URL&#39;][n], headers = {&quot;User-Agent&quot;: &quot;Mozilla/5.0&quot;})
html = urlopen(req).read()

soup_tmp = BeautifulSoup(html, &#39;lxml&#39;)

gettings = soup_tml.find(&#39;p&#39;, &#39;addy&#39;).get_text()

price_tmp = re.split(&#39;.,&#39;, gettings)[0]
tmp = re.search(&quot;\$\d+\.(\d+)?&quot;, price_tmp).group()

price.append(tmp)
address.append(price_tmp[len(tmp) + 2 :])

print(n)</code></pre><pre><code>- python스러운 문법
    - list를 고대로 사용하기
        - 여러 컬럼을 for문 안에서 사용하기 어려움
    - iterrows() 함수를 활용</code></pre><p>for idx, row in df.iterrows():
    print(row[&#39;URL&#39;])</p>
<pre><code>
- TQDM
    - 라이브러리
    - 코드 실행 중에 프로그래스 바가 보여짐
    - 오류 없이 제대로 모두 적용되었는지 확인하는데 활용하는 것</code></pre><p>from tqdm import tqdm
price = []
address = []</p>
<h1 id="코드-작동-유무-확인-위해-세-번만-돌리기-1">코드 작동 유무 확인 위해 세 번만 돌리기</h1>
<p>for idx, row in tqdm(df.index[:3].iterrows()):
    # html = urlopen(df[&#39;URL&#39;][n])</p>
<pre><code>req = request(row[&#39;URL&#39;], headers = {&quot;User-Agent&quot;: &quot;Mozilla/5.0&quot;})
html = urlopen(req).read()
# 홈페이지 수정중에 html parser로 불가능할 수 있음
# conda 환경 사용 중에 lxml 환경이 없는 경우가 있다. 깔아주면 됨
soup_tmp = BeautifulSoup(html, &#39;lxml&#39;)

gettings = soup_tml.find(&#39;p&#39;, &#39;addy&#39;).get_text()

price_tmp = re.split(&#39;.,&#39;, gettings)[0]
tmp = re.search(&quot;\$\d+\.(\d+)?&quot;, price_tmp).group()

price.append(tmp)
address.append(price_tmp[len(tmp) + 2 :])

print(n)</code></pre><pre><code></code></pre><p>df[&#39;Price&#39;] = price
df[&#39;Address&#39;] = address</p>
<h1 id="price-address를-위해-link-데이터가-필요했던-것이므로-최종적으로는-삭제">price, address를 위해 link 데이터가 필요했던 것이므로 최종적으로는 삭제</h1>
<p>df = df.loc[:, [&#39;Rank&#39;, &#39;Cafe&#39;, &#39;Menu&#39;, &#39;Price&#39;, &#39;Address&#39;]]
df.set_index(&#39;Rank&#39;, inplace = True)</p>
<p>df.to_csv(&#39;&#39;, sep = &#39;,&#39;, encoding = &#39;utf-8&#39;)</p>
<p>pd.read_csv(&#39;&#39;, index_col = 0)</p>
<pre><code>#### 시카고 맛집 데이터 지도 시각화</code></pre><p>import folium
import pandas as pd
import googlemaps
import numpy as np
from tqdm import tqdm</p>
<h1 id="주소-체크">주소 체크</h1>
<p>df_ pd.read_csv(&#39;&#39;, index_col = 0)</p>
<p>gmaps_key = &quot;geocoding api key geocoding api key&quot;
gmaps = googlemaps.Client(key = gmaps_key)</p>
<p>lat = []
lng = []</p>
<p>for idx, row in tqdm(df.iterrows()):
    if not row[&quot;Address&quot;] == &quot;Multiple location&quot;:
        target_name = row[&quot;Address&quot;] + &quot;, &quot; + &quot;Chicago&quot;
        gmaps_output = gmaps.geocode(target_name)
        location_output = gmaps_output[0].get(&#39;geometry&#39;)
        lat.append(location_output[&quot;location&quot;][&quot;lat&quot;])
        lng.append(location_output[&quot;location&quot;][&quot;lng&quot;])</p>
<pre><code>else:
    lat.append(np.nan)
    lng.append(np.nan)</code></pre><p>df[&quot;lat&quot;] = lat
df[&quot;lng&quot;] = lng</p>
<p>df.head()</p>
<p>mapping = folium.Map(location = [41.8781136, -87.6297982], zoom_start = 11)</p>
<p>mapping</p>
<p>for idx, row in df.iterrows():
    if not row[&quot;Address&quot;] == &quot;Multiple location&quot;:
        folium.Marker([row[&quot;lat&quot;],
        row[&quot;lng&quot;]],
        popup = row[&quot;Cafe&quot;],
        tooltip = row[&quot;Menu&quot;],
        icon = folium.Icon(
            Icon = &quot;coffee&quot;,
            prefix = &quot;fa&quot;
            )
        ).add_to(mapping)</p>
<p>mapping</p>
<pre><code>
## 유가 분석
### selenium
#### 설치
- **최근 버전의 셀레니움은 크롬드라이버를 다운로드 받으실 필요가 없게 바뀌었습니다! 크롬드라이버는 받지 마시고, 코드 작성시driver = webdriver.Chrome()**
- Beautiful Soup으로만 해결할 수 없는 것
    - 접근할 웹 주소를 알 수 없을 때
    - 자바스크립트를 사용하는 웹페이지
    - 웹 브라우저로 접근하지 않으면 안될 때
- 웹 브라우저를 원격 조작하는 도구
- 자동으로 URL을 열고 클릭 등이 가능
- 스크롤, 문자의 입력, 화면 캡처 등
- Python 모듈 설치, 크롬드라이버 설치</code></pre><p>from selenium import webdriver</p>
<h1 id="더이상-드라이버를-다운받지-않아도-됨">더이상 드라이버를 다운받지 않아도 됨</h1>
<p>driver = webdriver.Chrome()</p>
<h1 id="적은-주소의-새-창-키기">적은 주소의 새 창 키기</h1>
<p>driver.get(&quot;<a href="https://www.naver.com&quot;">https://www.naver.com&quot;</a>)</p>
<h1 id="꺼짐">꺼짐</h1>
<p>driver.quit()</p>
<pre><code>#### 기초</code></pre><p>from selenium import webdriver
from selenium import By</p>
<h1 id="더이상-드라이버를-다운받지-않아도-됨-1">더이상 드라이버를 다운받지 않아도 됨</h1>
<p>driver = webdriver.Chrome()</p>
<h1 id="적은-주소의-새-창-키기-1">적은 주소의 새 창 키기</h1>
<p>driver.get(&quot;<a href="https://www.pinkwink.kr/&quot;">https://www.pinkwink.kr/&quot;</a>)</p>
<h1 id="스크롤-가능한-높이-가져오기">스크롤 가능한 높이 가져오기</h1>
<p>last_height = driver.execute_script(&quot;return document.body.scrollHeight&quot;)
last_height</p>
<h1 id="화면-스크롤-하단-이동">화면 스크롤 하단 이동</h1>
<p>driver.execute_script(&quot;window.scrollTo(0, document.body.scrollHeight);&quot;))</p>
<h1 id="xpath-카피해온-곳-까지-스크롤">Xpath 카피해온 곳 까지 스크롤</h1>
<p>from selenium.webdriver import ActionChains</p>
<p>some_tag = driver.find_element(By.XPATH, &#39;//*[@id=&quot;paging&quot;]/ul&#39;)</p>
<p>action = ActionChains(driver)
action.move_to_element(some_tag).perform()</p>
<h1 id="id로-찾아-입력-창에-글자-넣기">id로 찾아 입력 창에 글자 넣기</h1>
<p>some_tag = driver.find_element(By.ID, &#39;gsc-i-idl&#39;)
some_tag.send_keys(&#39;data science&#39;)</p>
<h1 id="버튼-클릭하는-코드-실행">버튼 클릭하는 코드 실행</h1>
<p>xpath = &#39;&#39;&#39;//*[@id=&quot;___gcse_0&quot;]/div/form/table/tbody/tr/td2/buttion&#39;&#39;&#39;
some_tag = driiver.find_element(By.XPATH, xpath).clink()</p>
<h1 id="현재-화면-html-코드가져오기">현재 화면 html 코드가져오기</h1>
<p>from bs4 import BeutifulSoup</p>
<p>req = driver.page_source
soup = BeautifulSoup(req, &#39;html.parser&#39;)</p>
<p>result = soup.find_all(&#39;div&#39;, &#39;gsc-webResult gsc-result&#39;)
result[0]</p>
<pre><code>##### 기본 동작
- `get()` 함수
    - 접근하고 싶은 주소 지정
- `execute_script(&#39;&#39;)`
    -  자바스크립트 코드를 실행
- 화면 페이지를 지정히는 지점의 xpath를 찾기
    - Copy &gt; Copy Xpath
- 보이는 화면에 내가 원하는 데이터가 있어야 에러가 안남
    - 한 화면에 많은 정보가 담겨있는 것이 좋음
- 화면 최대 크기 설정
    - `driver.maximize_window()`
- 화면 최소 크기 설정
    - `driver.minimize_window()`
- 화면 크기 설정
    - `driver.set_window_size(600, 600)`
- 새로 고침
    - `driver.refresh()`
- 뒤로가기
    - `driver.back()`
- 앞으로가기
    - `driver.forward()`
- 요소 찾기
    - `from selenium.webdriver.common.by import By`
    - `driver.find_element(by=BY.NAME, value=&quot;태그값&quot;)`
- 클릭
    - `driver.find_element(BY.CSS_SELECTOR, &#39;css값 복사해오기&#39;)`
- CSS
    - `#`
        - id
    - `&gt;`
        - 하위
    - `.~~~`
        - class 이름
    - `(n)`
        - n번째 요소
- 새로운 탭 생성
    - `driver.execute_script(&#39;window.open(&quot;주소&quot;)&#39;)`
        - 공란이면 `about:blank` 창이 뜸
- 탭 이동
    - `driver.switch_to.window(driver.window_handles[1])`
    - n번째 창으로 이동
- 탭 닫기
    - `driver.close()`
        - 드라이버가 가리키고 있는 것이 이미 닫혀있을 경우 에러
- 전체 종료
    - `driver.quit()`
##### 화면 스크롤 &amp; 검색어 입력
- 스크롤 가능한 높이(길이)
    - `driver.execte_script(&#39;return document.body.scrollHeight&#39;)`
- 화면 스크롤 하단 이동
    - `driver.execute_script(&#39;window.scrollTo(0, document.body.scrollHeight);&#39;)`
- 현재 보이는 화면 스크린샷 저장
    - `driver.save_screenshot(&#39;./파일이름.확장자&#39;)`
        - `./`
            - 현재 위치
        - 저장위치/파일이름.확장자
- 화면 스크롤 상단 이동
    - `driver.execute_script(&#39;window.scrollTo(0, 0);&#39;)`
- 특정 태그 지점까지 스크롤 이동</code></pre><p>from selenium.webdriver import ActionChains</p>
<p>some_tag = driver.find_element(By.CSS_SELEECTOR, &#39;태그 이름&#39;)
action = ActionChans(driver)
action.move_to_element(some_tag).perform()</p>
<pre><code>##### 검색어 입력(1)
- XPATH
    - `//`
        - 최상위
    - `*`
        - 자손 태그
        - 내 아래에 있는 모든 자손
    - `/`
        - 자식 태그
        - 내 바로 아래 있는 자식
    - `div[n]`
        - div 태그 중에서 n번째 태그
    - Xpath를 감싸는 것은 작은 따옴표로 하는 것이 내부의 큰 따옴표와 겹치지 않아 에러 방지에 좋다
</code></pre><p>from selenium import webdriver
from selenium.webdriver.common.by import By</p>
<h1 id="더이상-드라이버를-다운받지-않아도-됨-2">더이상 드라이버를 다운받지 않아도 됨</h1>
<p>driver = webdriver.Chrome()</p>
<h1 id="적은-주소의-새-창-키기-2">적은 주소의 새 창 키기</h1>
<p>driver.get(&quot;<a href="https://www.naver.com/&quot;">https://www.naver.com/&quot;</a>)</p>
<h1 id="css_selector">css_selector</h1>
<h1 id="검색어-입력">검색어 입력</h1>
<p>keyword = driver.find_element(By.CSS_SELECTOR, &#39;#query&#39;)
keyword.send_keys(&#39;파이썬&#39;)</p>
<h1 id="버튼-클릭">버튼 클릭</h1>
<p>search_btn = driver.find_element(by.CSS_SELECTOR, &#39;#search_btn&#39;)
search_btn.click()</p>
<h1 id="검색어-지우기">검색어 지우기</h1>
<p>keyword = driver.find_element(By.CSS_SELECTOR, &#39;#query&#39;)
keyword.clear()
keyword.send_keys(&#39;딥러닝&#39;)</p>
<h1 id="xpath">XPATH</h1>
<h1 id="검색어-입력-1">검색어 입력</h1>
<p>keyword = driver.find_element(By.XPATH, &#39;//*[@id=&quot;query&quot;]&#39;)
keyword.send_keys(&#39;파이썬&#39;)</p>
<h1 id="버튼-클릭-1">버튼 클릭</h1>
<p>search_btn = driver.find_element(by.XPATH, &#39;//*[@id=&quot;search_btn&quot;]&#39;)
search_btn.click()</p>
<h1 id="검색어-지우기-1">검색어 지우기</h1>
<p>keyword = driver.find_element(By.XPATH, &#39;//*[@id=&quot;query&quot;]&#39;)
keyword.clear()
keyword.send_keys(&#39;딥러닝&#39;)</p>
<pre><code>##### 검색어 입력(2)</code></pre><p>from selenium import webdriver
from selenium.webdriver.common.by import By</p>
<p>driver = webdriver.chrome()
driver.get(&#39;<a href="http://pinkwink.kr&#39;">http://pinkwink.kr&#39;</a>)</p>
<h1 id="돋보기-버튼-선택">돋보기 버튼 선택</h1>
<p>driver.find_element(BY.CSS_SELECTOR, &#39;#header &gt; div.search&#39;).click()</p>
<h1 id="처음부터-선택이-잘-안되고-직접-눌러야-search-on이라는-이름으로-바뀜">처음부터 선택이 잘 안되고, 직접 눌러야 search on이라는 이름으로 바뀜</h1>
<h1 id="아래의-내용으로-진행">아래의 내용으로 진행</h1>
<p>from selenium.webdriver import ActionChains</p>
<p>search_tag = driver.find_element(By.CSS_SELECTOR, &#39;.search&#39;)
action = ActionChains(driver)
action.click(search_tag)
action.perform()</p>
<h1 id="검색어-입력-2">검색어 입력</h1>
<p>driver.find_element(BY.CSS_SELECTOR, &#39;#header &gt; div.search &gt; input[type=text]&#39;).send_keys(&#39;딥러닝&#39;)</p>
<h1 id="검색-버튼-클릭">검색 버튼 클릭</h1>
<p>driver.find_element(BY.CSS_SELECTOR, &#39;#header &gt; div.search.on &gt; button&#39;).click()</p>
<pre><code>##### Selenium과 BeautifulSoup 함께 사용하기</code></pre><h1 id="현재-화면-html-코드-가져오기">현재 화면 html 코드 가져오기</h1>
<p>driver.page_source</p>
<p>from bs4 import Beautifulopti</p>
<p>req = driver.page_source
soup = BeautifulSoup(req, &#39;html.parser&#39;)</p>
<p>soup.select(&#39;.post-item&#39;)</p>
<p>contents = soup.select(&#39;.post-item&#39;)
len(contents)</p>
<pre><code>### 주유소 가격
#### 데이터 얻어오기
- 대한민국 주유 가격을 알아보는 사이트: https://www.opinet.co.kr/user/main/mainView.dos
    - 싼 주유소 찾기 &gt; 지역별
        - https://www.opinet.co.kr/searRgSelect.do
        - 사이트 구조 확인하기
            - 지역 정보를 선택
                - 웹페이지 주소도 안 바뀌고, HTML 소스에서 원하는 정보를 얻기도 쉽지 않다
            - 검색한 내용의 하단에 엑셀 저장이 바로 존재함
        - 목표 데이터
            - 브랜드
            - 가격
            - 셀프 주요 여부
            - 위치

- 문제 발생
    1. 해당 URL로 한 번에 접근이 안 됨
    2. 메인 페이지로 접속이 되고, 팝업창이 하나 나옴
    3. 창 전환 시 에러가 남
        - time.sleep(n) 으로 n초가 쉬어가면 selenium이 잘 따라감</code></pre><p>from selenium impor webdriver</p>
<p>url = &#39;<a href="http://www.opinet.co.kr/searRgSlect.do&#39;">http://www.opinet.co.kr/searRgSlect.do&#39;</a>
driver = webdriver.Chrome()
driver.get(url)
time.sleep(3)</p>
<h1 id="팝업창-뜸">팝업창 뜸</h1>
<h1 id="팝업창으로-전환-후-닫아줌">팝업창으로 전환 후 닫아줌</h1>
<p>driver.switch_to_window(driver.window_handles[-1])
driver.close()
time.sleep(3)</p>
<h1 id="메인-화면-창으로-전환">메인 화면 창으로 전환</h1>
<p>driver.switch_to_window(driver.window_handles[-1])
driver.get(url)</p>
<h1 id="새로-정리하기">새로 정리하기</h1>
<p>import time</p>
<p>def main_get():
from selenium impor webdriver</p>
<h1 id="페이지-접근">페이지 접근</h1>
<p>url = &#39;<a href="http://www.opinet.co.kr/searRgSlect.do&#39;">http://www.opinet.co.kr/searRgSlect.do&#39;</a>
driver = webdriver.Chrome()
driver.get(url)
time.sleep(3)</p>
<h1 id="팝업창으로-전환">팝업창으로 전환</h1>
<p>driver.switch_to_window(driver.window_handles[-1])</p>
<h1 id="팝업창-닫기">팝업창 닫기</h1>
<p>driver.close()
time.sleep(3)</p>
<h1 id="메인-화면-창으로-전환-1">메인 화면 창으로 전환</h1>
<p>driver.switch_to_window(driver.window_handles[-1])</p>
<h1 id="접근-url-다시-요청">접근 URL 다시 요청</h1>
<p>driver.get(url)</p>
<p>main_get()</p>
<pre><code>- 시도, 구 정보 가져오기</code></pre><h1 id="지역-시도">지역: 시/도</h1>
<p>sido_list_raw = driver.find_element(BY.ID, &#39;SIDO_MNO&#39;)
sido_list_raw</p>
<p>sido_list = sido_list_raw.find_elements(BY.TAG_NAME, &#39;option&#39;)
sido_list</p>
<p>sido_names = [option.get_attribute(&#39;value&#39;) for option in sido_list]
sido_names.remove(&quot;&quot;)
sido_names</p>
<p>sido_list_raw.send_keys(sido_names[1])</p>
<p>gu_list_raw = driver.find_element(BY.ID, &#39;SIGUNGU_NM0&#39;)
gu_list = gu_list_raw.find_elements(BY.TAG_NAME, &#39;option&#39;)</p>
<p>gu_names = [opion.get_attribute(&#39;value&#39;) for option in gu_list]
gu_names.remove(&quot;&quot;)
gu_names</p>
<p>element_get_excel = driver.find_element(BY.ID, &#39;glopopd_excel&#39;).click()</p>
<p>import time
from tqdom import tqdm_notebook</p>
<p>for gu in tqdm_notebook(gu_names):
    element = driver.find_element(BY.ID , &#39;SIGUNGU_NM0&#39;)
    element.send_keys(gu)
    time.sleep(2)</p>
<pre><code>element_get_excel = driver.find_element(BY.ID, &#39;glopopd_excel&#39;).click()
time.sleep(1)</code></pre><p>driver.close()</p>
<pre><code>#### 주유소 가격 정보 정리하기
- 파일 목록을 한 번에 가져오기
    - glob 라이브러리를 활용
- DF 형식이 동일하고 연달아 붙이기만 하면 될 때
    - pd.concat()
- </code></pre><p>import pandas as pd
from glob import glob</p>
<p>stations_files = glob(&quot;../data/지역_*.xls)
stations_files</p>
<p>tmp_raw = []</p>
<p>for file_name in stations_files:
    tmp = pd.read_excel(file_name, hedaer = 2)
    tmp_raw.append(tmp)</p>
<p>station_raw = pd.concat(tmp_raw)
station_raw.info()
station_raw.head()</p>
<p>stations = pd.DataFrame(
    {
        &quot;상호&quot;: station_raw[&quot;상호&quot;],
        &quot;주소&quot;: station_raw[&quot;주소&quot;],
        &quot;가격&quot;: station_raw[&quot;휘발유&quot;],
        &quot;셀프&quot;: station_raw[&quot;셀프여부&quot;],
        &quot;상표&quot;: station_raw[&quot;상표&quot;],
    }
)
stations[&#39;구&#39;] = [eachAddress.split()[1] for eachAddress in stations[&#39;주소&#39;]]</p>
<p>len(stations[&#39;구&#39;].unique())</p>
<p>stations[stations[&#39;구&#39;] == &#39;서울특별시&#39;, &#39;구&#39;] = &#39;성동구&#39;
stations[stations[&#39;구&#39;] == &#39;특별시&#39;, &#39;구&#39;] = &#39;도봉구&#39;</p>
<p>len(stations[&#39;구&#39;].unique())</p>
<p>stations[&#39;가격&#39;] = stations[&#39;가격&#39;].astype(&#39;float&#39;)</p>
<h1 id="가격이-없어서--로-표시된-부분-버리기">가격이 없어서 -로 표시된 부분 버리기</h1>
<p>stations = stations[stations[&#39;가격&#39;] != &#39;-&#39;]
stations[&#39;가격&#39;] = stations[&#39;가격&#39;].astype(&#39;float&#39;)</p>
<p>stations.reset_index(inplace = True)
del stations[&#39;index&#39;]</p>
<p>stations.head()</p>
<pre><code>#### 주유가격 시각화
- Box Plot
    - Median 중심으로 아래 위 상자가 각각 전체 데이터의 25%씩 총 50%를 가짐
    - 상자 전체 길이, IQR(Inter Quatile Range)
    - IQR의 1.5배를 벗어나면 점으로 별도 표기, outlier
    - 가운데 십자 표시, Mean</code></pre><p>import matplotlib.pyplot as plt
import seaborn as sns</p>
<h1 id="pandas의-boxplot">pandas의 boxplot</h1>
<p>stations.boxplot(column = &#39;가격&#39;, by = &#39;셀프&#39;, figsize = (12, 8));</p>
<h1 id="seaborn의-boxplot">seaborn의 boxplot</h1>
<p>plt.figure(figsize = (12, 8))
sns.boxplot(x = &#39;셀프&#39;, y = &#39;가격&#39;, data = stations, palette = &#39;Set3&#39;)
plt.grid()
plt.show()</p>
<p>plt.figure(figsize = (12, 8))
sns.boxplot(x = &#39;상표&#39;, y = &#39;가격&#39;, hue = &#39;셀프&#39;, data = stations, palette = &#39;Set3&#39;)
plt.grid()
plt.show()</p>
<h1 id="지도-시각화">지도 시각화</h1>
<p>import json
immport folium
import warnings</p>
<p>Warnings.simplefilter(acction = &#39;ignore&#39;, category = futrueWarning)</p>
<p>stations.sort_values(by = &#39;가격&#39;, asceding = False).head(10)
stations.sort_values(by = &#39;가격&#39;, asceding = True).head(10)</p>
<p>import numpy as np</p>
<p>gu_data = pd.pivot_table(stations, index = [&#39;구&#39;], values = [&#39;가격&#39;], aggfunc = np.mean)
gu_data.head()</p>
<p>geo_path = &#39;../data/02. skorea_municipalities_geo_simple.json&#39;
geo_str = json.load(open(geo_path, encoding = &#39;utf-8&#39;))</p>
<p>my_map = folium.Map(location = [37.5502, 126.982],
    zom_start = 10.5,
    tiles = &#39;Stamen Toner&#39;)</p>
<p>my_map.choropleth(
    geo_data = geo_str,
    data = gu_data,
    columns = [gu_data.index, &#39;가격&#39;],
    fill_color = &#39;PuRd&#39;,
    key_on = &#39;feature.id&#39;
)
my_map</p>
<p>```</p>
<h2 id="느낀점">느낀점</h2>
<p>사용하던 노트북에 문제가 있어서 새 노트북을 사는데 시간이 좀 걸렸다. 나는 빨리 구매했지만, 그 분이 삼 주에 걸쳐서 우리 집으로 오심.. 그 과정에서 마음이 지치고, 와중에 웹데이터를 이용하는 내용도 어렵고. 언제나 생각하지만 교육 자체보다는 외적인 것에 더 흔들릴 수 있음을 잊지말아야겠다. 교육은 쉬지 않고 진행되는데, 내가 이걸 끝까지 해내는 것이 목표라면 내가 좀 잘 못하는 순간도 괜찮다 생각하고 넘길 줄 알아야겠다.</p>
<p><strong>이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[006. 데이터 취업 스쿨 스터디 노트_6주차_EDA, 웹크롤링, 파이썬 프로그래밍_1]]></title>
            <link>https://velog.io/@julia-jh319/006.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B86%EC%A3%BC%EC%B0%A8EDA-%EC%9B%B9%ED%81%AC%EB%A1%A4%EB%A7%81-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D1</link>
            <guid>https://velog.io/@julia-jh319/006.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B86%EC%A3%BC%EC%B0%A8EDA-%EC%9B%B9%ED%81%AC%EB%A1%A4%EB%A7%81-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D1</guid>
            <pubDate>Mon, 13 May 2024 12:58:58 GMT</pubDate>
            <description><![CDATA[<h1 id="6주차">6주차</h1>
<h2 id="수강한-분량">수강한 분량</h2>
<p>EDA, 웹크롤링, 파이썬 프로그래밍의 일부분인 OT, 서울시 CCTV 현황 데이터 분석, 서울시 범죄 현황 데이터 분석</p>
<h1 id="각-강의별-학습한-핵심-내용-정리">각 강의별 학습한 핵심 내용 정리</h1>
<p>EDA / 웹크롤링 / 파이썬 프로그래밍</p>
<h2 id="ot">OT</h2>
<p>프로젝트 위주로 진행하여, 잦은 변화 속 중요한 흐름을 이해하고 다양한 경험을 하는 것을 목표로 한다</p>
<h3 id="minoconda-설치">minoconda 설치</h3>
<ul>
<li><p>win</p>
<ul>
<li>anaconda Prompt</li>
</ul>
</li>
<li><p>mac</p>
<ul>
<li>homebrew 설치 필요</li>
<li>M1<ul>
<li>miniforge설치<h3 id="conda-가상환경">conda 가상환경</h3>
</li>
</ul>
</li>
</ul>
</li>
<li><p>버전 확인</p>
<ul>
<li>conda --version</li>
</ul>
</li>
<li><p>업데이트하기</p>
<ul>
<li>conda update conda</li>
</ul>
</li>
<li><p>conda 가상환경 생성</p>
<ul>
<li>conda create -n ds_study python=3.8</li>
</ul>
</li>
<li><p>conda 가상환경 활성화</p>
<ul>
<li>conda activate ds_study</li>
</ul>
</li>
<li><p>conda 가상환경 비활성화</p>
<ul>
<li>conda deactivate</li>
</ul>
</li>
<li><p>conda 가상환경 목록</p>
<ul>
<li>conda env list</li>
</ul>
</li>
<li><p>conda 가상환경 삭제</p>
<ul>
<li>conda env remove -n ds_study</li>
</ul>
</li>
<li><p>jupyter notebook 설치</p>
<ul>
<li>conda install jupyter</li>
</ul>
</li>
<li><p>package 설치</p>
<ul>
<li>conda install ipython</li>
<li>conda install matplotlib</li>
<li>conda install seaborn</li>
<li>conda install pandas</li>
<li>conda install scikit-learn</li>
<li>conda install xlrd</li>
</ul>
</li>
<li><p>jupyter notebook 실행</p>
<ul>
<li>jupyter notebook~~</li>
</ul>
</li>
<li><p>matplotlib 한글 설정(일단매번 설정해둠)</p>
<pre><code>import matplotlib.pyplot as plt
from matplotlib import rc
%matplotlib inline
rc(&#39;font&#39;, family = &#39;Malgun Gothic&#39;)
</code></pre></li>
</ul>
<p>from matplotlib import font_manager
f_path = &#39;C:\Windows\Fonts\malgun.ttf&#39;
font_manager.FontProperties(fname-f_path).get_name()</p>
<pre><code>### vscode 환경설정
- ctrl + shift + p
- select interpreter
- python: select interpreter
- ds_study 있는것 선택

## 서울시 CCTV 현황 데이터 분석
### 목표
1. 서울시 구별 CCTV 현황 데이터 확보
2. 인구 현황 데이터 확보
3. CCTV 데이터와 인구 현황 데이터 합치기
4. 데이터 정리, 정렬
5. 그래프 그리기
6. 전체 경향 파악하는 능력
7. 경향에서 벗어난 데이터 강조하는 능력
1~4: python, pandas
5: matplotlib
6: regression using numpy
7: insight, visualization
### 엑셀, 텍스트 파일 읽기
- `data = pd.read_csv(&quot;파일주소/파일명.확장자&quot;, encoding = &#39;utf-8&#39;)`
    - 인코딩값은 변하기도 함
- `data.head()`
    - 정렬된 값 중 상위 5개를 보는 것
    - ()안에 숫자를 넣으면 그만큼 볼 수 있음
- `data.tail()`
    - 정렬된 값 중 하위 5개를 보는 것
    - ()안에 숫자를 넣으면 그만큼 볼 수 있음
- `data.columns`
    - 컬럼 이름 조회
- `data.rename(columns = {&quot;원래이름&quot; : &quot;바꿀이름&quot; }, inplace = True)`
    - 원래이름 자리에 data.columns\[n\]으로 표시하는 것이 편하기도 하다
    - inplace = True 옵션
        - 원본 데이터를 이번 버전으로 교체하는 여부
        - True / False
- `data = pd.read_excel(&quot;파일주소/파일명.확장자&quot;)`
    - 엑셀 파일을 여는 함수
- `data = pd.read_excel(&quot;파일주소/파일명.확장자&quot;, header = n, usecols = &quot;Alphabets&quot;)`
    - 헤더에 병합셀이 있을 수 있으므로 헤더를 지정해주는 것이 좋다
    - header 옵션
        - 자료를 읽기 시작할 행
    - usercols 옵션
        - Alphabets는 읽어올 엑셀의 지정 컬럼
### python 모듈 규칙
- `import MODULE`
    - module을 사용하겠다
    - MODULE.function
- `import MODULE as md`
    - module을 사용할 건데 md라고 부르겠다
    - md.function
- `from MODULE import function`
    - module에 포함된 function 함수만 사용하겠다
    - function
### pandas 이용하기
#### **Series**
- pandas의 데이터형의 기본 구성
- index, value로 이루어져 있다.
    - DF의 컬럼 한 줄 한 줄은 Series로, 이것들이 모여 DF가 된다.
- 한 가지 데이터 타입만 가질 수 있다.
    - 입력 데이터타입이 단일하지 않을 때 전체를 문자열, 실수형 데이터로 인식하게 됨
#### `date_range(&quot;시작날짜&quot;, periods = n)`
- 시작날짜부터 n일까지의 날짜 목록을 만드는 함수
- 시작날짜 양식은 
    - 예시: 20240429
- 데이터 타입
    - datetime64
#### **DataFrame**
- DataFrame 선언 방법
    - `pd.DataFrame(값, index = 값, columns = [값])`
        - index와 columns를 지정해야한다
    - `pd.DataFrame({&quot;Key&quot;: [&quot;K0&quot;, &quot;K1&quot;], &quot;A&quot;: [&quot;A0&quot;, &quot;A1&quot;]})`
        - 열 단위로 지정
    - `pd.DataFrame({&quot;Key&quot;: &quot;K0&quot;, &quot;A&quot;: &quot;A0&quot;}, {&quot;Key&quot;: &quot;K1&quot;, &quot;A&quot;: &quot;A1&quot;})`
        - 행 단위로 지정
- 각 값만 보고 싶을 때
    - `df.index`
    - `df.columns`
    - `df.values`
- `df.info()`
    - df 기본 정보 확인
    - 각 컬럼 크기와 데이터 형태 확인하는 용도
- `df.describe()`
    - df의 통계적 기본 정보 확인용
- `df.sort_values(by = &quot;컬럼명&quot;, ascending = False)`
    -  by 옵션 
        - 컬럼명 기준으로 정렬
    - ascending 옵션
        - True일 경우 오름차순
- `df[&quot;컬럼명&quot;]`
    - 특정 컬럼만 읽기
    - 컬럼명이 문자열인 경우 `df.컬럼명` 으로도 가능하다
- `df[인덱스 범위1:인덱스 범위2]`
    - 인덱스 범위에 있는 데이터 확인
    - 인덱스 범위를 숫자로 지정할 경우 인덱스 범위2에서 1개 뺀 값
    - 인덱스 범위를 이름으로 지정할 경우 끝까지 포함
- `df.loc[행, 열]`
    - `:` 표현
        - 전체 선택
    - `[, ]` 표현
        - 일부 선택
- `df.iloc[행, 열]`
    - 열 생략시 행만 선택
    - `:` 구분자를 이용해 범위를 지정하여 슬라이싱
    - `[]` 을 이용해 띄어서 선택도 가능
- `df[df[&quot;A&quot;] &gt; 0]`
    - df의 A컬럼 값 중 0보다 큰 것들만 선택적으로 보여준다
    - 내부는 조건문
    - 이때 전체 df 모양은 살린다
    - 조건에 맞지 않는 부분은 NaN으로 표시된다
        - NaN: Not a Number
- `df[&quot;E&quot;] = [값들]`
    - 새로운 컬럼 E를 만들어 값들을 넣어준다.
- `df[&quot;E&quot;].isin([값들])`
    - df의 E 컬럼에 값들이 있는가, 그렇다면 True, 아니면 False 반환
    - 조건문이므로 저것을 활용한 df만 편집하여 볼 수 있다
- `del df[&quot;컬럼명&quot;]`
    - 특정 컬럼 삭제하기
- `df.drop([입력값], axis = 1)`
    - axis 옵션
        - 0
            - 디폴트값
            - 인덱스를 기준으로 삭제
        - 1
            - 컬럼을 기준으로 삭제
- `df.apply(함수)`
    - 함수를 각 컬럼마다 적용한 결과를 확인할 수 있다
    - 예시) `df.apply(np.cumsum)`
        - 각 컬럼 누적합
- `df.set_index(&quot;컬럼명&quot;, inplace = True)`
    - index를 재지정하는 함수
    - unique한 데이터를 index로 잡는 것이 좋음
- `df.corr()`
    - 데이터 상관관계 찾는 함수
    - 최소한의 근거가 있어야 해당 데이터를 비교하는 의미가 존재
    - 0.2 이상 데이터 비교하는 것은 의미 있다
    - 상관관계 != 인과관계
- 두 데이터 합치기
    - pandas.merge() 함수를 이용하여 병합
        - `pd.merge(left, right, on = &#39;key&#39;)`
            - key 컬럼을 기준으로 병합
        - `pd.merge(left, right, how = &#39;left&#39;, on = &#39;key&#39;)`
            - left에 key 를 기준으로 right 병합
            - right에 없는 값은 NaN으로 표시된다
            - left key에 없는 값은 없어진다
        - `pd.merge(left, right, how = &#39;outer&#39;, on = &#39;key&#39;)`
            - 둘 다 손상되지 않도록 key 컬럼을 기준으로 병합
            - 각자 없는 값은 NaN으로 표시된다
        - `pd.merge(left, right, how = &#39;inner&#39;, on = &#39;key&#39;)`
            - key 컬럼에서 두 데이터에 공통 분모만 병합
            - 기본 디폴트값
    - pandas.concat() 함수를 이용하여 병합
    - pandas.join() 함수를 이용하여 병합
- `df.to_csv(&quot;경로/파일이름.csv&quot;, sep = &quot;,&quot;, encoding = &quot;utf-8&quot;)`
    - DataFrame을 csv로 저장하는 함수\
### matplotlib 기초
- 그래프 결과가 중요할 경우 그래프 그리는 코드를 def()로 작성한다. 별도의 셀에서 그림만 나타낼 수 있기 때문이다
- `import matplotlib as mpl`
    - 자주 사용은 않지만 자주 쓰는 약어 알아두기
- `import matplotlib.pyplot as plt`
    - 2차원 그래프 그리는 모듈
    - matlab에 있는 기능을 담아둔 곳
- `from matplotlib.colors import ListedColormap`
    - 사용자 정의로 color map을 세팅할 수 있는 함수
    - `ListedColormap(리스트값)` 을 이용해 나만의 color map을 생성
- `get_ipython().run_line_magic(&#39;matplotlib&#39;, &#39;inline&#39;)`
    - 주피터 노트북에서 matplotlib 결과를 문서에 포함시켜서 출력하라
    - `%matplotlib inline` 이라고 작성해도 무방
- `plt.figure(figsize = (n, m))`
    - 가로 n 세로 m 길이의 사이즈의 그래프를 그려라
    - figure 하나에 여러 그래프를 그릴 수 있다
    - nXm 크기의 도화지를 설정한다고 생각하기
- `plt.plot(x 데이터, y 데이터, label = &#39;라벨값&#39;, &quot;선스타일옵션&quot;)`
    - x 데이터에 대응되는 y 데이터를 라벨값을 라벨로 달아서 그려라
    - 선 스타일 옵션, 문자와 기호로도 표현 가능
        - 문자
            - r
                - 빨간색
            - b
                - 파란색
            - s
                - 네모
            - g
                - 초록색
        - 기호
            - `--`
                - 점선
            - `^`
                - 삼각형
    - color 옵션
        - 선 색
    - linestyle 옵션
        - 선 모양
    - marker
        - 점 모양
    - markerfacecolor
        - 점 색
    - markersize
        - 점 크기
- `plt.scatter(x데이터, y데이터)`
    - 점을 뿌리듯이 그리는 그림. 점만으로 표현
    - c 옵션
        - 색깔을 단계로 지정
- `plt.text(x좌표, y좌표, 표시글자, fontsize = 숫자)`
    - 글자를 찍는 함수
    - 좌표값이 데이터와 동일하면 가리게 되므로 `x좌표값 * 1.02` 혹은 `y좌표값 * 0.98` 등으로 표시한다
- `plt.colorbar()`
    - 각 단계별 색 표현하는 함수
- `plt.xilm([시작, 끝])`
    - x축 범위를 시작과 끝으로 지정 가능
    - x를 y로 바꾸면 y축도 동일하게 적용됨
- `plt.grid()`
    - 그래프 격자 그리는 함수
    - 내부 값 디폴트: True
- `plt.legend()`
    - 라벨 범례 표현하는 함수
    - labels 옵션
        - 범례 종류를 나타내는 옵션
        - plot 내부에 범례를 표시한 경우 생략가능
        - 리스트 값으로 표현 가능
    - loc 옵션
        - 범례 위치
        - best가 디폴트로 총 11가지 존재하며 string 혹은 integer로 표시 가능
- `plt.xlabel(&quot;x축이름&quot;)`
    - x축 이름 달아줘
    - x를 y로 바꾸면 y축도 동일하게 적용됨
- `plt.title(&quot;그래프 이름&quot;)`
    - 그래프 이름 달아줘
- `plt.show()`
    - 그래프 보여줘
### numpy 기능
- `numpy.arange(a, b, s)`
    - a부터 b가지의 **s의 간격**
- `numpy.sin(value)`
    - value에 대응하는 sin값을 출력
    - sin자리에 cos를 넣으면 cos값 출력
- **numpy를 이용하여 1차 직선 만들기**
    - `np.polyfit(x데이터, y데이터, 차수)`
        - 직선을 구성하기 위한 계수 계산
        - 차수 옵션은 숫자로 바로 사용 가능
    - `np.poly1d(계수)`
        - polyfit으로 찾은 계수로 python에서 사용할 함수로 만들어 줌
        - 직선을 구성하는 두 개의 계수를 넣음
        - 이 결과값에 (x값)을 넣으면 예측 y값을 출력
    - `np.linsplace(a, b, n)`
        - a부터 b까지 **n개의 등간격** 데이터 생성
        - 경향선을 위한 x데이터 생성
        - 이 값을 np.npoly1d의 결과 1차 함수에 활용
### pandas에서 matplotlib 기능 가져와 사용하기
- `df.plot(kind = &#39;모양&#39;, figsize = (n, m), grid = True);`
    - kind 옵션
        - &#39;bar&#39;
        - &#39;barh&#39;
        - &#39;line&#39;
    - figsize 옵션
        - (n, m)
    - grid 옵션
        - True / False
    - 마지막 `;` 표시하면 메모리 번지가 보이지 않음
        - 주피터 노트북은 셀 내부 마지막에 변수가 존재하면, 변수값을 보여줌. plot의 변수값은 메모리 번지인듯. 그것을 보여주지 않으려면 ;을 붙이면 됨 왤까???
### 인구현황 데이터 훑어보기
- 전체 숫자 오름차순, 내림차순 정렬
- 최근 증가율 확인 위해 최근 3년간 그 전 보유한 갯수 대비 많이 설치한 것으로 정리
    - 2016 + 2015 + 2014 / 2013 이전 \*100
- unique() 함수 이용하여 데이터 초반 검증 필요
- 각 요소의 합계도 보아야 하지만, 비율도 보아야 한다
- 특정 컬럼을 골라 sort_values()를 한 결과를 보면 정렬이 되어 데이터를 되어 보기 좋다
- **주피터 노트북 내에 망치 모양 뭐지???**
### CCTV 데이터 경향
- 데이터 경향 그려보기
    - 단순한 소계
    - 중요 지수 대비 비율
        - 선형회귀 활용 -&gt; 간단히 numpy 활용
    - 비율과 데이터, 전체 경향 함께 보기
- 경향에서 벗어난 데이터 강조하기
    - 실제값과 경향과의 차이를 오차 컬럼을 만들어 표현하기
    - 오름차순, 내림차순 둘 다 보여주기
    - 오차 컬럼 내 상위, 하위 5개만 표시하는 등 선택적으로 글씨와 함께 특별한 색을 사용하면 EDA용 시각화자료로 괜찮음
## 서울시 범죄 현황 데이터 분석
### 강남3구 범죄 현황 데이터 특징 정리하기
- 데이터 과학의 목적
    - 가정(인식)을 검증하고 표현하는 것
### 데이터 개요
- 서울시 관서별 5대 범죄 현황 &gt; 데이터 수집
- `thousands = &quot;,&quot;`
    - pd.read_csv로 부를 때, 숫자에 콤마가 있는 경우 활용할 수 있는 옵션
    - 문자 인식될 수 있지만, 콤마 제거 후 숫자로 읽는 것이 가능해짐
- `df.info()`로 확인한 후 실제 데이터 갯수와 RangeIndex 범위를 비교해 보면 정리해야 하는 데이터가 얼마나 있는지 확인할 수 있다
- `df[df[&#39;특정컬럼&#39;].isnull()]`
    - 특정 컬럼에 NaN이 있는 데이터만 따로 확인해보기
- `df = df[df[&#39;특정컬럼&#39;].notnull()]`
    - NaN 컬럼을 제거하지 말고, NaN이 아닌 데이터만 불러오기
### pandas의 pivot_table
- `pd.pivot_table(df, index = [&quot;컬럼명&quot;, ...], values = [&quot;컬럼명&quot;, ...], columns = [&quot;컬럼명&quot;, ...], aggfunc = [함수, ...], margins = True)`
    - 컬럼명을 인덱스로 재정렬해줌
    - `df.pivot_table()` 로 사용해도 동일한 결과가 나옴
    - 옵션의 값들이 한 개일 경우 일반적인 표현, 여러 개일 경우 리스트 형태로 표현
    - 인덱스를 여러 개 지정한 경우, 제일 첫 번째 요소에 맞추고 뒤로 갈 수록 중복될 수 있다
    - values 옵션으로 보고 싶은 컬럼을 지정할 수 있음
    - columns 옵션
        - 분류를 지정
        - 없는 데이터는 NaN으로 표시
            - fill_value = 값
                - NaN에 대한 표시를 지정해주는 옵션
    - aggfunc 옵션
        - 중복 데이터를 정리하는 방식
        - 디폴트: 평균
        - 함수를 값으로 받음
        - 함수를 리스트 형태로 여러 개 받을 수 있음. 하나의 컬럼에서 평균, 총합 등으로 계산한 값이 따로 가능
    - margins 옵션
        - False 값이 디폴트
        - True이면 총계값 나옴
### 데이터 정리
- index를 경찰서 이름, columns를 죄종, 발생검거로, aggfunc을 덧셈으로 활용하여 pivot_table을 만들어본다
- 컬럼이 multi로 잡혀 보기 불편함
    - `df[&quot;함수명&quot;, &quot;계산된 컬럼명&quot;, &quot;죄종값&quot;, &quot;발생검거값&quot;]`등으로 접근해야 함
        - level 0~n까지 순서대로 나옴
    - `df.columns.droplevel([0, 1, ...])`
            - 다중 컬럼에서 특정 컬럼을 제거
            - 위 값을 df.columns로 다시 재배정함
                - **inplace 옵션이 있는지 확인**
            - df.columns의 결과가 MultiIndex일 경우, 마지막에 names 값을 확인해보기
                - None이라고 되어있을 경우 종류가 여러 개라는 것이 아니므로 삭제해도 괜찮을지도...? 다만 pivot한 과정을 어딘가에 메모해두어 컬럼의 속성을 기억해둘 필요 있음
- 경찰서 이름 &gt; 구 이름 변환 등이 필요함
    - 커뮤니케이션 능력
    - 보고서 능력
    - 목적을 상기하여 지역별 분석이었으므로 이름을 지역으로 치환하는 것이 필요
### pip 명령과 conda 명령
- anaconda가 많은 python 모듈을 포함한 배포판이라 따로 설치할 일이 없음
- pip 명령
    - python의 공식 모듈 관리자
    - `pip list`
        - 현재 설치된 모듈 리스트 반환
    - `pip install module_name`
        - 모듈 설치
    - `pip uninstall module_name`
        - 설치된 모듈 제거
    - 주피터 노트북에서는 !를 앞에 붙이면 os레벨 명령 사용 가능
        - `!pip list`
            - 주피터 노트북 안쓰고 바로 코드를 export 하여 사용하면 !명령어는 에러 발생
        - `get_ipython().system(&quot;pip list&quot;)`
- conda 명령
    - anaconda에서 배포한 모듈 관리자
    - pip 명령은 conda환경에서 dependency 관리가 정확하지 않을 수 있으므로 가급적 conda를 사용하는 것이 좋음
    - 모든 모듈이 conda로 설치되지 X
    - `codna list`
        - 설치된 모듈 list
    - `conda install module_name`
        - 모듈 설치
    - `conda uninstall module_name`
        - 모듈 제거
    - `conda install -c channel_name module_name`
        - 지정된 배포 채널에서 모듈 설치
### google maps api 사용
- conda install googlemaps를 검색
    - conda-forge 채널에서 설치하기
    - python 세계 모듈간 dependency문제와 개인 PC 환경의 indivisual diffence로 인한 문제가 있음
- `conda install -c conda-forge googlemaps`
- Google Map API key가 필요
    - 구글 클라우드 결제 계정 링크에 접속
    - 계정만들기
    - ds_study로 이름 만들기
    - 개인정보 입력하기
    - 탐색메뉴&gt; API 및 서비스 &gt; 사용자 인증 정보 선택
    - 사용자 인증 정보 만들기 &gt; API 키 선택
    - 발급된 키 복사 후 저장 &gt; 키 제한 선택
    - API 및 서비스 &gt; 사용자 인증 정보 &gt; 키 제한 선택 &gt; Geocoding API 선택 &gt; 저장</code></pre><p>import googlemaps</p>
<p>gmaps_key = &quot;복사한 키값&quot;
gmaps = googlemaps.Client(key = gmaps_key)</p>
<p>gmaps.geocode(&quot;서울영등포경찰서&quot;, language = &quot;ko&quot;)</p>
<pre><code>### python for 문</code></pre><p>for n in [1, 2, 3, 4]:
    print(n)</p>
<h1 id="list-comprehension">list comprehension</h1>
<p>[n for n in range(1, 5)]</p>
<pre><code>- pandas의 iterrows()
    - pandas DF는 대부분 2차원인데, for문을 이용하면 가독성이 떨어짐
    - itterows() 옵션을 사용하면 편함
    - 인덱스와 내용으로 나누어 받는 것을 주의
### google maps에서 구별 정보 얻어 데이터 정리</code></pre><p>import googlemaps</p>
<p>gmaps_key = &quot;복사한 키값&quot;
gmaps = googlemaps.Client(key = gmaps_key)</p>
<p>gmaps.geocode(&quot;서울영등포경찰서&quot;, language = &quot;ko&quot;)</p>
<pre><code>- api를 불러온 결과는 리스트 형태이고 각 값이 딕셔너리 형태이다.
- 딕셔너리에서 데이터 얻는 get 명령어를 활용
- 전체 주소에서 필요한 구 이름만 가져온다
- 경찰서 이름에서 소속된 구이름, 위도, 경도 정보 저장하기 위한 컬럼을 np.nan으로 채워 생성
- iterrows()를 이용해 인덱스와 그에 해당하는 행을 받아 반복문을 수행
- 구글 검색을 용이하게 하기 위해 검색어를 가급적 상세하게 잡아준다
- 범죄의 발생과 검거를 합쳐 표현하고 싶다
    - `get_level_values(0)[0] + get_level_values(1)[0]`를 반복적으로 활용
### 구별 데이터로 변경
- `pd.read_csv(index_col = 0)` index_col 옵션을 통해 인덱스를 지정할 수 있음
- 구별로 pivot하기, 이때 활용 함수는 sum
    - 활용 함수에 맞지 않는 위도와 경도는 삭제
- 검거율 컬럼 만들기
    - 다수의 컬럼을 다수의 컬럼으로 나누기
        - `df[컬럼명리스트] = df[분자리스트].div(df[분모리스트].values) ** 100`
    - 검거 컬럼 삭제
    - 실제로는 발생 연도, 검거 연도를 구분 분석해야 하지만, 일단은 디테일하게 하지 않는다고 가정하고 heatmap 그래프에서 문제될 가능성이 있어 100이상 수치는 100으로 바꾼다
        - `df[df[컬럼명리스트] &gt; 100] = 100`
            - 만약 모듈 버전과 의존성 문제로 작동하지 않는 경우 for문을 활용
    - 컬럼 이름 변경
        - `df.rename(columns = {&quot;원래이름&quot;: &quot;나중이름&quot;, ...}, inplace = True)`
### 범죄현황 데이터 최종 정리
- 범죄 특성 상 경중에 따라 발생 건수의 차이가 크다. 예로 살인은 한 자리수, 절도는 네 자리수 발생임
    - 시각화 후 비교가 어려워진다
    - 본래 DF는 두고, 정규화한 데이터를 만든다.
    - min-max scailing
        - 최고값:1, 최솟값: 0
        - `df = df[리스트변수]/df[리스트변수].max()`
    - 스케일링한 자료에 검거율 자료를 이어 붙인다
    - `df1[리스트변수] = df2[리스트변수]`를 활용하면 df1에 df2값을 가로로 이어붙일 수 있다. 이때 리스트 변수는 이어붙이기 원하는 컬럼명들의 나열
- 범죄 스케일링 데이터 + 범죄 검거율 데이터 + 인구 데이터 + CCTV 데이터 + 정규화된 범죄 데이터의 평균 데이터
    - 이후에 범죄별로 가중치를 더해서 평균을 내는 방법도 존재함
    - `np.mean(np.array([여러 데이터 나열1], [여러 데이터 나열2], ...), axis = 1)`
        - 결과값: 여러 데이터 나열1의 평균, 여러 데이터 나열2의 평균, ...
        - axis = 1이면 행을 기준, 디폴트값 
### seaborn 사용
- `!conda install -y seaborn`
    - seabon 깔기
- `import seaborn as sns`
    - matplotlib과 함께 실행된다
    - 임포트만 시켜도 matplotlib 결과가 seaborn 스타일로 바뀐다
- `sns.load_dataset(&quot;&quot;)`
    - 연습용 데이터 제공해줌
- `plt.plot(x데이터1, y데이터1, x데이터2, y데이터2, x데이터3, y데이터3, ...)` 등으로 여러 그래프 그릴 수 있음
    - 개별 설정은 불가능
- `sns.set_style(&quot;문자&quot;)`
    - white, whitegrid, dark, darkgrid, stick 등 이 존재함
- `sns.despine(offset = 10)`
    - 그래프 중심점이 10만큼 떨어짐
- `sns.boxplot(x = x데이터, y = y데이터, data = 원천 데이터, hue = &quot;&quot;, palette = &quot;&quot;)`
    - 원천 데이터를 먼저 고르고 x데이터와 y데이터는 컬럼명으로 선택 가능
    - hue 옵션
        - 종류따라 구분 하고 싶은 컬럼
    - palett 옵션
        - 색상표 선택
- `sns.swarmplot(x = &quot;&quot;, y = &quot;&quot;, data = 원천 데이터, color = &quot;&quot;)`
    - 데이터 분포를 볼 수 있음
    - 박스플랏과 함게 콜라보하면 좋음
    - color 옵션
        - 낮아질수록 검은색, 높아질수록 흰색이 됨
- `sns.lmplot(x = &quot;&quot;, y = &quot;&quot;, data = 원천 데이터, hue = &quot;&quot;, ci = None, order = 1, size = 숫자), roubust = False`
    - 회귀선 + 산점도 동시에 그려주는 그래프
    - size 옵션
        - 그래프의 크기
        - 정수 한 개 입력
        - height로 이름 바뀜
    - hue 옵션
        - 종류따라 구분 하고 싶은 컬럼
        - 컬럼의 종류별 산점도 + 회귀선을 동시에 볼 수 있다
    - ci 옵션
        - 회귀선 근처 흐릿한 부분
        - None으로 두면 회귀선 근처 흐릿한 부분이 사라짐
        - 디폴트: None 아님
    - scatter_kws 옵션
        - 산점도 크기와 값을 표현
        - {&quot;문자&quot; = 값} 속성의 이름을 문자에, 해당되는 값을 할당
    - order 옵션
        - 회귀선의 차수
        - 디폴트: 1
    - robust 옵션
        - 이상값을 포함할지 여부
        - 디폴트: False, 이상값 모두 포함함
- `sns.heatmap(데이터, annot = True, fmt = &quot;&quot;, cmap = &quot;&quot;)`
    - annot 옵션
        - 네모 상자마다 값 표시
        - True / False
    - fmt 옵션
        - 소수점 표시 여부
        - d: 정수형
        - f: 실수형
    - cmap 옵션
        - 색상표
    - linewidths 옵션
        - 표 칸 간격 표시
        - 숫자 표시
- `sns.pairplot(데이터, hue = &quot;&quot;)`
    - 다수의 컬럼을 비교할 때 사용
    - 특성별 상관관계를 표시
    - hue 옵션
        - 종류따라 구분 하고 싶은 컬럼
        - 기준 컬럼별로 특성별 상관관계를 겹치게 그려줌
    - 이때, 원하는 컬럼만 선택하려면 `x_vars = [], y_vars = []` 옵션을 사용하여 리스트 내부에 원하는 컬럼명을 순서대로 넣어준다
    - kind 옵션
        - reg: 회귀
        - scatter: 산점도
        - kde: 지형도
        - hist: 히스토그램
    - height 옵션
        - 산점도 크기
        - 이전에는 size
- `df.query(&quot;컬럼명 == &#39;문자&#39;&quot;)`
    - 해당 컬럼이 문자와 동일한 데이터만 가져와라
### 범죄현황데이터 시각화
- 각 범죄간의 상관관계 확인
    - 강도가 살인으로 연결되는 것 보다 폭력이 살인으로 연결될 가능성이 높지 않을까 가설 후보로 둘 수 있음
    - 자료의 갯수가 많지 않아 확실히 알 수는 없음
- 인구수, CCTV와 범죄들의 상관관계를 확인
    - 소수의 이상점을 포함한 회귀선은 오류가 있을 수 있으므로 그것을 제외한 관계를 보는 것이 좋다
    - 인과관계가 아니라 상관관계이므로 가설을 세울 때 유의해야함
- 인구수, CCTV와 범죄 검거율의 상관관계를 확인
    - 검거율을 맨 처음 100이상을 100으로 제한하여 대부분이 100에 몰려있음
- 검거율로 heatmap, 정규화된 검거율의 대표값인 검거의 합을 기준으로 정렬
- 범죄발생 건수로 heatmap, 대표값으로 정규화된 발생 건수로 정렬
- **강남 3구 범죄 발생 건수가 낮지 않고, 범죄 검거율이 높지 않다. 인구대비 현황을 고려해야 할 것이다.**
### Folium 지도 시각화
- 크롬에서 동작이 가장 좋은 지도 시각화 도구
- `conda install -c conda -forge folium`
    - 설치에 문제가 있어
        - `!pip install folium`으로 설치
        - `!pip install charset` , `!pip install charset-normalizer` 설치하면 오류가 적어짐(windows한정)
- 위도와 경도 좌표만 입력해도 지도가 표시됨
        - `folium.Map(location = [위도, 경도])`
- 지도를 html로 저장 가능
    - `지도.save(&#39;파일경로/파일명.html&#39;)`
        - 주피터 노트북 환경이 아닐 때, 결과보기위함
- `folium.Map(location = [위도, 경도], tiles = &#39;스타일&#39;, zoom_start = 크기)`
    - zoom_start 옵션
        - 확대 크기를 지정
        - 허용 범위: 0~18
        - 디폴트: 10
    - tiles 옵션
        - 지도 스타일 바꿔줌
            - 디폴트: OpenStreetMap
            - 여러 종류 있음
- 마커를 추가
    - `folium.Marker(location = [위도, 경도]).add_to(지도이름)`
- `folium.Marker(location = [위도, 경도], popup = &#39;나올 멘트와 형식&#39;, tooltip = &#39;나올 멘트와 형식&#39;, icon = folium.Icon(icon = 모양, color = 색깔)).add_to(지도이름)`
    - popup 옵션
        - 문자타입으로 입력
        - 클릭하면 입력한 글씨가 출력됨
        - html 문법 적용 가능
            - `&lt;a href = &quot;연결주소&quot; target = _&#39;blink&#39;&gt;표시글자&lt;/a&gt;`
                - 표시 글자가 작성되어있고, 클릭하면 연결주소로 새창이 열림
    - tooltip 옵션
        - 문자타입으로 입력
        - 갖다대기만 하면 글씨가 출력됨
        - html 문법 적용 가능
    - icon 옵션
        - `folium.Icon()`를 불러옴
            - color 옵션
                - 문자로 입력가능
                - 아이콘 둘러싼 것의 색깔
                - 디폴트: 파랑
            - icon_color 옵션
                - 아이콘 자체의 색깔
                - 디폴트: 하양
            - icon 옵션
                - 표현되는 아이콘 모양
                - 디폴트: info-sign
            - angle 옵션
                - 가운데 아이콘의 기울어짐 정도
                - 시계방향
                - 디폴트: 0
            - prefix 옵션
                - fa 값일 경우
                    - font-awsome 참조
                - 디폴트: glyphicon
                    - getbootsrap 참조
- `지도이름.add_child(folium.ClickForMarker(popup = &#39;표시 문구&#39;))`
    - 지도를 클릭한 곳에 마커가 생성됨
    -  popup 옵션
        - 문자 입력으로 표시문구가 반환
        - 디폴트: 위도, 경도
- `지도이름.add_child(folium.LatLngPopup())`
    - 지도 클릭한 곳에 위도 경도를 반환해줌
    - 옵션 X
- `folium.Circle(location = [위도, 경도], radius = 반지름 크기, popup = &#39;나올 멘트와 형식&#39;, tooltip = &#39;나올 멘트와 형식&#39;, color = &quot;색깔&quot;, fill = False, fill_color = 색깔)`
    - radius 옵션
        - 반지름 크기
        - 디폴트: 10
    - color 옵션
        - 선 색깔
    - fill 옵션
        - True 일 경우, 내부 색상 채워짐
        - 디폴트: False
    - fill_color 옵션
        - fill이 True일 경우 채워질 색상
- `folium.CircleMarker(location = [위도, 경도], radius = 반지름 크기, popup = &#39;나올 멘트와 형식&#39;, tooltip = &#39;나올 멘트와 형식&#39;, color = &quot;색깔&quot;, fill = False, fill_color = 색깔)`
    - Circle보다 원형 크기가 훨씬 큼
    - 공식문서에서도 정확한 차이 기술 X
- 클릭으로 위도 경도 정보 반환
    - `folium.Map(~~).add_child(folium.LatLngPopup())`
- 지도에 colormap 표현
    - us_states.json 파일 이용해 경계선과 id를 각 지역에 구현
        - json 라이브러리 임포트 필요
    - us_unemployment csv파일에 위의 json 파일과 매칭되는 id와 값을 갖게 함
    - `지도.Choropleth(geo_data = &#39;활용 json 데이터&#39;, data = 활용 데이터, columns = [활용 컬럼들 나열], key_on = &#39;공유 기준 컬럼&#39;, fill_color = &#39;색&#39;, fill_opacity = 색 진하기 수치, line_opacity = 색 진하기 수치, legend_name = &#39;표시 이름&#39;`
        - 경계선을 하나의 덩어리로 잡고 색을 입힐 수 있음
        - geo_data 옵션
            - 경계선 좌표값이 담긴 데이터
        - data 옵션
            - 활용 데이터
            - Pandas의 DataFrame, Series 로 이루어져야 함
        - columns 옵션
            - 활용 데이터에서 사용할 컬럼
        - key_on 옵션
            - 문자값
            - 활용 지도 데이터와 활용 데이터 사이 공통된 key 컬럼 이름
            - feature.id 혹은 feature.properties.statename
        - fill_color 옵션
            - 채우는 색
        - fill_opacity 옵션
            - 채우는 색 흐린 정도
            - 0~1 사이
        - line_opacity 옵션
            - 선 흐린 정도
            - 0~1 사이
        - legend_name 옵션
            - 범례 이름
#### 아파트 유형 지도 시각화
- 공공데이터 포털 참조
- pandas의 DataFrame으로 부름
- DataFrame.info()로 데이터 상태 확인
    - NaN 데이터 제거
        - `df.dropna()`
    - 인덱스 리셋
        - `df.reset_index(drop = True)`
- for 문과 iterrows() 함수 활용하여 각 행별로 세대 수에 따라 색을 다르게 표현</code></pre><p>for idx, rows in df.iterrows():
    lat, lng = row.위도, row.경도</p>
<pre><code># marker
folium.Markar(
    location = [lat, lng],
    popup = rows.주소,
    tooltip = rows.분류,
    icon = folium.Icon(
        icon = &#39;home&#39;,
        colors = &quot;lightred&quot; if rows.세대수 &gt;= 199 else &quot;lightblue&quot;
        icon_color = &#39;darkred&#39; if rows.세대수 &gt;= 199 else &quot;darkblue&quot;
    )
).add_to(지도이미지)

# CircleMarker
folium.CircleMarkar(
    location = [lat, lng],
    radius = rows.세대수 * 0.2,
    fill = True,
    color = &quot;pink&quot; if rows.세대수 &gt;= 518 else &quot;green&quot;,
    fill_color = &quot;pink&quot; if rows.세대수 &gt;= 518 else &quot;green&quot;
    )
).add_to(지도이미지)</code></pre><p>```</p>
<h3 id="서울시-범죄현황-지도-시각화-및-장소별-분석">서울시 범죄현황 지도 시각화 및 장소별 분석</h3>
<h4 id="지도시각화">지도시각화</h4>
<ul>
<li>지도시각화에 필요한 json 파일 &gt; 현재 무료는 Lucy Park 자료가 유일</li>
<li>각 범죄별, 범죄 전체, 인구대비 범죄 데이터를 지도에 시각화하기</li>
<li>각 범죄별 검거의 평균값을 검거 컬럼으로 넣고 경찰서별 정보를 이용해 범죄발생과 함께 정리<ul>
<li>각 범죄 검거 컬럼을 컬럼 내 최댓값으로 나누어 정규화한 값의 평균을 구하여 검거 라는 컬럼을 만듬</li>
<li>이때, np.mean() 옵션의 axis = 1이 행으로 다른 것과 다름에 주의</li>
</ul>
</li>
<li>실습 중 crime_in_Seoul_row 파일로 실습이 잘 안 될 경우, crime_in_Seoul_1st 파일을 활용하면 잘 될 것</li>
</ul>
<h4 id="장소별-분석">장소별 분석</h4>
<ul>
<li>강남 3구 &gt; 유흥업소가 몰려있어서 그럴 수 있다는 가설을 확인하기 위함<ul>
<li>최초 받았던 발생 장소별 데이터를 읽어보기</li>
<li>장소 컬럼을 unique() 함수로 무엇이 있는지 확인해보기</li>
</ul>
</li>
<li>pd.DataFrame.pivot_table() 함수를 활용하여 index = 장소,. columns = 범죄명, aggfunc = np.sum 으로 장소별 범죄의 합을 보기<ul>
<li>각 범죄를 각 범죄별 최댓값으로 나누어 정규화하기</li>
<li>정규화된 각 범죄의 평균을 구함</li>
<li>droplevel로 멀티컬럼 지울 것 지우기, 맨 위가 0번</li>
</ul>
</li>
<li>heatmap으로 확인하기<ul>
<li>노상에서 많이 일어남</li>
<li>범죄가 시작되기 전 상태가 아니라, 발생한 순간의 장소임을 확인</li>
</ul>
</li>
</ul>
<h2 id="느낀점">느낀점</h2>
<p>단순히 프로그래밍을 할 줄 아는 것이 아니라, 어떤 데이터를 특정한 모양으로 보고 싶다 혹은 어떠한 이유로 이런 데이터들을 정리하고 싶다와 같이 데이터를 파고드는 힘이 있어야한다는 것을 알았다.</p>
<p><strong>이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[005. 데이터 취업 스쿨 스터디 노트_5주차_알고리즘]]></title>
            <link>https://velog.io/@julia-jh319/005.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B85%EC%A3%BC%EC%B0%A8%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@julia-jh319/005.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B85%EC%A3%BC%EC%B0%A8%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Tue, 07 May 2024 22:56:46 GMT</pubDate>
            <description><![CDATA[<h1 id="5주차">5주차</h1>
<h2 id="수강한-분량">수강한 분량</h2>
<p>알고리즘을 수강했다. 검색, 순위, 정렬 등 기본부터 특정 값(최대, 최소, 최빈 등)을 구하는 것, 그리고 알고리즘에서 가장 많이 활용되는 것 같아 보이는 재귀까지 다양한 알고리즘을 배웠다.</p>
<h2 id="각-강의별-학습한-핵심-내용-정리">각 강의별 학습한 핵심 내용 정리</h2>
<ul>
<li>algorithm<ul>
<li>일련의 절차나 방법을 공식화한 형태로 표현한 것</li>
</ul>
</li>
<li>API<ul>
<li>application Programming Interface</li>
<li>사용자가 사용하기 쉽게 이미 만들어둔 함수, 속성</li>
<li>알고리즘을 활용해 만듬<h3 id="선형-검색">선형 검색</h3>
</li>
</ul>
</li>
<li>선형으로 나열되어 있는 데이터를 순차적으로 스캔하며 원하는 값을 찾는다<ul>
<li>검색 성공 / 실패</li>
</ul>
</li>
<li>보초법<ul>
<li>마지막 인데스에 찾으려는 값을 추가해, 찾는 과정을 간략화 한다<ul>
<li>검색 성공: 마지막 이전에 값이 검색된 경우</li>
<li>검색 실패: 마지막에 값이 검색된 경우</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="이진-검색">이진 검색</h3>
<ul>
<li><strong>정렬되어 있는 자료구조</strong>에서 중앙값과의 크고 작음을 이용해 데이터를 검색한다<ul>
<li>중요 변수<ul>
<li>staIdx<ul>
<li>첫 인덱스</li>
</ul>
</li>
<li>endIdx<ul>
<li>마지막 인덱스</li>
</ul>
</li>
<li>midIdx<ul>
<li>중앙값 인덱스</li>
<li>(staIdx + endIdx) // 2</li>
</ul>
</li>
<li>midVal<ul>
<li>중앙값</li>
</ul>
</li>
</ul>
</li>
<li>의사코드<ul>
<li>검색 데이터가 주어진 데이터들의 범위 안엔 있는지 먼저 확인</li>
<li>검색 데이터가 중앙값보다 크다면 staIdx를 중앙값 인덱스 +1</li>
<li>검색 데이터가 중앙값보다 작다면 endIdx를 중앙값 인덱스 -1</li>
<li>검색 데이터가 중앙값과 같다면 midIdx를 반환</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="순위-rank">순위, Rank</h3>
<ul>
<li><p>수의 크고 작음을 이용해서 정렬되지 않은 수의 순서를 정하는 것</p>
</li>
<li><p>중요변수</p>
<ul>
<li><code>ranks = [0 for i in range(n)]</code><ul>
<li>기존 자료구조의 순위를 저장하는 자료구조, n은 기존 자료구조의 수와 동일</li>
</ul>
</li>
</ul>
</li>
<li><p>의사코드</p>
<ul>
<li>중첩구문을 활용해 기존 자료구조의 모든 숫자와 나머지의 모든 숫자와 비교한다</li>
<li>기준 숫자와 비교해 더 작은 경우 rank값에 1을 더해준다</li>
</ul>
</li>
<li><p>class를 활용한 실습사항</p>
<ul>
<li>변수 초기화</li>
<li>반복적으로 활용하는 함수를 만들고, 그것을 활용해 특정 상황마다 앞의 함수에 적용하는 함수, 그리고 적용된 결과물을 불러오는 함수를 따로 만들었다<ul>
<li>setRank</li>
<li>setMidRank</li>
<li>getMidRank</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="버블-정렬-bubble">버블 정렬, Bubble</h3>
<ul>
<li><p>처음부터 끝가지 인접하는 인덱스 값을 순차적으로 비교하여 큰 숫자를 가장 끝으로 옮기는 알고리즘</p>
</li>
<li><p>중요변수</p>
<ul>
<li>tmp 활용해 두 자료를 맞교환할 수 있다. 그러나 아래와 같이 python에서는 swap에 유용한 구조가 있다<ul>
<li><code>tmp = a; a = b; b = tmp</code></li>
<li><code>a, b = b, a</code></li>
</ul>
</li>
</ul>
</li>
<li><p>의사코드</p>
<ul>
<li>중첩 반복문을 활용해 처음 두 변수를 비교해 더 큰 수가 오른쪽에 오게 한다.</li>
<li>한 싸이클을 다 돌고 나면 다시 처음부터 비교하는데 이때 지난 싸이클에서 비교한 제일 마지막 숫자는 제외한다</li>
</ul>
</li>
<li><p>깊은 복사</p>
<pre><code>import copy
</code></pre></li>
</ul>
<p>def 함수명(데이터, deepCopy = True):
    if deepCopy:
        cns = copy.copy(데이터)
    else:
        cns = 데이터 </p>
<pre><code>
### 삽입 정렬, Insert
- 정렬되어 있는 자료 배열과 하나씩 비교해 정렬 위치를 찾는 알고리즘
- 중요변수
    - cNum
        - 현재 비교 기준 변수
    - i2
        - 현재 비교 기준 변수와 비교할 앞 변수 인덱스
        - 이 인덱스를 가진 자료값이 cNum과 비교하여 오름차순일 때는 크다면, 내림차순일 때는 작다면 i2 + 1 인덱스를 가진 자료값에 이 인덱스 자료값을 넣어주고, i2값은 하나 빼어 0까지 변화한다.
        - 만약 비교 후 변화가 없다면 i2보다 작은 인덱스를 가진 값들은 이미 정렬되어 있으므로 비교X
- 의사코드
    - 두 번째 요소부터 마지막까지 범위인 반복문을 만들어, 현재 비교 기준 변수 인덱스로 할당한다.
    - 현재 비교 기준 변수 인덱스 왼쪽에 존재하는 변수와 값을 비교하여 변화해야 하는 경우 비교 인덱스 + 1 위치에 비교 인덱스의 자료값을 넣어주고, 비교 인덱스는 하나를 빼어 더 왼쪽값을 비교한다. 이때 비교 인덱스가 0보다 크거나 같을 때까지를 조건으로 둔다

- 함수에서 동일 데이터를 옵션만 바꾸어 활용하고 싶을 때를 위해 **옵션만 바꾸는 함수**를 class 내부에 선언해주기도 함</code></pre><p>class 클래스명:
    def <strong>init</strong>(self, 데이터, asc = True):
        self.data = 데이텆
        self.isAsc = asc</p>
<pre><code>def isAscending(self, flag):
    self.isAsc = flag</code></pre><p>객체명 = 클래스명.함수(데이터)</p>
<h1 id="위에서-잔뜩-활용한-객체명에-특정-옵션만-바꾸어-마저-활용할-수-있다">위에서 잔뜩 활용한 객체명에 특정 옵션만 바꾸어 마저 활용할 수 있다</h1>
<p>객체명.isAscending(False)</p>
<pre><code>
### 선택 정렬, Select
- 주어진 리스트 중에 최솟값을 찾아 그 값을 맨 앞에 위치한 값과 교체하는 방식으로 자료를 정리하는 알고리즘
- 중요변수
    - minIdx
        - 최솟값 인덱스
    - tempNum
        - 기준값과 최소인덱스를 교환할 때 사용하는 임시변수
- 의사코드
    - 중첩 반복문을 활용하여, 주어진 자료 처음부터 마지막 -1 까지 반복문은 비교 기준 인덱스 값을, 비교 기준인덱스 + 1부터 마지막까지 반복하는 내부 반복문은 비교 인덱스값으로 활용한다.
    - 첫번째 반복문을 시작할 때 반복문에 활용하는 i값을 minIdx 초기값으로 할당한다.
    - 주어진 값을 상호 비교하여 비교 기준 인덱스의 자료값이 비교 인덱스 자료값보다 크다면 minIdx에 비교 인덱스 값을 할당한다
    - 내부 반복문이 완료되면, i번째 값과 minIdx번째 값을 상호교환한다.

- 깊은 복사를 함수 외부에서도 활용할 수 있음
    - 아래와 같이 활용할 경우 원본 데이터 훼손을 막을 수 있음</code></pre><p>import copy
result = 클래스명.함수명(copy.deepcopy(데이터))</p>
<p>```</p>
<h3 id="최댓값-max">최댓값, Max</h3>
<ul>
<li>자료구조에서 가장 큰 값을 찾는다.</li>
<li>중요변수<ul>
<li>maxNum<ul>
<li>가장 큰 수</li>
<li>임의로 자료구조의 가장 첫 번째 요소를 할당</li>
</ul>
</li>
</ul>
</li>
<li>의사코드<ul>
<li>maxNum에 자료구조 가장 첫 번째 요소를 할당한다</li>
<li>maxNum을 주어진 자료구조의 두 번째 요소부터 마지막 요소까지 비교하여, maxNum이 더 작을 경우 비교 요소를 maxNum에 할당한다</li>
</ul>
</li>
</ul>
<h3 id="최솟값-min">최솟값, Min</h3>
<ul>
<li>자료구조에서 가장 작은 값을 찾는다</li>
<li>중요변수<ul>
<li>minNum<ul>
<li>가장 작은 수</li>
<li>임의로 자료구조의 가장 첫 번째 요소를 할당</li>
</ul>
</li>
</ul>
</li>
<li>의사코드<ul>
<li>minNum에 자료구조 가장 첫 번째 요소를 할당한다</li>
<li>minNum을 주어진 자료구조의 두 번째 요소부터 마지막 요소까지 비교하여, minNum이 더 클 경우 비교 요소를 minNum에 할당한다</li>
</ul>
</li>
</ul>
<h3 id="최빈값">최빈값,</h3>
<ul>
<li>자료구조에서 빈도수가 가장 많은 데이터</li>
<li>중요변수<ul>
<li>indexes<ul>
<li>자료구조에 포함된 데이터값을 인덱스로 두고 빈도를 체크할 리스트</li>
</ul>
</li>
<li>maxAlgorithm<ul>
<li>최댓값 알고리즘을 활용해 원래 자료구조에서 가장 큰 값을 구하고, 이후에 새로운 리스트에서 가장 큰 값을 구하는데 활용한다.</li>
</ul>
</li>
</ul>
</li>
<li>의사코드<ul>
<li>자료구조에서 최댓값 알고리즘을 활용해 가장 큰값을 구해, 0부터 가장 큰 값까지 0이 배정된 새로운 리스트를 만든다</li>
<li>자료구조 데이터가 나올 때 마다 새로운 리스트의 해당 인덱스값에 1을 더해준다.</li>
<li>최댓값 알고리즘을 활용해 새로운 리스트에서 가장 큰 값의 인덱스를 구한다.</li>
</ul>
</li>
</ul>
<h3 id="근삿값-near">근삿값, Near</h3>
<ul>
<li>자료구조에서 특정 값(참값)에 가장 가까운 값</li>
<li>중요변수<ul>
<li>inputNum<ul>
<li>찾고 싶은 숫자</li>
</ul>
</li>
</ul>
</li>
<li>의사코드<ul>
<li>주어진 자료구조 각 데이터에서 찾고 싶은 숫자를 빼고, 절대값 함수 abs() 처리를 한다</li>
<li>위의 처리를 한 각 값을 비교하여 가장 작은 값을 가진 숫자를 찾아 출력한다</li>
<li>만약 근삿값을 이용해 새로운 값을 기존 리스트에 추가하는 경우에는 제일 끝에 있는 것부터 하나씩 뒤로 밀어두고, 근사값 인덱스 자리에 새로운 값을 추가한다</li>
</ul>
</li>
</ul>
<h3 id="평균-average">평균, Average</h3>
<ul>
<li>여러 수나 양의 중간값을 갖는 수</li>
<li>중요변수<ul>
<li>total<ul>
<li>모든 수의 합</li>
</ul>
</li>
<li>len(자료구조)<ul>
<li>모든 수의 갯수</li>
</ul>
</li>
<li>cnt<ul>
<li>조건을 만족한 모든 수의 갯수</li>
</ul>
</li>
</ul>
</li>
<li>의사코드<ul>
<li>반복문을 활요앻 주어진 숫자를 다 더한다</li>
<li>모든 수의 합을 모든 수의 갯수로 나눈다</li>
<li>만약 특정 조건을 만족해야 한다면, 조건을 만족한 경우 추가되는 새로운 리스트 자료구조를 만들어 두어도 된다. 혹은 cnt 변수를 이용해 모든 수의 갯수를 저장해두어도 괜찮다.<ul>
<li>특정 조건 중 정수들의 평균을 구할 때<ul>
<li>주어진 숫자 - int(주어진 숫자) == 0 을 조건으로 두기</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="재귀-recursion">재귀, Recursion</h3>
<ul>
<li>나 자신을 다시 호출하는 것</li>
<li>의사코드<ul>
<li>특정 조건에서만 나 스스로를 부른다</li>
<li>이때 인수값을 하나씩 빼주는 등 변화를 주어야 한다</li>
<li>영원히 반복되지 않도록 특정 조건2일 때 반복되지 않는 특정 값을 반환한다</li>
</ul>
</li>
<li>유클리드 호제법<ul>
<li>두 자연수 n1, n2에 대해 (n1 &gt; n2) n1을 n2로 나눈 나머지를 r이라고 할 때, n1과 n2의 최대공약수는 n2와 r의 최대공약수와 같다</li>
</ul>
</li>
</ul>
<h3 id="하노이의-탑-tower-of-hanoi">하노이의 탑, Tower of hanoi</h3>
<ul>
<li>퍼즐 게임의 일종으로 세 개의 기둥을 이용해, 원판을 다른 기둥으로 옮기면 된다.<ul>
<li>한 번에 한 개의 원판만 옮길 수 있다</li>
<li>큰 원판이 작은 원판 위에 있어서는 안 된다</li>
</ul>
</li>
<li>중요변수<ul>
<li>discCnt<ul>
<li>원판 갯수</li>
</ul>
</li>
<li>fromBar<ul>
<li>출발 기둥</li>
</ul>
</li>
<li>toBar<ul>
<li>도착 기둥</li>
</ul>
</li>
<li>viaBar<ul>
<li>경유 기둥</li>
</ul>
</li>
</ul>
</li>
<li>의사코드<ul>
<li>만약 디스크 갯수가 1개라면 그 디스크를 출발 기둥에서 도착 기둥으로 옮겨라</li>
<li>만약 디스크 갯수가 1개보다 많다면<ul>
<li>원판 갯수-1 개들을 출발 기둥에서 경유 기둥으로 옮겨라 -&gt; 재귀 함수로 반복</li>
<li>제일 큰 원판을 출발 기둥에서 도착 기둥으로 옮겨라</li>
<li>원판 갯수-1 개들을 경유 기둥에서 도착 기둥으로 옮겨라 -&gt; 재귀 함수로 반복</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="병합-정렬-merge">병합 정렬, Merge</h3>
<ul>
<li>자료구조를 분할하고 각각의 분할된 자료구조를 정렬한 후 다시 병합하여 정렬한다</li>
<li>상대적으로 속도가 빠르다</li>
<li>중요변수<ul>
<li>midIdx<ul>
<li>중간 인덱스 값</li>
</ul>
</li>
<li>leftNums<ul>
<li>0부터 midIdx까지의 값들 모음</li>
</ul>
</li>
<li>rightNums<ul>
<li>midIdx부터 끝까지의 값들 모음</li>
</ul>
</li>
<li>mergeNums<ul>
<li>정렬된 값을 저장할 리스트</li>
</ul>
</li>
<li>leftIdx<ul>
<li>왼쪽 숫자들의 인덱스</li>
<li>처음은 0이고, 한 묶음이 끝나면 다시 0</li>
</ul>
</li>
<li>rightIdx<ul>
<li>오른쪽 숫자들의 인덱스</li>
<li>처음은 0이고, 한 묶음이 끝나면 다시 0</li>
</ul>
</li>
</ul>
</li>
<li>의사코드<ul>
<li>만약 주어진 데이터의 길이가 2보다 작다면 을 반환</li>
<li>주어진 자료의 길이 중간값을 midIdx로 둔다</li>
<li>왼쪽 숫자와 오른쪽 숫자로 나눈다</li>
<li>왼쪽 숫자가 오른쪽 숫자보다 작다면 <code>왼쪽 숫자[왼쪽인덱스]</code>를 정렬된 값에 추가한다</li>
<li>만약 오른쪽 숫자가 더 크다면 <code>오른쪽 숫자[오른쪽인덱스]</code>를 정렬된 값에 추가한다</li>
<li>왼쪽인덱스가 왼쪽 숫자모음 길이보다 커지거나, 오른쪽인덱스가 오른쪽 숫자모음길이 보다 커지면 루프를 나와, 정렬된 값에 남은 숫자들을 이어 붙인다</li>
<li>만약 순서가 바뀐다면, <code>asc = True</code> 와 같은 옵션을 넣어주어야 하며, 재귀로 부를 때에도 옵션에 <code>asc = asc</code> 등으로 명시를 해주어야 한다</li>
</ul>
</li>
</ul>
<h3 id="퀵-정렬-quick">퀵 정렬, Quick</h3>
<ul>
<li><p>기준 값보다 작은 값과 큰 값으로 분리한 후 다시 합친다</p>
</li>
<li><p>중요변수</p>
<ul>
<li>midIdx<ul>
<li>기준 인덱스로, 주어진 자료의 길이를 반으로 나눈 몫으로 할당</li>
</ul>
</li>
<li>midVal<ul>
<li>기준 인덱스의 자료값</li>
</ul>
</li>
<li>smallNums<ul>
<li>기준 값보다 작은 숫자들의 리스트</li>
</ul>
</li>
<li>sameNums<ul>
<li>기준 값과 같은 숫자들의 리스트</li>
</ul>
</li>
<li>bigNums<ul>
<li>기준 값보다 큰 숫자들의 리스트</li>
</ul>
</li>
</ul>
</li>
<li><p>의사코드</p>
<ul>
<li>주어진 자료의 길이가 2보다 작다면 자료를 반환한다</li>
<li>주어진 자료의 값이 기준값보다 작으면 smallNums에 추가</li>
<li>주어진 자료의 값이 기준값과 같으면 sameNums에 추가</li>
<li>주어진 자료의 값이 기준값보다 크면 bigNums에 추가</li>
<li>smallNums에 재귀적으로 적용한 것에 sameNums를 더하고, bigNums에 재귀적으로 적용한 것을 더하여 반환한다</li>
</ul>
</li>
</ul>
<h3 id="연습문제">연습문제</h3>
<p>*<em>+ 추후에 추가
*</em></p>
<h2 id="느낀점">느낀점</h2>
<p><strong>이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[004. 데이터 취업 스쿨 스터디 노트_4주차_자료구조]]></title>
            <link>https://velog.io/@julia-jh319/004.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B84%EC%A3%BC%EC%B0%A8%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@julia-jh319/004.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B84%EC%A3%BC%EC%B0%A8%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Tue, 07 May 2024 22:56:35 GMT</pubDate>
            <description><![CDATA[<h1 id="4주차">4주차</h1>
<h2 id="수강한-분량">수강한 분량</h2>
<p>자료구조를 수강했다. 자료구조에서는 리스트, 튜플, 딕셔너리를 배웠고, 각 자료구조마다 존재하는 함수도 있지만 슬라이싱, 정렬 등은 비슷하게 작용했다. 다만 딕셔너리는 인덱스가 아니라 키로 값들을 구분하는 것을 유의해야 했다.</p>
<h2 id="각-강의별-학습한-핵심-내용-정리">각 강의별 학습한 핵심 내용 정리</h2>
<ul>
<li><p>자료구조</p>
<ul>
<li>컨테이너 자료형의 데이터 구조<ul>
<li>컨테이너 자료형<ul>
<li>여러 개의 데이터가 묶여있는 자료형</li>
<li>리스트, 튜플, 딕셔너리, 셋트 존재</li>
<li>변수명을 복수형으로 적는 경향있다<h3 id="리스트">리스트</h3>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>리스트</p>
<ul>
<li>배열과 같이 여러 개의 데이터를 나열한 자료구조</li>
</ul>
</li>
<li><p>[]로 선언하고, 데이터 구분은 ,를 이용한다</p>
</li>
<li><p>숫자, 문자(열), 논리형 등 모든 기본 데이터를 같이 저장할 수 있다</p>
</li>
<li><p>리스트에 또 다른 컨테이너 자료형 데이터를 저장할 수 있다</p>
</li>
<li><p>인덱스</p>
<ul>
<li>아이템에 자동으로 부여되는 번호표</li>
</ul>
</li>
<li><p>리스트 아이템은 인덱스를 이용해 조회가 가능하다</p>
<ul>
<li>변수명[인덱스번호]를 이용해 아이템에 접근 가능하다</li>
</ul>
</li>
<li><p>리스트 길이</p>
<ul>
<li>리스트 저장된 아이템 갯수</li>
<li>len(리스트변수)</li>
</ul>
</li>
<li><p>레퍼런스 변수</p>
<ul>
<li>메모리 주소를 가지고 멀리 있는 리스트 값을 참조하는 것</li>
<li>리스트의 레퍼런스 변수: 리스트를 선언할 때 사용한 변수명</li>
</ul>
</li>
<li><p>for문의 range(len(리스트변수))를 활용하면 리스트의 아이템 조회가 쉽다</p>
<ul>
<li><code>for item in range(lists)</code></li>
</ul>
</li>
<li><p>for문에 리스트변수를 활용하면 리스트 아이템 조회가 쉽다</p>
<ul>
<li><code>for item in lists</code></li>
</ul>
</li>
<li><p>len(변수)</p>
<ul>
<li>변수가 문자열일 경우, 문자열 길이도 알 수 있다</li>
</ul>
</li>
<li><p>for문을 활용한 리스트 아이템 참조하기</p>
<ul>
<li><code>for 지역변수 in range(len(리스트변수명)):</code><ul>
<li>리스트변수 내부 아이템의 인덱스를 참조하는 방법</li>
</ul>
</li>
<li><code>for 지역변수 in 리스트변수명:</code><ul>
<li>리스트변수 내부 아이템을 직접적으로 참조하는 방법</li>
</ul>
</li>
<li><strong>리스트 내부</strong>에 리스트가 또 있는 경우<ul>
<li><code>for 지역변수1, 지역변수2 in 리스트변수명:</code></li>
<li>지역변수1은 리스트내부의 첫 번째 요소를, 지역변수2는 리스트내부의 두 번째 요소를 가리킨다</li>
</ul>
</li>
<li>조건문을 함께 활용할 경우<pre><code>for 지역변수 in 리스트변수명:
if 조건문: continue  # 조건에 해당하면 아래를 수행하지 않고 다음 단계의 for문을 수행한다
수행문 # 조건에 해당하지 않을 경우 수행하는 문구</code></pre></li>
</ul>
</li>
<li><p>while문을 활용한 리스트 아이템 참조하기</p>
<ul>
<li>조건을 횟수로 제한하고, 반복문 말미에 횟수 변수에 1을 더하는 방법</li>
<li>boolean값을 가진 flag변수를 활용하여 반복문 말미에 횟수 변수에 1을 더하고, 횟수 변수가 어느 값인 경우 flag에 false를 주는 방법</li>
<li>True 조건문을 활용하여 반복문 말미에 횟수 변수에 1을 더하고, 횟수 변수가 어느 값인 경우 break를 주는 방법</li>
</ul>
</li>
<li><p>enumerate()함수</p>
<ul>
<li>인덱스와 아이템을 한 번에 조회하는 함수</li>
<li><code>for idx, value in enumerate(리스트변수명):</code><ul>
<li>인덱스변수, 값변수 순서로 배정된다</li>
</ul>
</li>
<li>리스트변수 뿐 아니라, 문자열로도 활용이 된다</li>
</ul>
</li>
</ul>
<ul>
<li><p>리스트에 아이템 추가하기</p>
<ul>
<li>append() 함수<ul>
<li><code>리스트변수명.append(새로운값)</code></li>
<li><strong>마지막 인덱스</strong>에 아이템을 추가한다.</li>
</ul>
</li>
<li>insert() 함수<ul>
<li><code>리스트변수명.insert(특정인덱스, 새로운값)</code></li>
<li><strong>특정 인덱스</strong>에 아이템을 추가한다.</li>
</ul>
</li>
</ul>
</li>
<li><p>리스트 아이템 삭제하기</p>
<ul>
<li>pop() 함수<ul>
<li><code>리스트변수명.pop()</code><ul>
<li><strong>마지막 인덱스</strong>에 해당하는 아이템을 삭제한다.</li>
</ul>
</li>
<li><code>리스트변수명.pop(특정인덱스)</code><ul>
<li><strong>특정 인덱스</strong>에 해당하는 아이템을 삭제한다.</li>
</ul>
</li>
<li>삭제하는 데이터를 반환한다.</li>
</ul>
</li>
<li>remove() 함수<ul>
<li><code>리스트변수명.remove(아이템)</code><ul>
<li><strong>특정 아이템</strong>을 삭제한다.</li>
</ul>
</li>
<li>1개의 아이템만 삭제할 수 있으므로, 여러 개를 삭제하고 싶다면 while문을 활용하는 것이 좋다.<pre><code>while 아이템 in 리스트변수명:
리스트변수명.remove(아이템)</code></pre></li>
</ul>
</li>
</ul>
</li>
<li><p>리스트 연결하기</p>
<ul>
<li>extend() 함수<ul>
<li><code>리스트변수명1.extend(리스트변수명2)</code></li>
<li>리스트변수명1에 리스트변수명2를 추가한다.</li>
</ul>
</li>
<li>덧셈 연산자 활용<ul>
<li><code>리스트변수명1 + 리스트변수명2</code></li>
<li>리스트변수명1과 리스트변수명2가 이어진 새로운 변수가 만들어진다.</li>
</ul>
</li>
</ul>
</li>
<li><p>리스트 정렬하기</p>
<ul>
<li>sort() 함수<ul>
<li>오름차순으로 정렬한다</li>
<li>sort(reverse = True)<ul>
<li>내림차순으로 정렬</li>
</ul>
</li>
</ul>
</li>
<li>reverse() 함수<ul>
<li>주어진 순서를 뒤집는다</li>
<li>변수명.reverse()</li>
</ul>
</li>
</ul>
</li>
<li><p>리스트 슬라이싱</p>
<ul>
<li><code>[n:m:s]</code><ul>
<li>n에서 부터 m-1까지 s칸씩</li>
<li>숫자가 없을 경우 n자리는 맨 처음부터, m자리는 맨 끝까지, s는 1이 디폴트</li>
<li>숫자가 음수일 경우 뒤쪽에서부터 계산, 이때 -1이 맨 끝자리</li>
</ul>
</li>
<li>문자열 슬라이싱<ul>
<li>리스트 슬라이싱과 동일</li>
</ul>
</li>
<li>슬라이싱을 이용해 아이템 변경도 가능</li>
<li>slice() 함수<ul>
<li><code>변수명[slice(n, m)]</code></li>
</ul>
</li>
</ul>
</li>
<li><p>리스트 곱셈 연산</p>
<ul>
<li>아이템이 반복된다</li>
</ul>
</li>
<li><p>리스트 아이템 위치 찾기</p>
<ul>
<li>index() 함수<ul>
<li><code>변수명.index(값, n, m)</code></li>
<li>만약 변수 내부에 값이 복수개 존재할 경우 맨 앞의 하나만 반환한다</li>
<li>n에서 m까지의 범위 내에서 주어진 값의 인덱스를 찾는다. 생략시 처음부터 끝까지가 디폴트</li>
</ul>
</li>
</ul>
</li>
<li><p>리스트에서 특정 아이템 갯수 알아내기</p>
<ul>
<li>count() 함수<ul>
<li><code>변수명.count(값)</code></li>
</ul>
</li>
</ul>
</li>
<li><p>특정 아이템 삭제</p>
<ul>
<li><code>del 변수명[n]</code><ul>
<li>n자리에 인덱스, 슬라이싱 적용 가능</li>
</ul>
</li>
</ul>
</li>
<li><p>random 패키지에 sample 함수 활용</p>
<ul>
<li>random.sample(범위, 갯수)</li>
<li>리스트로 반환</li>
</ul>
</li>
</ul>
<h3 id="튜플">튜플</h3>
<ul>
<li><p>튜플</p>
<ul>
<li>리스트와 비슷하지만 아이템 변경(수정, 삭제)이 불가능</li>
<li>() 이용해 선언하고, ,를 이용해 구분한다<ul>
<li>아이템이 한 개일 경우 아이템 뒤에 콤마를 추가하면 튜플로 선언이 가능<ul>
<li><code>(아이템, )</code></li>
</ul>
</li>
</ul>
</li>
<li>소괄호 없이 아이템을 , 이용해 나열해도 튜플로 선언됨</li>
<li>숫자, 문자(열), 논리형 등을 같이 저장할 수 있음</li>
<li>튜플 내 또 다른 컨테이너 자료형 데이터 저장이 가능하다</li>
<li>튜플과 리스트는 서로 변환이 가능하다<ul>
<li>tuple() 함수<ul>
<li><code>tuple(변수명)</code></li>
</ul>
</li>
<li>list() 함수<ul>
<li><code>list(변수명)</code></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>튜플 아이템 조회</p>
<ul>
<li>인덱스를 활용한 슬라이싱을 이용</li>
</ul>
</li>
<li><p>특정 아이템 존재 유/무</p>
<ul>
<li>in, not in 키워드 활용<ul>
<li>값 in 변수명<ul>
<li>변수내에 값과 동일한 아이템이 있으면 True</li>
</ul>
</li>
<li>값 not in 변수명<ul>
<li>변수내에 값과 동일한 아이템이 없으면 True</li>
</ul>
</li>
<li>문자열에도 활용 가능</li>
</ul>
</li>
</ul>
</li>
<li><p>튜플 길이</p>
<ul>
<li><code>len(튜플변수명)</code></li>
</ul>
</li>
<li><p>튜플 결합</p>
<ul>
<li><ul>
<li>연산자를 이용해 두 튜플을 결합해 새로운 튜플을 선언할 수 있다</li>
</ul>
</li>
<li>리스트의 extend() 함수 사용 불가능</li>
</ul>
</li>
<li><p>튜플 슬라이싱</p>
<ul>
<li>리스트와 동일한 방식으로 슬라이싱 가능</li>
<li>슬라이싱 이용한 데이터 변경은 불가능</li>
<li>다만 리스트를 슬라이싱 이용해 튜플의 아이템으로 변경할 수 있고, 결과는 여전히 리스트이다.</li>
<li>slice() 함수 활용 가능</li>
</ul>
</li>
<li><p>튜플 아이템 정렬</p>
<ul>
<li>튜플을 리스트로 변환 후, sort() 함수를 활용해 정렬, tuple() 함수를 이용해 재변환</li>
<li>sorted() 함수<ul>
<li><code>sorted(변수명)</code><ul>
<li>원본 자료는 그대로, 새롭게 리스트 자료형을 반환</li>
<li>key, reverse 옵션은 sort() 함수와 동일</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>튜플과 for문</p>
<ul>
<li>리스트와 동일한 방법 활용</li>
</ul>
</li>
<li><p>튜플과 while문</p>
<ul>
<li>리스트와 동일한 방법 활용</li>
</ul>
</li>
</ul>
<h3 id="딕셔너리">딕셔너리</h3>
<ul>
<li><p>딕셔너리</p>
<ul>
<li>key와 value를 이용해 자료를 관리</li>
<li>key<ul>
<li>중복X</li>
<li>리스트, 튜플의 index와 비슷한 역할, 내가 부여하는 값</li>
<li>immutable값만 올 수 있다.(변경 불가능한)<ul>
<li>ex) tuple</li>
</ul>
</li>
</ul>
</li>
<li>{}을 이용해 선언하고, : 이용해 key와 value를 연결하고, ,를 이용해 아이템 나열<ul>
<li><code>{key : value, ...}</code></li>
<li>숫자, 문자(열), 논리형, 컨테이너 자료형도 올 수 있다</li>
</ul>
</li>
</ul>
</li>
<li><p>딕셔너리 조회</p>
<ul>
<li><code>변수명[key]</code>를 활용해 value를 조회한다<ul>
<li>없는 key를 넣으면 Error 발생</li>
</ul>
</li>
<li><code>변수명.get(key)</code>를 활용해 value를 조회한다<ul>
<li>없는 key를 넣으면 None을 반환한다</li>
</ul>
</li>
<li>전체값 조회<ul>
<li>keys() 함수<ul>
<li><code>변수명.keys()</code></li>
<li>타입: dict_keys</li>
<li>리스트 형태로 반환</li>
</ul>
</li>
<li>values() 함수<ul>
<li><code>변수명.values()</code></li>
<li>타입: dict_values</li>
<li>리스트 형태로 반환</li>
</ul>
</li>
<li>items() 함수<ul>
<li><code>변수명.items()</code></li>
<li>타입: dict_items</li>
<li>tuple 형태로 저장되어 있음</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>딕셔너리 추가</p>
<ul>
<li><code>변수명[key] = value</code>형태로 아이템을 추가<ul>
<li>이미 존재하는 key일 경우 value값이 수정됨</li>
</ul>
</li>
</ul>
</li>
<li><p>딕셔너리 수정</p>
<ul>
<li><code>변수명[존재하는 key] = 새로운 값</code></li>
</ul>
</li>
<li><p>딕셔너리 삭제</p>
<ul>
<li><code>del 변수명[key]</code></li>
<li><code>변수명.pop(key)</code><ul>
<li>삭제된 값이 반환된다</li>
</ul>
</li>
</ul>
</li>
<li><p>딕셔너리</p>
<ul>
<li>in, not in 키워드<ul>
<li>key 존재 유무를 판단</li>
</ul>
</li>
<li>len() 함수</li>
<li>clear()<ul>
<li>모든 아이템을 삭제</li>
<li>아이템 갯수가 0인 dict만 남는다<h3 id="연습문제">연습문제</h3>
</li>
</ul>
</li>
</ul>
</li>
<li><p>*+ 추후에 추가</p>
</li>
<li><p>*</p>
<h2 id="느낀점">느낀점</h2>
</li>
</ul>
<p><strong>이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[003. 데이터 취업 스쿨 스터디 노트_3주차_기초 수학]]></title>
            <link>https://velog.io/@julia-jh319/003.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B83%EC%A3%BC%EC%B0%A8%EA%B8%B0%EC%B4%88-%EC%88%98%ED%95%99</link>
            <guid>https://velog.io/@julia-jh319/003.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B83%EC%A3%BC%EC%B0%A8%EA%B8%B0%EC%B4%88-%EC%88%98%ED%95%99</guid>
            <pubDate>Tue, 23 Apr 2024 12:12:31 GMT</pubDate>
            <description><![CDATA[<h1 id="3주차">3주차</h1>
<h2 id="수강한-분량">수강한 분량</h2>
<p>일정이 밀려 2주차에 들었어야 하는 기초 수학을 3주차에 듣게 되었다. 우선 기본 개념강의를 우선적으로 듣고 문제 강의는 하루에 쪼개어 들어야겠다. 순수하게 활용할 수 있는 시간 자체가 별로 없다는 기분이다.</p>
<h2 id="각-강의별-학습한-핵심-내용-정리">각 강의별 학습한 핵심 내용 정리</h2>
<h3 id="1-약수-소수-소인수-공약수-공배수">1. 약수 소수 소인수 공약수 공배수</h3>
<ul>
<li><p>약수</p>
<ul>
<li>어떤 수를 나누어 떨어지게 하는 수</li>
<li>나누어서 나머지가 0인 숫자</li>
</ul>
</li>
<li><p>소수</p>
<ul>
<li>1과 그 수 자신만을 약수로 가지는 수</li>
<li>1은 제외</li>
<li>중첩 반복문으로 그 숫자보다 작은 숫자로 나누어 나머지가 0이 아닌것으로만 구성된 것</li>
</ul>
</li>
<li><p>소인수</p>
<ul>
<li>약수 중에서 소수인 숫자</li>
</ul>
</li>
<li><p>소인수분해</p>
<ul>
<li>1보다 큰 정수를 소인수의 곱으로 나타낸 것</li>
<li>주어진 수를 제일 작은 소인수로 반복적으로 나눈다</li>
<li>소인수분해를 이용하면 최대공약수, 공약수를 구할 수 있다<ul>
<li>공통인 소인수 거듭제곱에서 지수가 작은 수를 모두 곱한 것</li>
<li>모든 수를 공통으로 나누어 떨어지는 것들을 구해 나눗셈에 사용된 숫자를 모두 곱한 것</li>
</ul>
</li>
<li>소인수분해를 이용하면 최소공배수, 공배수를 구할 수 있다<ul>
<li>공통인 소인수 거듭제곱에서 지수가 크고 공통이 아닌 수를 모두 곱한 것</li>
<li>모든 수를 공통으로 나누어 더이상 공통수로 나눌 수 없을 때 나눈 수들과 나눈 결과값들을 전부 곱한 수</li>
</ul>
</li>
</ul>
</li>
<li><p>공약수</p>
<ul>
<li>두 개 이상의 수에서 공통된 약수</li>
</ul>
</li>
<li><p>최대공약수</p>
<ul>
<li>공약수 중 가장 큰 수</li>
<li>유크리드 호제법<ul>
<li>x, y의 최대공약수는 y, x%y의 최대공약수와 같다</li>
</ul>
</li>
</ul>
</li>
<li><p>공배수</p>
<ul>
<li>두 개 이상의 수에서 공통된 배수</li>
</ul>
</li>
<li><p>최소공배수</p>
<ul>
<li>공배수 중 가장 작은 수</li>
<li>주어진 수를 곱한 것에 최대공약수로 나눈 것의 몫</li>
<li>주어진 수가 3개 이상이면, 일단 두 개의 최소공배수를 구한 후, 그것과 세 번째 수의 공배수를 구한다</li>
</ul>
</li>
<li><p>리스트</p>
<ul>
<li>리스트변수.count(a)<ul>
<li>리스트 변수 내에 a라는 것이 몇 개가 있는지 반환</li>
</ul>
</li>
<li>리스트변수.append(a)<ul>
<li>리스트변수에 a를 추가하기</li>
</ul>
</li>
<li>리스트변수.remove(a)<ul>
<li>리스트변수 내에 a를 없애기</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="2-진법">2. 진법</h3>
<ul>
<li>진법<ul>
<li>특정 숫자 몇 개를 사용해 수를 표시하는 방법</li>
</ul>
</li>
<li>2진수<ul>
<li>0, 1</li>
</ul>
</li>
<li>8진수<ul>
<li>0~7</li>
</ul>
</li>
<li>10진수<ul>
<li>0~9</li>
</ul>
</li>
<li>16진수<ul>
<li>0<del>9와 A</del>F</li>
</ul>
</li>
<li>변환법<ul>
<li>10진수 &gt; X 진수<ul>
<li>주어진 수를 X로 나누고 가장 마지막 나머지부터 매 순간 있던 나머지를 연속으로 나열한 값</li>
<li>print(&#39;{숫자:#b}&#39;) 등의 형태로도 가능함</li>
<li># 없이 사용하면 앞에 몇 진수인지 표시가 나오지 않는다.</li>
<li>bin()<ul>
<li>binary, 2진수로 바꾸는 함수</li>
<li>바꾼 값 앞에 0b표시가 나오고, 문자열임</li>
<li>format(숫자, &#39;#b&#39;)로도 가능하다</li>
</ul>
</li>
<li>oct()<ul>
<li>octal, 8진수로 바꾸는 함수</li>
<li>바꾼 값 앞에 0o표시가 나오고, 문자열임</li>
<li>format(숫자, &#39;#o&#39;)로도 가능하다</li>
</ul>
</li>
<li>hex()<ul>
<li>hexadecimal, 16진수로 바꾸는 함수</li>
<li>바꾼 값 앞에 0x표시가 나오고, 문자열임</li>
<li>format(숫자, &#39;#x&#39;)로도 가능하다</li>
</ul>
</li>
</ul>
</li>
<li>X진수 &gt; 10진수<ul>
<li>각 자릿수에 있는 숫자 * X ^ 자릿수(제일 오른쪽이 0)을 다 더한다</li>
<li>int(&#39;숫자&#39;, X)<ul>
<li>X진수의 숫자를 10진수로 바꾸어준다</li>
</ul>
</li>
</ul>
</li>
<li>2진수 &gt; 8진수<ul>
<li>뒤에서부터 3자리씩 구분하고 빈 자리는 0으로 채운다</li>
<li>칸마다 각 자릿수에 있는 숫자 * 2 ^ 자릿수(제일 오른쪽이 0)을 다 더하고, 합의 수를 나열한다</li>
</ul>
</li>
<li>2진수 &gt; 16진수<ul>
<li>뒤에서부터 4자리씩 구분하고 빈 자리는 0으로 채운다</li>
<li>칸마다 각 자릿수에 있는 숫자 * 2 ^ 자릿수(제일 오른쪽이 0)을 다 더하고, 합의 수를 나열한다</li>
</ul>
</li>
<li>모든 변환 함수는 X진수에서 X진수로 변환이 가능하다</li>
</ul>
</li>
</ul>
<h3 id="3-수열">3. 수열</h3>
<ul>
<li>수열<ul>
<li>규칙성을 갖고 나열된 수들</li>
<li>${a_n}$: 일반항</li>
<li>n 정의역: 자연수</li>
<li>${{a_n}}$: 수열이라는 표시</li>
<li>특정항은 특정항까지의 합에서 특정학 이전의 항까지의 합과 같다</li>
<li>${S_n = a_1 + a_2 + a_3 + ...}$<ul>
<li>${a_n = S_n - S_{(n-1)}}$        ${단, n &gt;= 2이고, a_1 = S_1}$</li>
</ul>
</li>
</ul>
</li>
<li>등차수열<ul>
<li>연속된 두 항의 차이가 일정한 수열</li>
<li>${a_n = a_1 + (n-1)\times d}$</li>
<li>등차 중항<ul>
<li>연속된 세 항에서 가운데 항</li>
<li>앞 뒤 항을 더하고 반으로 나누면 등차중항이 나온다</li>
</ul>
</li>
<li>${S_n = n(a_1 + a_n)/2}$</li>
</ul>
</li>
<li>등비수열<ul>
<li>연속된 두 항의 비가 일정한 수열</li>
<li>${a_n = a_1 \times r^{(n-1)}}$</li>
<li>등비 중항<ul>
<li>연속된 세 항에서 가운데 항</li>
<li>앞항과 뒷항을 곱하고 루트를 씌우면 등차중항이 나온다</li>
</ul>
</li>
<li>${S_n = a_1 \times (1 - (r^n)) / (1-r) = a_1 \times ((r^n) - 1) / (r - 1)}$</li>
</ul>
</li>
<li>시그마<ul>
<li>${\Sigma}$ <ul>
<li>수열의 합을 나타내는 기호</li>
</ul>
</li>
<li>${\Sigma^{n}_{k=1}a_k}$ <ul>
<li>1부터 n항까지 합 구하라는 의미</li>
</ul>
</li>
</ul>
</li>
<li>계차수열<ul>
<li>어떤 수열의 인접하는 두 항의 차로 이루어진 또 다른 수열</li>
<li>${{b_n}}$은 ${{a_n}}$의 계차 수열</li>
<li>${\Sigma^{n-1}_{k=1}b_k = a_n - a_1}$ , ${a_n = a_1 + (n-1) \times d}$ , ${S_n = n(a_1 + a_n) / 2}$ 를 활용하여 일반항을 구하면 된다</li>
</ul>
</li>
<li>피보나치 수열<ul>
<li>세 번째 항은 두 번째 항과 첫 번째 항을 더한 합인 수열</li>
<li>${a_1 = 1, a_2 = 1, n &gt; 2}$ 일 때, ${a_n = a_{(n-2)} + a_{(n-1)}}$</li>
</ul>
</li>
<li>팩토리얼<ul>
<li>1부터 양의 정수 n까지 정수를 모두 곱한 것</li>
<li>${0! = 1, n! = 1 \times 2 \times 3 \times ... \times n}$</li>
<li>math 모듈<ul>
<li>math.factorial(n) &gt;&gt; n!</li>
</ul>
</li>
</ul>
</li>
<li>군 수열<ul>
<li>여러 개의 항을 묶었을 때 규칙성을 가지는 수열</li>
<li>군<ul>
<li>여러 항을 묶은 것</li>
<li>군마다 항의 갯수를 나열하면 그것 또한 수열이고, 그것의 합은 전체 군 수열에서 n번째 항이 몇 군, 몇 번째 항인지 알 수 있다</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="4-통계">4. 통계</h3>
<ul>
<li>순열<ul>
<li>n개에서 r개를 택해 나열하는 경우의 수</li>
<li>${_nP_r = n(n-1)(n-2)...(n-r+1) =  {n! \over {(n-r)!}} }$</li>
<li>원순열<ul>
<li>시작과 끝의 구분이 없는 순열</li>
<li>${{n! \over n}\quad or \quad (n-1)!}$</li>
</ul>
</li>
</ul>
</li>
<li>조합<ul>
<li>n개에서 순서없이 r개 선택하는 경우의 수</li>
<li>${_nC_r = {_nP_r \over r!} =  {n! \over {(n-r)!r!}} \quad 단, 0&lt;r&lt;=n}$</li>
</ul>
</li>
<li>확률<ul>
<li>모든 사건에서 특정 사건이 일어날 수 있는 수<ul>
<li>모든 사건 = 표본 공간</li>
<li>특정 사건 = 사건</li>
</ul>
</li>
<li>조합을 이용해 확률을 알아낼 수 있다.<ul>
<li>당첨의 조합과 낙첨의 조합의 곱을 분자로, 전체에서 뽑는 갯수의 조합을 분모로 두면 확률을 구할 수 있다</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="연습문제">연습문제</h3>
<p><strong>+ 추후에 추가</strong></p>
<h2 id="느낀점">느낀점</h2>
<p>기초 수학은 짧기도 하고, 이전에 공부한 내용이라 어렵지 않았다. 게다가 매번 예시를 들어 설명해주기 때문에 이해하기 어려운 부분은 나오지 않았다. 잠깐 숨 돌리는 기분이었다.</p>
<p><strong>이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[002. 데이터 취업 스쿨 스터디 노트_2주차_파이썬중급]]></title>
            <link>https://velog.io/@julia-jh319/002.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B82%EC%A3%BC%EC%B0%A8%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%A4%91%EA%B8%89</link>
            <guid>https://velog.io/@julia-jh319/002.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B82%EC%A3%BC%EC%B0%A8%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%A4%91%EA%B8%89</guid>
            <pubDate>Tue, 23 Apr 2024 12:04:55 GMT</pubDate>
            <description><![CDATA[<h1 id="2주차">2주차</h1>
<h2 id="수강한-분량">수강한 분량</h2>
<p>파이썬 중급은 객체지향개념과 클래스, 패키지와 함수, 모듈에 대해 다루었다. 스터디 조가 배정되었고, 일주일에 한 번씩 만나 주어진 과제를 공유하고, 그 내용에 대해 얘기하고 있다. 그러면 안되는데도 개인사가 자꾸 일정을 방해한다.</p>
<h2 id="각-강의별-학습한-핵심-내용-정리">각 강의별 학습한 핵심 내용 정리</h2>
<h3 id="1-함수">1. 함수</h3>
<ul>
<li>함수: 입력값이 주어지면 특정 연산을 거쳐 출력값을 만드는 것<pre><code>def 함수명(입력값(생략가능)):
  return 반환값
</code></pre></li>
</ul>
<p>함수명(입력값들) # 호출법</p>
<pre><code>
- 내장 함수: 파이썬에서 기본으로 제공하는 것
- 사용자 함수: 사용자가 직접 선언하는 함수
- 함수 사용 하는 이유: 특정 기능을 재사용하기 위함

- round(a, b): a숫자의 소수점 아래 b번째까지만 출력

- 함수 내에서 또 다른 함수 호출</code></pre><p>def fun1():
    print(&#39;fun1 호출&#39;)
    fun2()
    print(&#39;fun2 호출 후 실행&#39;)
def fun2():
    print(&#39;fun2 호출&#39;)
    fun3()
    print(&#39;fun3 호출 후 실행&#39;)
def fun3():
    print(&#39;fun3 호출&#39;)</p>
<pre><code>
#### 함수 요소
- pass 이용해 실행문 생략 가능, 실행문을 비워두면 error 발생

- 인수: 함수 호출 시 함수에 전달되는 데이터
- 매개변수: 호출부와 선언부에 관계에 매개를 맺어주는 변수
    - \*매개변수 매개변수 갯수가 정해지지 않은 경우에 사용하는 것
        - type은 tuple 데이터 타입으로 iterable type
- 인수와 매개변수의 갯수가 동일해야 한다. 아니면 error

- return 키워드를 활용하면 함수 실행 결과를 호출부로 반환할 수 있다
    - return을 만나면 함수 실행을 **종료**한다

- 지역변수: 함수 안에 선언된 변수로, 함수 안에서만 사용이 가능하다
- 전역변수: 함수 밖에 선언된 변수로, 어디에서나 사용은 가능하지만 함수 안에서 수정은 불가능하다
- global 키워드를 사용하면 함수 안에서도 전역변수 값을 수정할 수 있다

- 중첩함수: 함수 안에 또 다른 함수가 있는 형태
    - 내부 함수를 감싸고 있는 함수 외부에서 호출 불가능

- lambda 함수: 함수 선언이 보다 간단하게 가능</code></pre><p>함수이름 = lambda 매개변수: 연산식
함수이름(매개변수) # 호출법</p>
<pre><code>
### 2. 모듈
- 모듈: 함수가 선언되어 있는 파이썬 파일
    - 내부 모듈: 파이썬 설치 시 기본적으로 사용할 수 있는 모듈
    - 외부 모듈: 별도 설치 후 사용할 수 있는 모듈
    - 사용자 모듈: 사용자가 직접 만든 모듈
#### 모듈 제작
- 일반 python 파일을 만들면 된다.
    - 확장자 .py
    - as 이용하여 모듈 이름 단축 가능
        - import @#$% as @@
    - from 과 as 이용하여 모듈 특정 기능만 사용하는 것
        - from 모듈 import 함수1, 함수2, ...: 단일~복수 개 가능
        - from 모듈 import \*: 모든 기능을 활용하겠다는 의미

#### 모듈 실행
- import 를 이용해 확장자를 제외한 파일 이름을 붙여 불러온다

### 3. 실행 파일
- \_\_name\_\_: 에는 모듈 이름이 저장되거나 &#39;\_\_main\_\_&#39;이 저장된다
- 실행 파일 중에 제일 먼저 실행해야 하는 파일
- 이 파일이 실행파일이라면 그때만 아래 기능이 실행되어라</code></pre><p>if <strong>name</strong> == &#39;<strong>main</strong>&#39;:
    실행문</p>
<pre><code>
### 4. 패키지
- 패키지를 이용하면 관련 있는 모듈을 그룹으로 관리할 수 있음
- site-packages라는 디렉토리에 있는 모듈은 어디서나 사용할 수 있다</code></pre><p>import sys</p>
<p>for path in sys.path:
    print(path) # 참조하는 디렉토리 리스트를 출력해줌</p>
<pre><code>- venv: virtual environment의 약자, 가상환경
    - 프로젝트마다 가상환경을 만들고, 그것에 맞추어 설정을 바꾸거나 작업을 할 수 있다. 각 환경마다 독립적으로 진행할 수 있음

- 자주 사용하는 모듈
    - math: 수학
    - random: 난수
    - time: 시간
### 5. 객체지향 프로그래밍
- 객체를 이용한 프로그램
- 객체(object)
    - 속성(attribute)
        - 변수
    - 기능(Function)
        - 함수
- 객체 사용 장점
    - 코드 재사용, 모듈화에 좋다
    - 부품 결합도가 낮으면 가장 이상적인 프로그램이 될 수 있다

### 6. 클래스
- class키워드와 속성(변수), 기능(함수)를 이용해 만든다</code></pre><h1 id="클래스명-첫-자는-대문자로-쓰는-것이-관례">클래스명 첫 자는 대문자로 쓰는 것이 관례</h1>
<p>class 클래스명: # 클래스 선언
    def <strong>init</strong>(self, 변수1, 변수2): # 생성자, 속성
        self.변수명1 = 변수1 # 변수명은 객체 속성을 의미
        self.변수명2 = 변수2 # 변수1은 매개변수를 의미
    def 함수명1(self): # 기능, self 표시는 현재 클래스안에 포함된다는 의미
        실행문
    def 함수명2(self): # 기능
        실행문</p>
<pre><code>
- 객체는 클래스의 생성자를 호출한다.
    - 객체명1 = 클래스명(변수1값, 변수2값)
- 객체 속성 변경
    - 속성에 직접 접근하여 수정하기
    - 객체명.객체속성 = 새로운 값

- 객체와 메모리
    - 클래스에서 객체를 선언해 사용하는 것은 변수안에 저장된 객체 메모리 주소를 이용해 객체 기능을 호출하거나 속성을 변경하는 것
    - 변수는 객체의 메모리 주소를 저장하고 이를 이용해 객체를 참조하는 것
    - 레퍼런스 변수라고 부르기도 한다
    - 얕은 복사
        - 객체의 메모리 주소가 할당되는 것
        - 객체가 새로 생긴 것이 아니라, 메모리 주소만 복사한 것으로 하나의 객체를 가리키는 여러 변수가 생긴 것
    - 깊은 복사
        - 동일한 객체가 하나 더 생기는 것
        - copy.copy()함수 사용으로 가능
            - `import copy`
              `사본 = copy.copy(원본)`
        - id() 이용하면 메모리 주소를 확인할 수 있음
            - id(변수)
        - 자료구조가 가지고 있는 함수를 사용해 깊은 복사가 가능하기도 함
            - 반복구조 변수라면 for문을 사용해 하나씩 이어붙이는 것도 가능

- 클래스 상속
    - 클래스가 다른 클래스를 상속해 내 것처럼 사용하는 것
        - `class 클래스명(다른 클래스명)`
    - 생성자
        - 객체가 생성될 때 생성자를 호출하면  \_\_init\_\_()가 자동 호출됨
            - 호출됨: `변수 = 클래스명()`
    - \_\_init\_\_()
        - 속성을 초기화한다
    - 기능은 바로 사용이 가능하지만, 속성은 \_\_init\_\_() 호출되어야 사용이 가능하다
    - 상위 클래스의 속성을 초기화함
        - `상위클래스.__init__(self, 변수명1, 변수명2)`
        - super() 함수 사용
            - `super().__init__(변수명1, 변수명2)`
    - **다중 상속**
        - 2개 이상 클래스를 상속한다
        - `class 클래스명(클래스1, 클래스2, 클래스3, ...)`
        - 동일한 이름이 있으면 헷갈리므로 남발하면 안됨
            - 원칙적으로는 가장 먼저 상속받은 클래스를 이용함
    - 오버라이딩
        - 하위 클래스에서 상위 클래스의 메서드를 재정의(override)하는 것
        - 중복된 코드를 많이 정리할 수 있고, 시간 절약도 된다</code></pre><p>class 상위:
    def <strong>init</strong>(self, 변수명1, 변수명2):
        self.변수1 = 변수명1
        self.변수2 = 변수명2</p>
<pre><code>def 함수명1(self):
    수행문1</code></pre><p>class 하위(상위):
    def <strong>init</strong>(self, 변수명1, 변수명2):
        super().<strong>init</strong>(변수명1, 변수명2)</p>
<pre><code>def 함수명1(self):
    수행문2</code></pre><pre><code>
- 추상 클래스
    - 상위 클래스에서 하위 클래스에 메서드 구현을 강요하는 것
    - 구체화하지 않으면 에러가 발생
    - 특정 기능을 각자 알맞게 맞추어 사용하기 위함</code></pre><p>from abc import ABCMeta
from abc import abstractmethod</p>
<p>class 상위(metaclass = ABCMeta):
    def <strong>init</strong>(self, 변수명1, 변수명2):
        self.변수1 = 변수명1
        self.변수2 = 변수명2</p>
<pre><code>@abstractmethod # decoration
def 함수명1(self):
    pass # 선언만 되어있음</code></pre><p>class 하위(상위):
    def <strong>init</strong>(self, 변수명1, 변수명2):
        super().<strong>init</strong>(변수명1, 변수명2)</p>
<pre><code>def 함수명1(self):
    수행문 # 구현을 함</code></pre><pre><code>### 7. 예외란?
- 예외
    - 문법적인 문제는 없으나, 실행 중 발생하는 예상하지 못한 문제
    - 소프트웨어적으로 처리할 수 없는 문제
    - eg) syntax error, network error, system 환경 불안정, 하드웨어적 불가능
- 예외 관련 클래스는 Exception 클래스를 상속한다
    - Exception
        - ArithmeticError
            - ZeroDivisionError
        - EnvironmentError
            - IOError
        - LookupError
            - IndexError
        - SyntaxError
            - IndentationError
- 예외 처리
    - 발생된 예외를 별도 처리함으로써 프로그램 전체의 실행에 문제가 없도록 하는 것
    - 정확하게 문제가 발생할 부분만 try로 감싸야 함</code></pre><p>try:
    실행문1 # 문제가 발생할 수 있는 부분, 문제가 없는 경우 수행됨
except:
    실행문2 # 문제가 발생한 경우 수행될 부분
else:
    실행문3 # 예외가 발생하지 않았을 때 수행하는 부분
finally:
    실행문4 # 예외 발생과 상관없이 항상 수행되는 부분
실행문5 # 에러가 없이 예외처리 정리가 잘 된 경우 마저 수행될 부분</p>
<pre><code>
- Exception
    - 예외를 담당하는 클래스
    - 어떤 에러때문에 발생한 예외인지 알아낼 수 있다</code></pre><p>try:
    실행문1
except Exception as e: # error 발생 시 예외처리 구문을 e로 부르기로 함
    print(e) # error 발생 시, 적절한 예외 처리 구문이 나옴</p>
<pre><code>- raise
    - 예외를 발생시킬 수 있다.</code></pre><p>def 함수(변수명1, 변수명2):
    if 조건문:
        실행문1
    else:
        raise Exception(&#39;예외 처리 문구&#39;)</p>
<p>try:
    함수(값1, 값2) # 호출
except Exception as e: # error 발생 시 예외처리 구문을 e로 부르기로 함
    print(e) # error 발생 시, 위에서 만든 예외 처리 문구가 나옴</p>
<pre><code>
- 사용자 예외 클래스
    - Exception 클래스를 상속해 만들 수 있다</code></pre><p>class 사용자예외클래스명(Exception):
    def <strong>init</strong>(self, 변수명):
        super().<strong>init</strong>(&#39;{}은 사용할 수 없습니다.&#39;.format(변수명))</p>
<p>def 함수(변수명1, 변수명2):
    if 조건문: # 특정 상황일 때 만들어둔 사용자 예외 클래스를 실행시킨다
        raise 사용자예외클래스명(변수)
    else:
        실행문1</p>
<p>try:
    함수(값1, 값2) # 호출
except Exception as e: # error 발생 시 예외처리 구문을 e로 부르기로 함
    print(e) # error 발생 시, 위에서 만든 예외 처리 문구가 나옴</p>
<pre><code>
### 8. 텍스트 파일 쓰기
- open(&#39;a&#39;, &#39;b&#39;)
    - 파일 열기
    - a: 디렉토리명
    - b: 파일의 모드
        - w 모드
            - 쓰기 전용, write
            - 파일이 존재하지 않으면 만들고, 존재하면 연다.
            - 기존의 글을 전부 지우고 새로운 글로 덮어버린다
        - r 모드
            - 읽기 전용, read
            - 파일이 존재하지 않으면 에러발생
            - 내부 내용이 무엇이건 문자열로 읽어들임
            - encoding = &#39;&#39;
                - UTF8 등 인코딩버전을 맞춰야할 때가 있다
        - a 모드
            - 쓰기 전용, append
            - 파일이 존재하면 덧붙인다
        - x 모드, exclusive creation
            - 쓰기 전용, 
            - 파일을 만들고 작성한다
            - 파일이 존재하면 에러가 발생
- read()
    - 읽기
- write()
    - 쓰기
    - 내용은 문자열만 가능하다. 숫자여도 str()로 변환하기
- close()
    - 파일 닫기</code></pre><p>file = open(&#39;파일주소/파일명.확장자&#39;, &#39;w&#39;)</p>
<p>변수명 = file.write(&#39;작성할 문구&#39;) # 작성할 문구의 길이를 반환함
print(변수명)</p>
<p>file.close()</p>
<pre><code></code></pre><p>file = open(&#39;파일주소/파일명.확장자&#39;, &#39;r&#39;)</p>
<p>변수명 = file.read() # 텍스트파일 내용을 문자열로 읽음
print(변수명)</p>
<p>file.close()</p>
<pre><code>
- time.strftime()
    - 출력되고자하는 문자형태로 표시하기
    - %Y
        - 연
    - %m
        - 월
    - %d
        - 일
    - %H
        - 시
    - %M
        - 분
    - %S
        - 초
    - %p
        - am, pm 표시
    - %I
        - 12시간제

- 문자열.replace(&#39;문자열1&#39;, &#39;문자열2&#39;, 횟수)
    - 문자열 내에서 문자열1을 발견하면 문자열2로 바꾸겠다. 이때 횟수가 주어지면 그 횟수만큼만 적용되고, 그 횟수를 넘어간 이후 발견한 문자열1은 바꾸지 않는다.
- 문자열.split(&#39;구분자&#39;)
    - 문자열 내에 구분자를 기준으로 문자열을 나누어 리스트에 각각 저장한다

- with as 구문
    - 파일 닫기를 생략할 수 있다
    - with open(&#39;파일주소/파일명.확장자&#39;, 모드) as 변수명
        - &#39;파일주소/파일명.확장자&#39;를 열어서 파일을 가리키고 있는 레퍼런스 변수를 변수명이라 하겠다.</code></pre><p>with open(&#39;파일주소/&#39; + &#39;파일명.확장자&#39;, &#39;a&#39;) as f:
    f.write(&#39;작성 문자열&#39;)</p>
<pre><code></code></pre><p>with open(&#39;파일주소/&#39; + &#39;파일명.확장자&#39;, &#39;r&#39;) as f:
    print(f.read())</p>
<pre><code>
- uri
    - 인터넷에 있는 자원을 나타내는 유일한 주소(Uniform Resource Identifier)

- writelines()
    - 반복 가능한 자료형의 데이터를 파일에 쓸 때 사용하는 함수
- readlines()
    - 파일의 모든 데이터를 읽어서 리스트 형태로 반환함
- readline()
    - d
</code></pre><p>변수명 = 반복 가능한 자료형</p>
<p>for i in 변수명:
    with open(&#39;파일주소/&#39; + &#39;파일명.확장자&#39;, &#39;a&#39;) as f:
        f.write(i)
        f.write(\n)</p>
<p>변수명 = 반복 가능한 자료형</p>
<p>with open(&#39;파일주소/&#39; + &#39;파일명.확장자&#39;, &#39;a&#39;) as f:
    f.writelines(변수명) # 바로 연결됨
    # 개행을 원한다면 아래와 같이 사용 가능
    f.writelines(i + &#39;\n&#39; for i in 변수명)</p>
<pre><code></code></pre><p>with open(&#39;파일주소/&#39; + &#39;파일명.확장자&#39;, &#39;r&#39;) as f:
    변수명 = f.readlines()</p>
<p>print(변수명)</p>
<pre><code></code></pre><p>with open(&#39;파일주소/&#39; + &#39;파일명.확장자&#39;, &#39;r&#39;) as f:
    변수명 = f.readline()</p>
<pre><code>while 변수명 != 0:
    print(&#39;변수명)
    변수명 = f.readline() # 다음 줄 읽게 됨</code></pre><p>```</p>
<h3 id="연습문제">연습문제</h3>
<p>+ 추후에 추가</p>
<h2 id="느낀점">느낀점</h2>
<p>혼자 공부할 때는 어디서부터 어디까지 내가 지금 당장 알아야 활용할 수 있는지조차 모르기 때문에 필요한 정보를 찾아내는 것 자체도 힘이 드는 일이었다. 아무래도 모든 내용을 다루지 않는 다는 것은, 오히려 꼭 알아야 하는 내용을 위주로 정리한것이니 이것만큼은 꼭 이해해야겠다는 생각이 들었다.</p>
<p><strong>이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[001. 데이터  취업 스쿨 스터디 노트_1주차_파이썬기초]]></title>
            <link>https://velog.io/@julia-jh319/001.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B81%EC%A3%BC%EC%B0%A8%ED%8C%8C%EC%9D%B4%EC%8D%AC%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@julia-jh319/001.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B7%A8%EC%97%85-%EC%8A%A4%EC%BF%A8-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%85%B8%ED%8A%B81%EC%A3%BC%EC%B0%A8%ED%8C%8C%EC%9D%B4%EC%8D%AC%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Fri, 12 Apr 2024 04:40:48 GMT</pubDate>
            <description><![CDATA[<h1 id="1주차">1주차</h1>
<h2 id="수강한-분량">수강한 분량</h2>
<p>교육 첫 주에 배정된 분량은 파이썬 기초의 개념 강의와 실습 강의였다. 개인의 일정에 따라 몰입형과 병행형으로 나누어졌는데, 평일 중에 수업을 듣는 나는 몰입형으로 하루에 3~4시간의 분량이 추천되었다.</p>
<h2 id="각-강의별-학습한-핵심-내용-정리">각 강의별 학습한 핵심 내용 정리</h2>
<h3 id="1-pycharm-설치">1. pyCharm 설치</h3>
<p>pycharm에서 붙여넣고 싶을 때 단축키 ctrl + d (duplicate 약자)
pycharm에서 실행하고 싶을 때 shift + F10</p>
<h3 id="2-변수">2. 변수</h3>
<ul>
<li>변수: 데이터가 저장되어 있는 특정한 공간</li>
<li>변수명: 메모리 주소가 너무 어려워 인간이 이해할 수 있는 언어로 지칭하는 것</li>
<li>변수를 사용하는 이유: 반복과 수정이 용이함</li>
<li>변수명 규칙<ul>
<li>데이터의 의미를 유추할 수 있게 작명</li>
<li>영문</li>
<li>소문자 시작(추후에 나올 클래스와 혼동 가능성 줄이기 위함)</li>
<li>카멜 표기법: myAge</li>
<li>스네이크 표기법: my_age</li>
<li>예약어, _ 제외한 특수문자, 공백문자 사용 금지</li>
<li>숫자는 첫 번째 자리 제외하고 사용 가능</li>
</ul>
</li>
</ul>
<h3 id="3-자료형">3. 자료형</h3>
<p>메모리를 낭비하지 않고 효율적으로 관리하기 위해서</p>
<ul>
<li><p>정수형</p>
<ul>
<li>int</li>
<li>메모리가 허용되는 한 무한 사용 가능</li>
</ul>
</li>
<li><p>실수형</p>
<ul>
<li>float</li>
<li>대략 소수점 이하 17~18번째에서 데이터 손실이 일어남</li>
</ul>
</li>
<li><p>문자형</p>
<ul>
<li>str</li>
<li>&#39;&#39; 혹은 &quot;&quot; 로 묶어서 표현</li>
</ul>
</li>
<li><p>논리형</p>
<ul>
<li>bool</li>
<li>True 혹은 False 존재</li>
</ul>
</li>
<li><p>type(변수): 변수의 타입을 확인할 수 있다</p>
</li>
<li><p># 내용 :단행 주석, ctrl + \ 로 가능</p>
</li>
<li><p>&#39;&#39;&#39;내용&#39;&#39;&#39;: 다행 주석</p>
</li>
<li><p>자료형 변환</p>
<ul>
<li>문자로<ul>
<li>str()</li>
</ul>
</li>
<li>숫자로<ul>
<li>int()</li>
<li>float()</li>
<li>논리형을 숫자로 바꾸면, True는 1로 False는 0으로 변환됨</li>
</ul>
</li>
<li>논리로<ul>
<li>bool()</li>
</ul>
</li>
<li>빈 문자 / 공백 문자<ul>
<li>&#39;&#39;: 빈 문자<ul>
<li>False</li>
</ul>
</li>
<li>&#39; &#39;: 공백 문자<ul>
<li>True</li>
</ul>
</li>
<li><strong>글자 내용과 관계없이 채워진 문자라면 True</strong><h3 id="4-데이터-입력">4. 데이터 입력</h3>
</li>
</ul>
</li>
</ul>
</li>
<li><p>input(&#39;가이드 문구&#39;): 입력 함수</p>
<ul>
<li>입력받은 데이터는 모두 str 타입<h3 id="5-데이터-출력">5. 데이터 출력</h3>
</li>
</ul>
</li>
<li><p>print(): 출력함수</p>
<ul>
<li>,를 이용해 데이터 연속 출력 가능</li>
<li>옵션<ul>
<li>end<ul>
<li>자동으로 마지막에 개행문자가 삽입되어 있다</li>
<li>end = &#39;&#39;: 옵션값에 빈 문자 넣기 가능, 그 다음 내용이 바로 붙어서 나옴</li>
</ul>
</li>
</ul>
</li>
<li>f&#39;내용 {변수명}&#39;: format함수 사용</li>
</ul>
</li>
<li><p>특수문자</p>
<ul>
<li>\t: 탭</li>
<li>\n: 개행</li>
</ul>
</li>
<li><p>format()</p>
<ul>
<li>print(&#39;라라라{}라라라{}&#39;.format(변수명, 변수명))</li>
<li>print(&#39;라라라{0}라라라{1}&#39;.format(변수명, 변수명))</li>
</ul>
</li>
<li><p>형식 문자</p>
<ul>
<li>%s: 문자열</li>
<li>%d: 정수</li>
<li>%f: 실수<ul>
<li>%.1f: 소수점 첫 번째자리까지 표현, 사사오입 적용됨</li>
</ul>
</li>
<li>사용법<ul>
<li>print(&#39;lala: %s&#39; % VariableName)<h3 id="6-연산자">6. 연산자</h3>
<h4 id="산술">산술</h4>
</li>
</ul>
</li>
</ul>
</li>
<li><p>더하기</p>
<ul>
<li>+</li>
<li>숫자끼리 덧셈: 더하기 연산</li>
<li>문자끼리 덧셈: 문자열 이어 표현</li>
<li>숫자와 문자의 덧셈: 불가능</li>
</ul>
</li>
<li><p>빼기</p>
<ul>
<li>-</li>
<li>숫자끼리 뺄셈: 빼기 연산</li>
<li>문자끼리 뺄셈: 불가능</li>
<li>숫자와 문자의 뺄셈: 불가능</li>
</ul>
</li>
<li><p>곱하기</p>
<ul>
<li>*</li>
<li>숫자끼리 곱셈: 곱셈 연산</li>
<li>문자를 이용한 곱셈: 곱해진 수만큼 반복</li>
</ul>
</li>
<li><p>나누기</p>
<ul>
<li>/</li>
<li>숫자끼리 나눗셈: 나눗셈 연산</li>
<li>0을 나누는 경우 항상 결과는 0</li>
<li>0으로 나누는 경우 항상 결과는 ZeroDivisionError: division by zero로 0으로 나눌 수 없다는 에러가 나옴</li>
<li>나눈 결과는 항상 float</li>
</ul>
</li>
<li><p>나머지</p>
<ul>
<li>%</li>
<li>나머지만 구한다</li>
<li>divmod(num1, num2)[1]</li>
</ul>
</li>
<li><p>몫</p>
<ul>
<li>//</li>
<li>몫만 구한다</li>
<li>divmod(num1, num2)[0]</li>
</ul>
</li>
<li><p>나머지와 몫을 한 번에 구하기</p>
<ul>
<li>divmod(num1, num2)<ul>
<li>(몫, 나머지) 의 tuple 형태로 결과가 나옴</li>
</ul>
</li>
</ul>
</li>
<li><p>거듭 제곱</p>
<ul>
<li>**</li>
<li>앞의 수를 뒷 수만큼 거듭 제곱한다.</li>
<li>n의 m제곱근 공식<ul>
<li>n ** (1/m)</li>
</ul>
</li>
<li>math 모듈<ul>
<li>sqrt() 함수<ul>
<li>math.sqrt(n): n의 제곱근 구하기</li>
</ul>
</li>
<li>pow() 함수<ul>
<li>math.pow(n, m): n의 m제곱값 알려줌</li>
</ul>
</li>
</ul>
</li>
<li>format(숫자, &#39;,&#39;)<ul>
<li>숫자를 3자리마다 ,로 구분하고 데이터 타입을 str로 바꿈<h4 id="복합">복합</h4>
</li>
</ul>
</li>
</ul>
</li>
<li><p>할당</p>
<ul>
<li>=</li>
<li>오른쪽의 값을 왼쪽에 할당(대입)</li>
</ul>
</li>
<li><p>덧셈 연산 후 할당</p>
<ul>
<li>+=</li>
</ul>
</li>
<li><p>뺄셈 연산 후 할당</p>
<ul>
<li>-=</li>
</ul>
</li>
<li><p>곱셈 연산 후 할당</p>
<ul>
<li>*=</li>
</ul>
</li>
<li><p>나눗셈 연산 후 할당</p>
<ul>
<li>/=</li>
</ul>
</li>
<li><p>나머지 연산 후 할당</p>
<ul>
<li>%=</li>
</ul>
</li>
<li><p>몫 연산 후 할당</p>
<ul>
<li>//=</li>
</ul>
</li>
<li><p>거듭 제곱 연산 후 할당</p>
<ul>
<li>**=<h4 id="비교">비교</h4>
</li>
</ul>
</li>
<li><p>연산 결과는 bool이다</p>
</li>
<li><p>숫자인 경우 크기 비교</p>
</li>
<li><p>문자인 경우 아스키코드를 이용해 크기 비교</p>
<ul>
<li>A: 65</li>
<li>a: 97</li>
<li>ord() 함수<ul>
<li>문자를 십진수로 표현하기</li>
<li>ord(&#39;A&#39;) = 65</li>
</ul>
</li>
<li>chr() 함수<ul>
<li>십진수를 문자로 표현하기</li>
<li>chr(97) = a</li>
</ul>
</li>
</ul>
</li>
<li><p>문자열인 경우 문자열 자체를 비교</p>
<ul>
<li>하나라도 다르면 False</li>
</ul>
</li>
<li><p>크다</p>
<ul>
<li><blockquote>
</blockquote>
</li>
</ul>
</li>
<li><p>크거나 같다</p>
<ul>
<li><blockquote>
<p>=</p>
</blockquote>
</li>
</ul>
</li>
<li><p>작다</p>
<ul>
<li>&lt;</li>
</ul>
</li>
<li><p>작거나 같다</p>
<ul>
<li>&lt;=</li>
</ul>
</li>
<li><p>같다</p>
<ul>
<li>==</li>
</ul>
</li>
<li><p>같지 않다</p>
<ul>
<li>!=<h4 id="논리">논리</h4>
</li>
</ul>
</li>
<li><p>그리고</p>
<ul>
<li>and</li>
<li>A와 B 모두 True인 경우만 결과 값이 True</li>
</ul>
</li>
<li><p>또는</p>
<ul>
<li>or</li>
<li>A와 B 중 하나가 True인 경우 결과 값이 True</li>
</ul>
</li>
<li><p>아니다</p>
<ul>
<li>not</li>
<li>A 상태를 부정하는 결과</li>
</ul>
</li>
</ul>
<h3 id="7-operator모듈">7. operator모듈</h3>
<ul>
<li>산술 연산자 모듈<ul>
<li>operator.add()<ul>
<li>+</li>
</ul>
</li>
<li>operator.sub()<ul>
<li>-</li>
</ul>
</li>
<li>operator.mul()<ul>
<li>*</li>
</ul>
</li>
<li>operator.truediv()<ul>
<li>/</li>
</ul>
</li>
<li>operator.mod()<ul>
<li>%</li>
</ul>
</li>
<li>operator.floordiv()<ul>
<li>//</li>
</ul>
</li>
<li>operator.pow()<ul>
<li>**</li>
</ul>
</li>
</ul>
</li>
<li>비교 연산자 관련 모듈<ul>
<li>operator.eq()<ul>
<li>==</li>
</ul>
</li>
<li>operator.ne()<ul>
<li>!=</li>
</ul>
</li>
<li>operator.gt()<ul>
<li><blockquote>
</blockquote>
</li>
</ul>
</li>
<li>operator.ge()<ul>
<li><blockquote>
<p>=</p>
</blockquote>
</li>
</ul>
</li>
<li>operator.lt()<ul>
<li>&lt;</li>
</ul>
</li>
<li>operator.le()<ul>
<li>&lt;=</li>
</ul>
</li>
</ul>
</li>
<li>논리 연산자 관련 모듈<ul>
<li>operator.and_()<ul>
<li>and</li>
</ul>
</li>
<li>operator.or_()<ul>
<li>or</li>
</ul>
</li>
<li>operator.not_()<ul>
<li>not
난수 모듈</li>
</ul>
</li>
</ul>
</li>
<li>random<ul>
<li>random.randint(n, m)</li>
<li>n에서 m사이의 난수를 하나 만들기</li>
</ul>
</li>
</ul>
<h3 id="8-조건식">8. 조건식</h3>
<ul>
<li>조건식<ul>
<li>어떤 조건에 따라 실행이 분기되는 식</li>
</ul>
</li>
<li>A if 조건식 else B: 조건식의 결과가 True면 A 실행, 아니면 B실행</li>
<li>너무 길 때는 \를 끝에 두고 개행하면 연결 문장으로 읽힌다.<h4 id="if문">if문</h4>
</li>
<li>단일조건<pre><code>if 조건식:
  실행문 # 조건식이 True일 때 수행</code></pre></li>
</ul>
<h4 id="ifelse문">if~else문</h4>
<ul>
<li>양자택일<pre><code>if 조건식:
  실행문 # 조건식이 True일 때 수행
else:
  실행문 # 조건식이 False일 때 수행</code></pre></li>
<li><strong>삼항연산자 사용법</strong><ul>
<li>조건식 결과에 따른 실행만 하는 경우
  <code>실행문1 if 조건문 else 실행문2</code></li>
<li>조건식 결과를 변수에 할당하는 경우
  <code>변수 = 변수값1 if 조건문 else 변수값2</code><h4 id="ifelif문">if~elif문</h4>
</li>
</ul>
</li>
<li>다자택일(다중조건)<pre><code>if 조건식1:
  실행문1  # 조건식1이 True일 때 수행
elif 조건식2:
  실행문2  # 조건식2가 True일 때 수행</code></pre></li>
<li>조건식 중 하나를 만족하면 나머지 조건식은 비교X <strong>조건식 순서가 중요</strong></li>
<li>조건 범위를 명시한다.</li>
</ul>
<h4 id="중첩-조건문">중첩 조건문</h4>
<ul>
<li>조건문 안에 또 다른 조건문이 있을 수 있다</li>
<li>3단계 이상 중첩은 코드 식별이 어려워 논리적 오류가 나기 쉽다. </li>
</ul>
<h3 id="9-반복문">9. 반복문</h3>
<ul>
<li>특정 실행을 반복하는 것</li>
<li>프로그래밍이 간결하고 유지 보수가 쉽다</li>
<li>횟수에 의한 반복<ul>
<li>회수 지정하여 그만큼 반복 실행</li>
</ul>
</li>
<li>조건에 의한 반복<ul>
<li>조건을 지정하여 그에 만족하는 동안 반복 실행<h4 id="for문">for문</h4>
<pre><code>for 반복구조 적용될 변수 in 반복구조:
실행문</code></pre></li>
</ul>
</li>
<li>횟수에 의한 반복일 경우 적합한 반복문</li>
<li>range(시작, 끝, step)<ul>
<li>시작부터 끝-1까지 step만큼 증가하면서 반복</li>
<li>step이 1일 경우 생략 가능</li>
<li>시작이 0인 경우 생략 가능<h4 id="while문">while문</h4>
<pre><code>while 조건문:
실행문</code></pre></li>
</ul>
</li>
<li>조건에 의한 반복문일 경우 적합한 반복문</li>
<li>조건문이 True이면 영원히 반복하게 됨</li>
<li>무한루프: 반복문을 빠져나올 수 없는 경우<ul>
<li>외부, 내부에 조건문 관련하여 값이 조정되는 실행문을 넣어두어야 무한반복이 안 됨<ul>
<li>실행문에 n &lt; m,  실행문에 n += 1 등으로 for문과 비슷하게 제어</li>
<li>flag = True로 두고, 어떤 조건을 만족 시 flag = False로 하여 반복 중지<h4 id="반복문-제어">반복문 제어</h4>
</li>
</ul>
</li>
</ul>
</li>
<li>continue<ul>
<li>실행을 생략하고 다음 반복문 실행문으로 넘어간다</li>
</ul>
</li>
<li>else<ul>
<li>반복문이 종료된 후 실행되는 실행문이다</li>
</ul>
</li>
<li>break<ul>
<li>반복 실행 중 break를 만나면 반복문을 빠져나온다</li>
</ul>
</li>
</ul>
<h4 id="중첩-반복문">중첩 반복문</h4>
<ul>
<li>반복문 안에 다른 반복문을 선언하는 것</li>
<li>중첩은 2단계가 보편적이고 최대 3단계로 하는 것이 부하를 막는 좋은 방법</li>
</ul>
<h3 id="10-연습문제">10. 연습문제</h3>
<ul>
<li>datetime 라이브러리<ul>
<li>datetime.datetime.today()<ul>
<li>순간의 날짜와 시간을 불러올 수 있음</li>
<li>~~~.month, year, day, hour, minute, second 등 사용 가능</li>
</ul>
</li>
</ul>
</li>
<li>\t 를 이용하면 글씨 갯수와 관계없이 동일한 여백을 가질 수 있다.</li>
<li>len(): 문자 길이를 반환한다</li>
<li>find(): 특정 문자열의 위치를 찾아 반환함</li>
<li>isdigit(): 숫자이면 True 반환, 아니라면 False 반환</li>
<li>random 라이브러리<ul>
<li>random.randint(a, b): a와 b 사이의 정수 중 랜덤으로 하나 반환</li>
</ul>
</li>
</ul>
<h2 id="느낀-점">느낀 점</h2>
<p>개념 강의에도 예시 문제 풀이가 있었지만, 직접 해볼 수 있는 문제 풀이 강의를 통해 손에 익힐 수 있어 좋았다. 주에 한 번씩 추가 퀴즈를 풀어야 하는 점도 적당한 긴장감을 갖고 강의에 집중할 수 있는 요소였다.</p>
<p><strong>이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[000. ZB 데이터 취업 스쿨 26기 OT 후기]]></title>
            <link>https://velog.io/@julia-jh319/zbdata000</link>
            <guid>https://velog.io/@julia-jh319/zbdata000</guid>
            <pubDate>Tue, 02 Apr 2024 12:33:44 GMT</pubDate>
            <description><![CDATA[<h1 id="입과계기">입과계기</h1>
<p>기계공학과 졸업 이후 취업준비 중에 컴퓨터 공학에 관심을 가지게 되었고, 데이터 분석 교육 중 프로젝트 경험을 통해 매력을 느꼈다. 이후 독학으로 데이터관련 교육과 자격증 취득으로 취업을 준비하던 도중 개인적 한계를 느껴 도움을 받고자 취업 연계 교육을 찾아보았다. 부트텐트에서 제로베이스를 비롯한 여러 부트캠프를 알아보았지만, 전문가가 직접 코칭해주는 프로젝트 경험을 제공하는 데이터 취업 스쿨은 취업과 이후 업무에서도 도움이 될 것 같아 신청하게 되었다.</p>
<h1 id="ot-듣고난-후-각오와-다짐">OT 듣고난 후 각오와 다짐</h1>
<p>포기하지 않기 위해서는, 매일매일 꾸준하게 해야한다는 것을 다시 한 번 생각하게 된다. 그동안 취업이 제대로 되지 않았던 이유 또한 목표를 취업으로 두지 않았기 때문이라는 생각이 들었다. 매일매일 들어야 하는 수업, 매주 있는 평가과제, 한 과목이 끝날때마다 있는 평가 과제, 마지막으로 총 세 번 수행하는 프로젝트 과제까지 수행하는 것으로 끝이 아니다. 이후에 이력서와 자소서, 면접 코칭과 실제로 여러 회사에 지원하는 과정까지가 데이터 취업 스쿨의 진짜 끝이겠지.
데이터로 먹고 살기 위해서 시작했으니, 올해 꼭 끝을 볼 것이다.</p>
]]></description>
        </item>
    </channel>
</rss>