<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>zero-pepsi.log</title>
        <link>https://velog.io/</link>
        <description>Full of adventure</description>
        <lastBuildDate>Thu, 19 Sep 2024 04:59:42 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>zero-pepsi.log</title>
            <url>https://velog.velcdn.com/images/zero-pepsi/profile/a804cae5-1ebd-41a8-b592-afb1b6ba7efd/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. zero-pepsi.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/zero-pepsi" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Proxy]]></title>
            <link>https://velog.io/@zero-pepsi/52</link>
            <guid>https://velog.io/@zero-pepsi/52</guid>
            <pubDate>Thu, 19 Sep 2024 04:59:42 GMT</pubDate>
            <description><![CDATA[<h2 id="proxy란">Proxy란</h2>
<p>클라이언트에서 어떤 인터넷 주소의 정보를 요청 했을때 그 주소에 해당하는 정보를 사전에 저장해둔 서버에서 찾아보고 있으면 바로 응답을 해주고, 없으면 해당 주소의 웹서버에 접속해서 요청 정보를 가져와 저장 후 응답해 주는 역할을 말한다.</p>
<h2 id="forward-proxy란">Forward Proxy란</h2>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6b0893b6-2875-44d0-a27c-7fe81d246824/image.png" alt=""></p>
<p>클라이언트가 웹 서버에 접근하려고 할때 클라이언트의 요청이 웹서버에게 직접 전송되는 것이 아니고 중간에 Proxy 서버에게 전달되어 Proxy 서버는 그 요청을 웹 서버에게 전달하여 응답을 받아오는 방식이다.</p>
<p>추천 용도</p>
<ul>
<li>Content Filtering</li>
<li>eMail security</li>
<li>NAT&#39;ing</li>
<li>Compliance Reporting</li>
</ul>
<h2 id="reverse-proxy란">Reverse Proxy란</h2>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0f0e6987-9987-47d8-8d18-779703c3d242/image.png" alt=""></p>
<p>클라이언트는 웹 서버의 주소가 아닌 Reverse Proxy로 설정된 주소로 요청을 하게 되고, Proxy 서버가 받아서 그 뒷단에 있는 웹 서버에게 다시 요청을 하는 방식으로 클라이언트는 진짜 웹 서버의 정보를 알 수가 없다.</p>
<p><strong>추천 용도</strong></p>
<p>Application Delivery including
Load Balancing(TCP Multiplexing)
SSL Offload/Acceleration (SSL Multiplexing)
Caching
Compression
Content Switching/Redirection
Application Firewall
Server Obfuscation
Authentication
Single SIgn On</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Network Layer]]></title>
            <link>https://velog.io/@zero-pepsi/51</link>
            <guid>https://velog.io/@zero-pepsi/51</guid>
            <pubDate>Thu, 19 Sep 2024 04:59:37 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/fabbdae0-4c68-420f-ba28-10766717e6a2/image.png" alt=""></p>
<h2 id="internet-protocol-stack">Internet Protocol Stack</h2>
<p>인터넷에서 컴퓨터들이 서로 정보를 주고 받는데 쓰이는 프로토콜의 모음.
그 중 TCP와 IP가 가장 많이 쓰이기 때문에 TCP/IP Protocol Suite라고도 함.
응용 계층    DNS, TLS/SSL FTP, HTTP, SMTP, MQTT. .
전송 계층    TCP, UDP, QUIC, DCCP, RSVP. .
인터넷 계층    IPv4, IPv6, ICMP, IGMP, IPsec, ECN . .
링크 계층    ARP, NDP, OSPF, 터널(L2TP), MAC, 이더넷. .
링크 계층은 물리 계층, 데이터 계층으로 나눌수 있음</p>
<h2 id="osi-7-layers">OSI 7 Layers</h2>
<p>SSL이나 TLS를 설명할 때 잘 맞음</p>
<p>응용계층    HTTP, SMTP, FTP, 텔넷, SSH, NFS . .
표현계층    XDR, ASN.1, SMB, AFP . .
세션계층    TLS, SSL, ISO 8327, RPC . .
전송계층    TCP, UDP, RTP, SCTP, SPX . .
네트워크 계층    IP, ICMP, IGMP, ARP, RARP, RIP
데이터 링크계층    이더넷, 토큰링, 무선랜 . .
물리 계층    전선, 광섬유, 동축케이블, 모뎀 . .
​</p>
<p><strong>1. 물리 계층</strong>
데이터 전송 속도, 클록 동기화 방법, 물리적 연결 형태등
<strong>2. 데이터 계층 – MAC주소</strong>
Frame
<strong>3. 네트워크 계층 – IP주소</strong>
패킷, 호스트 구분을 위한 주소 개념 필요(전송경로)
<strong>4. 전송 계층 – PORT번호</strong>
프로세스 구분을 위한 주소 개념 필요, 프로세스간 통신
---------------------------------------OS에서 동작</p>
<p><strong>5. 세션 계층</strong>
세션 지원
<strong>6. 표현 계층</strong>
데이터의 의미와 표현 방법을 처리, 암호화/압축 기능 처리
<strong>7. 응용 계층(Application)</strong>
대표적 인터넷 서비스 : HTTP, FTP, Telnet, 메일
--------------------------------------사용자 프로그램으로 동작</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리눅스 기본]]></title>
            <link>https://velog.io/@zero-pepsi/%EB%A6%AC%EB%88%85%EC%8A%A4</link>
            <guid>https://velog.io/@zero-pepsi/%EB%A6%AC%EB%88%85%EC%8A%A4</guid>
            <pubDate>Thu, 12 Sep 2024 12:35:14 GMT</pubDate>
            <description><![CDATA[<h2 id="1-리눅스linux란">1. 리눅스(Linux)란?</h2>
<p>리누즈 토발즈(Linus Torvalds)에 의해 만들어진 컴퓨터 운영체제로, 자유 소프트웨어와 오픈 소스 개발의 가장 유명한 표본입니다. 컴퓨터 역사상 가장 많은 참여자가 관여하고 있는 오픈소스로 누구나 개발에 참여하고 코드를 볼 수 있는 프로젝트입니다.</p>
<p>아, 참고로 이 펭귄은 리눅스의 마스코트로 이름은 턱스(Tux)입니다 :)</p>
<p>또한, 리눅스는 GNU 프로젝트의 일환입니다. GNU 프로젝트란, &quot;GNU(그누) is not Unix(원래 문장 안에 자신이 이미 들어있는 재귀 약자)&quot;의 줄임말로, 리처드 스톨먼의 주도하에 시작된 공개 소프트웨어 프로젝트입니다.
유닉스 운영체제를 각자의 회사에서 개발하고 소스 코드를 공유하지 않는 문화에 대한 반발로 생겼습니다. 자유 소프트웨어라는 철학을 가지고 있으며, 스톨만은 첫 선언문에 이은 GNU 선언문을 비롯한 여러 글들을 통해서 &quot;초기 전산 공동체에 지배적이었던 협동 정신을 되돌리자&quot;고 주장했습니다.</p>
<h2 id="2-리눅스의-구조">2. 리눅스의 구조</h2>
<p>리눅스의 구조는 다음과 같이 크게 4가지로 분류할 수 있습니다.</p>
<p>office 등의 문서편집기 혹은 웹브라우저와 같은 응용프로그램에서 사용자가 명령을 내리면 shell(셸, 쉘)은 이 명령을 해석해줍니다. 그래서 shell을 명령어 해석기라고도 부르며, 해석된 사용자 입력 명령어를 kernel(커널)에게 전달합니다. kernel은 하드웨어를 제어하는 코드를 통해 소프트웨어와 커뮤니케이션을 하며, 시스템의 모든 자원을 통제/관리하는 역할을 수행합니다.</p>
<h2 id="3-리눅스의-특징과-종류">3. 리눅스의 특징과 종류</h2>
<p>리눅스는 유닉스(Unix)라는 운영체제를 기반으로 하고 있으며, 뛰어난 안정성과 보안성, 높은 신뢰성과 성능이 특징입니다. 시스템의 자원을 효율적으로 관리 및 사용할 수 있으며, 멀티 유저(multi-user)와 멀티 태스킹(multi-tasking)을 지원하고 있습니다.</p>
<p>Multi-User: 여러사용자가 동시에 하나의 시스템에 접근할 수 있음
Multi-Tasking: 여러 개의 task(작업)를 동시에 실행하고, 교대로 컴퓨터의 자원을 사용할 수 있는 기능</p>
<p>또한, 대부분의 리눅스는 CLI(명령어창)와 GUI(그래픽)를 모두 지원하고 있으며, 다양하고 강력한 네트워킹 기능 덕분에 서버 OS로 적합합니다. PC 서버에서도 엔터프라이즈 급의 성능을 제공하고, 성능이 낮은 PC에서도 작동합니다. 앞서 언급한 것과 같이 오픈소스 프로젝트이기 때문에 커널 소스코드 및 모든 관련 자료가 공개되어 빠른 발전을 지원하고 있습니다. 다양한 업무 환경을 만족시키는 다양한 배포판이 존재하고 풍부한 응용프로그램을 제공하고 있습니다.</p>
<p>가장 유명하고 사용성이 좋은 우분투(Ubuntu)와 사용자 인터페이스가 잘 갖춰진 페도라(Fedora), 라즈베리파이에서 자주 쓰이는 라즈비안, 우리에게 친숙한 안드로이드까지 모두 리눅스의 한 종류입니다.</p>
<p>패키지 형식    패키지 관리자    운영체제
레드헷(.rmp)    yum    CentOS, 페도라
데비안 레드헷(.deb)    apt    우분투, 리눅스 민트, 라즈비안
안드로이드(.apk)    Android Package Manager    안드로이드 OS
활용분야: 라우터나 AP와 같은 곳에서 사용하는 네트워크 서버장비, 라즈베리파이와 같은 임베딩시스템과 IoT, TV 셋톱박스, 정밀 의료기기, 리눅스 개발 서버 등</p>
<h2 id="4-가장-높은-인지도의-리눅스-우분투">4. 가장 높은 인지도의 리눅스: 우분투</h2>
<p>우분투는 리눅스 중에서도 가장 높은 인지도를 자랑합니다. 데비안 GNU/Linux를 기반으로 제작된 데스크탑 환경을 사용하는 리눅스 배포판입니다.</p>
<p>Ubuntu: 남아프리카의 반투어인 우분투라는 말에서 파생. 사람들간의 관계와 헌신에 중점을 둔 윤리사상 혹은 인본주의 사상으로 평화운동의 사상적 뿌리라는 철학을 가지고 있음. 마음이 열려 있고, 타인을 돕고 존중한다는 의미를 가지고 있음.</p>
<p>개인용 PC 환경에 최적화되어있고, 간결하고 쉽게 사용할 수 있다는 점이 큰 장점입니다. 또한, 높은 인지도와 많은 사용자를 보유하고 있어 그에 따른 커뮤니티도 많습니다. 우분투를 사용하던 중 문제가 생기거나 질문이 있을 때, 커뮤니티를 통해 빠르게 해결할 수 있습니다. 약 6개월 단위로 업데이트되기 때문에 보안이슈, 버그에의 대응이 빠릅니다. GNOME(그놈)을 기반으로 한 인터페이스도 가지고 있습니다.</p>
<p>버전 번호 ex. 19.04 = 19년도 4월 공개 버전을 의미. LTS는 Long Term Support의 약어로, 장기간(약 5년)으로 우분투에서 지원해주는 가장 안정적인 버전을 의미.</p>
<h2 id="5-gui-vs-cli">5. GUI vs CLI</h2>
<p>앞서, 대부분의 리눅스가 GUI와 CLI를 지원하고 있다고 말했는데, 각각은 그래픽창과 명령창을 의미합니다.</p>
<p><strong>5-1. GUI: Graphical User Interface</strong></p>
<p>위 사진에서 처럼 일반적인 사용자가 흔히 사용하는 인터페이스입니다. 사용자가 편리하게 사용할 수 있도록 기능을 아이콘, 이미지 등의 그래픽으로 나타낸 인터페이스입니다. 마우스 클릭이나 드래그앤드롭이 가능하고 수시로 확인이 가능하여 사용이 쉽습니다. 흔히 사용하는 Windows와 Mac 운영체제 모두 지원하고 있습니다.</p>
<p><strong>5-2. CLI: Command Line Interface</strong></p>
<p>문자로 사용자와 컴퓨터가 상호작용하여 동작하는 인터페이스입니다. Windows의 CMD, Mac의 Terminal에서 CLI를 사용할 수 있습니다.</p>
<h2 id="6-패키지-관리자---apt">6. 패키지 관리자 - apt</h2>
<p>Advanced Packaging Tool의 약자로, 데비안 리눅스(.dev) 또는 파생된 배포판(우분투)에서 소프트웨어를 설치, 제거, 업데이트할 때 사용합니다. 과거에는 설치, 제거, 업데이트에서 apt-get을, 검색과 확인에서는 apt-cache를 따로 사용했습니다. 하지만 최근에는 모두 apt로 통일되었습니다. 다만, 높은 권한이 필요한 활동에 대해서는 apt 앞에 sudo를 함께 입력하여 권한을 획득해야 합니다.</p>
<p><strong>6-1. 권한? sudo?</strong>
패키지 설치와 같은 활동에서는 apt install ~~을 입력했을 때 permission denied라는 메시지와 함께 활동이 제한될 수 있습니다. 이 때, sudo를 입력함으로써 리눅스에서 모든 권한을 가지고 있는 최고 관리자 root의 권한을 획득할 수 있습니다. root는 운영체제의 모든 것을 제어할 권리를 가집니다.</p>
<p>sudo apt install package
sudo와 함께 입력함으로써 관리자 권한을 획득하고, 암호를 입력하면 관리자 권한으로 패키지 설치가 가능합니다.</p>
<p><strong>6-2. 폴더별 권한</strong>
ls -al 명령어를 통해 모든 파일의 모든 속성을 확인할 수 있습니다. 파일의 속성은 다음과 같이 형성됩니다.</p>
<ul>
<li><p>rw-r-r- 1 soryeongk elice 8980 9월 18일 11:52 soryeognk.txt</p>
</li>
<li><p>: 파일 유형을 말하며, -은 파일을 d는 폴더를 의미
rw-r-r-: 파일의 권한
1: 링크된 수
soryeongk: 파일 소유자
elice: 소유 그룹
8980: 파일의 크기
9월 18일 11:52: 마지막 변경 시간
soryeongk.txt: 파일 이름
r(읽기, 4), w(쓰기, 2), x(실행, 1)로 구성되는데, 소유자/그룹/그외사용자 3개의 덩어리로 이루어집니다. 예를 들어, rw-r--r--의 경우, 소유자는 읽기와 쓰기가 가능하고 그룹과 그외 사용자는 읽기만 가능하다는 뜻입니다.</p>
</li>
</ul>
<p>같은 이야기를 숫자로 작성하기도 하며, - 하이픈은 0으로 합니다. 각 권한의 숫자를 더해서 나타내야 하므로 rw 읽기 쓰기 권한은 4+2인 6으로, rx 읽기 실행 권한은 4+1인 5로 나타냅니다. 읽기 쓰기 실행의 권한 4+2+1인 7이 됩니다.</p>
<p>권한을 변경하고 싶을 때에는 이 숫자를 사용해chmod [파일권한] [파일 위치 또는 이름]을 사용하면 됩니다. 가령 소유자는 읽기 쓰기 실행의 권한을, 그룹은 읽기 실행만을, 그외 사용자는 실행의 권한만을 가지게 한다고 하면 751를 입력하면 됩니다. 777은 모든 사용자가 모든 권한을 얻는다는 의미입니다.</p>
<p>소유자를 변경할 때에는 chown [소유할유저]:[소유할 그룹] [파일 위치 또는 파일명]을 입력하면 되며 root 권한이 있어야 실행이 가능합니다.</p>
<h2 id="7-리눅스-파일-시스템">7. 리눅스 파일 시스템</h2>
<p>먼저, 파일이란, 주기억장치나 디스크처럼 하드웨어 저장공간에 저장되는 데이터의 집합을 말합니다.</p>
<p>파일시스템이란, 저장 장치 내에서 데이터를 읽고 쓰기 위해 미리 정한 약속입니다. 하드디스크와 ssd는 데이터가 저장된 위치가 이 약속에 따라 달라집니다. 때문에 파일 저장 및 검색을 할 수 있도록 관리하는 방법도 파일시스템이라고 말합니다. 파일을 어떻게 관리할 것인가에 대한 정책이라고 생각하면 됩니다.</p>
<p>대부분의 파일 시스템은 디렉토리와 파일의 형태로 구성되어 있습니다. 리눅스의 파일시스템은 root 파일 아래에 계층적으로 모든 파일과 디렉토리가 만들어집니다.</p>
<p><strong>7-1. 파일시스템의 종류</strong>
FAT: File Allocate Table
파일 할당 테이블이라고 말하며, 디지털 카메라 등에 장착되는 대부분의 메모리 카드와 수많은 컴퓨터 시스템에 널리 쓰이는 파일 시스템의 종류입니다. 하지만, 너무 단순한 자료구조 탓에 작은 파일이 여러개 있을 경우 공간 활용을 제대로 하지 못한다는 단점이 있습니다. 용량이 계속 커지고 있으며, 높은 호환성을 갖습니다.</p>
<p>NTFS: New Technology File System
Windows NT 계열의 새로운 파일 시스템으로 기존의 FAT 구조를 대체하기위해 만들어졌습니다. 시스템 고장 및 손상 시, 디스크 볼륨을 재구성하여 일관성있는 상태로 복구가 가능하여 안정성이 높고, 보안성도 FAT보다 향상된 파일 시스템입니다.</p>
<p>EXT: EXTended file system
확장 파일 시스템의 준말로 리눅스의 기본 파일 시스템입니다. 성능을 향상시키면서 시리즈로 출시되고 있는데, 기본으로 사용되던 2차 확장 파일 시스템 EXT2를 완벽하게 호환하는 EXT3와 EXT4가 있습니다. EXT3부터 큰 규모의 디렉토리를 접근하기 위해 해쉬를 통해 접근하는 H-tree를 사용하여 데이터 검색이 보다 용이해졌고, EXT4는 지금까지 중 가장 큰 초대형 파일 시스템입니다.</p>
<p><strong>7-2. 리눅스의 디렉토리의 구조</strong>
모든 디렉토리는 최상위 디렉토리인 root이 하위로 만들어집니다.</p>
<p>bin: 기본 명령어들이 저장된 폴더
boot: 리눅스의 boot(시작)와 관련한 명령이 들어간 폴더
etc: 리눅스의 거의 모든 설정 파일이 들어간 폴더
home: 말그대로 홈 폴더, 로그인한 계정에 따라 폴더가 만들어짐
lib: 리눅스 및 각종 프로그램에서 사용되는 라이브러리들의 폴더
🌱root
 ┣ 📦bin
 ┣ 📦home
 ┃ ┣ 📂soryeongk
 ┃ ┃ ┣ 📂바탕화면
 ┃ ┃ ┣ 📂어쩌구 폴더
 ┃ ┃ ┗ 📜index.html
 ┣ 📦lib
 ┣ 📦user
 ┣ 📦boot
 ┗ 📦etc</p>
<h2 id="8-리눅스-명령어">8. 리눅스 명령어</h2>
<p>head, tail: 각각 처음과 끝의 N줄을 출력해주는 명령어로 cat과 함께 자주 쓰임
사용법: cat [filename] | head -n[N] cat [filename] | tail -n[N]
alias: 지정 명령어
su: 현재 사용자 변경하는 명령어
사용법: su [계정명, 없으면 root로]를 입력하고 비밀번호 입력
more: cat과 달리 화면 단위로 출력하며, 스페이스바로 한 칸씩 내리면서 내용 확인 가능
사용법: more [filename]
which: 절대 경로를 알려주는 것으로 명령어의 위치도 알 수 있음
사용법 예시: which cat
wc: 파일의 바이트, 문자, 단어, 라인 수를 출력해주는 명령어
사용법: wc [option] [filname]
shutdown: 시스템 종료 및 재부팅 명령어
사용법예시
shutdown -r now: 즉시 재부팅
shutdown -h now: 즉시 종료
diff: 두 파일 간의 차이를 보여주는 명령어
사용법: diff [filename1] [filename2] - filename1과 filename2의 차이를 보여줍니다.</p>
<p><strong>8-1. File Redirection</strong>
표준 스트림의 흐름을 바꾸어 일반적인 표준 스트림(표준 입력 및 출력 그리고 오류)를 사용하지 않고 다른 경로인 파일로 재지정하는 것을 뜻합니다. &lt;과 &gt;을 이용하여 사용 가능합니다.</p>
<p>표준 스트림?</p>
<p>stdin: 표준입력-키보드 입력
stdout: 표준 출력-화면 출력(cat, ls)
stderr: 표준 오류 출력
예시)
ls &gt; exitedFilename.txt 을 입력하면, ls명령 수행의 결과를 콘솔에 찍어주는 것 대신, exitedFilename.txt에 저장합니다. 기존의 내용을 대체하므로 주의해야합니다.
만약 존재하는 파일이 없는 경우에는 &gt;대신 &gt;&gt;을 사용하여 ls &gt;&gt; newFilename.txt처럼 입력하면 됩니다. 만약 newFilename.txt가 이미 존재하는 파일이라면 기존의 내용은 지우지 않고, 마지막 줄에 이어서 작성합니다.</p>
<p>python 파일을 작성하고, 입력 값을 다른 파일에 저장해둔 경우에도 file redirection을 사용할 수 있습니다.
예를 들어, 다음과 같은 파일들이 같은 폴더 내에 있다고 가정하겠습니다.
add_3.py</p>
<p>input_num = input()
answer = int(input_num) + 3
print(answer)
input_num.txt</p>
<p>10
result.txt</p>
<p>The result is 
input_num.txt의 내용 10을 add_3.py의 입력으로 넣은 뒤, 그 결과를 result.txt의 내용을 지우지 않고 뒤 이어서 담는 명령어의 수행 순서는 다음과 같습니다.</p>
<p>코드 실행을 위한 인터프리터 호출한다. - python [python filename]
&lt;으로 오른쪽의 내용을 왼쪽의 입력값으로 지정한다.
그 결과를 이미 존재하는 result.txt의 내용에 뒤이어 작성한다.
정답: python add_3.py &lt; input_num.txt &gt;&gt; result.txt</p>
<p>해석: 코드 실행을 위한 인터프리터 호출을 위해 python [python filename]을 입력하고, &lt;으로 오른쪽의 내용을 왼쪽의 입력값으로 지정합니다. 그리고 그 결과를 이미 존재하는 result.txt의 내용에 뒤이어 작성하기 위해 &gt;&gt;를 사용합니다.</p>
<p><strong>8-2. piping command</strong>
file redirection과 유사한 pipe는 |로 명령을 구분합니다. 여러가지 복잡한 명령어를 병렬로 작성할 수 있습니다.
가령, 이상에서 file redirection으로 작성한 python add_3.py &lt; input_num.txt &gt;&gt; result.txt의 내용을 piping command로도 똑같이 수행할 수 있습니다. 수행의 과정은 다음과 같습니다.</p>
<p>input_num.txt의 내용을 출력한다.
출력된 내용과 함께 add_3.py를 실행한다.
그 내용을 result.txt에 작성한다. - file redirection 사용
정답: cat input_num.txt | python add_3.py &gt;&gt; result.txt</p>
<h2 id="9-리눅스의-메모장-nano-editor">9. 리눅스의 메모장, nano editor</h2>
<p>UNIX 호환 시스템에서 사용 가능한 가볍고 간단한 텍스트 에디터로, 손쉽게 파일 내용 수정이 가능합니다.</p>
<p>단축키    기능    단축키    기능
ctrl + o    저장    Alt + 6    복사
ctrl + x    종료    ctrl + u    붙여넣기
ctrl + w    검색    ctrl + ^    여러 줄 선택</p>
<h2 id="10-mount">10. mount</h2>
<p>물리적인 저장장치(보조기억장치)를 디렉토리(폴더)에 연결시켜주는 것을 말합니다. windows에서는 하드, USB 등의 보조기억장치를 연결하면 자동으로 디렉토리(폴더)에 연결됩니다. USB를 꽂자마자 사용할 수 있게 되며, 이것을 Plug and Play 즉, PnP라고 말합니다.</p>
<p>하지만 리눅스의 경우 PnP 기능이 작동하지 않습니다. 직접 연결을 위해 보조기억장치를 설치했을 때 mount 작업을 수행해야 합니다.</p>
<p>명령어 기본형태: mount [option] [device] [directory]</p>
<p>device의 내용을 directory에 연결해줍니다.
device의 파일 시스템 명을 알아야하는데, 파일 시스템 명은 fdisk -l로 확인할 수 있습니다.
options</p>
<p>-a: etc/fstab에 명시된 파일 시스템을 마운트할 때 사용
-t: etx/fstab가 아닌 파일 시스템의 유형을 지정할 때 사용
-o: 추가적인 설정을 적요할 때 사용되며, 다수 조건을 적용할 때는 ,로 구분
mount된 디스크 정보 출력
df</p>
<p>mount 해제
remount [device] [directory]</p>
<h2 id="11-리눅스-프로세스">11. 리눅스 프로세스</h2>
<p>프로세스란, 시스템에서 메모리에 적재되어 실행되고 있는 모든 프로그램을 말합니다.</p>
<p>프로그램은 코딩을 통해 만든 코딩(명령어)의 집합체이고, 프로세스는 프로그램이 실행되는 과정 중에 현 상황을 말합니다. 즉, 실행되고 있는 프로그램이 곧 프로세스이며, RAM에 저장됩니다. 한 프로그램 내에서 여러 프로세스가 생성된다면 이를 멀티 프로세싱이라고 말합니다. 이들은 모두 운영체제에 의해 관리됩니다.</p>
<p><strong>11-1. 프로세스의 특징</strong>
모든 프로그램은 실행될 때 하나 이상의 프로세스를 갖는다.
병행적으로 실행이 가능하다.
부모(PPID), 자식(fork를 통해 복사된 것) 프로세스가 있게 된다.
커널(kernel)에 의해 관리된다.
모든 프로세스에는 소유자(리눅스 계정)가 있다.
프로세스마다 식별을 위한 ID(PID)가 부여된다.
PID:
모든 프로세스는 고유한 PID를 가지고 있으며, 1번은 init 프로세스, 2번은 kthreadd(kernel thread demon) 프로세스가 실행됩니다.
init 프로세스는 나머지 모든 시스템 프로세스의 부모 프로세스로, kthreadd가 아닌 다른 모든 프로세스들은 모두 init 프로세스를 fork하여 생성된 것입니다. 또한, kthreadd는 이 후에 실행되는 모든 프로세스의 부모 프로세스입니다.</p>
<p><strong>11-2. RAM(메모리) 구성</strong></p>
<p>프로세스 메모리는 크게 커널 주소 공간(kernel space)와 사용자 주소 공간으로 분리할 수 있으며, 이때 kernel 부분은 사용자가 접근할 수 없습니다. 우리가 사용하는 공간은 stack, heap, data, text 4개의 영역으로 나뉘는데, argv, argc, env, etc 파일들 역시 stack의 일부입니다.</p>
<p><strong>11-3. 관련 명령어</strong>
프로세스 목록 보기
ps [option]</p>
<p>-e: 현재 실행중인 모든 프로세스 정보 출력
-f: 모든 정보 확인
-a: 실행중인 전체 사용자의 모든 프로세스 출력
-u: 프로세스를 실행한 사용자와 프로세스 시작 시간 등을 추력
-x: 터미널 제어 없이 프로세스 현황 보기
조합하여 사용하는 것도 가능</p>
<p>프로세스 종료
kill [option] [PID]</p>
<p>-l: 사용 가능한 시그널 목록을 출력</p>
<p>-1: 재실행(SIGHUP)
-9: 강제종료(SIGKILL)
-15: 정상종료(SIGTERM)</p>
<h2 id="12-job">12. job</h2>
<p>리눅스에서 터미널을 통해 작동하는 거의 모든 명령어는 foreground에서 작동합니다. 즉, 우리가 지금 보고 있는 화면에서 그대로 작동한다는 것입니다. 하지만, &amp;명령을 통해 background를 사용하여 보이지 않는 곳에서도 돌아가게 할 수 있습니다.</p>
<p>job은 그 백그라운드로 실행되는 작업을 보여주고 효율적으로 사용할 수 있게 해주는 명령어입니다. job은 프로세스와 달리 터미널 명령을 통한 작업만을 의미하며, 각 터미널마다 job은 따로 존재합니다. 즉, 터미널이 종료되면 job도 함께 종료되는 의존적 형태입니다.</p>
<p>명령어 뒤에 &amp;를 붙이면 백그라운드에서 실행이 되는데, 이때의 목록은 jobs를 통해 확인할 수 있습니다. 프로세스와 마찬가지로 ps 명령어로 해당 프로세스의 PID를 알아내어 종료하는 것도 가능하고, 옵션 없이 kill %[job 번호]를 통해서도 종료가 가능합니다.</p>
<p>예를 들어, 잠시 멈춤을 의미하는 sleep 명령어를 백그라운드에서 실행하고 종료하는 과정은 다음과 같습니다.</p>
<p>$ sleep 500 &amp;
$ sleep 700 &amp;
$ jobs
이때의 결과 화면은 다음과 같습니다.</p>
<p>[1] - 실행중 sleep 500 &amp;
[2] + 실행중 sleep 700 &amp;
이때 sleep 500 &amp; 종료할 때는 kill %1을 입력하면 됩니다.</p>
<h2 id="13-작업-예약">13. 작업 예약</h2>
<p>13-1. at
지정된 시간에 1회 실행되는 작업 예약 명령어로 시간이 되면 수행되고 작업 리스트에서 사라집니다.</p>
<p>at [option] [time] [date] [+증가시간]</p>
<p>-m: 출력 결과와 함께 작업이 완료될 때 사용자에게 메일을 보냄(결과가 없더라도 메일을 보냄)
-f: 특정 스크립트 파일 등을 실행할 때 사용
at now + 3 hours -f soryeongk.sh은 지금으로부터 3시간 뒤 soryeongk.sh를 실행하라는 의미
-l: 예약된 작업 목록을 출력하며, atq 명령어와 같은 동작을 수행
-v: 작업이 수행될 정확한 시간을 출력
-d: 예약된 작업을 삭제하며, atrm 명령어롸 같은 동작을 수행</p>
<p>atq: 실행 예약이 된 at의 리스트(at번호 날자 시간 명령어)를 보여줌
atrm [at번호]: 해당 예약을 삭제</p>
<p><strong>13-2. crontab</strong>
crontab은 at과는 달리 주기적으로 예약을 실행할 수 있습니다. crontab을 사용한 개인 프로젝트에서 예시를 더 확인할 수 있습니다. 당시 리눅스를 공부하면서 정리한 내용이기에 미흡한 점이 많습니다 ಥ_ಥ</p>
<p>crontab [option] [option에 맞는 text]</p>
<p>-l: 현재 계정의 설정된 crontab 정보를 보여줌
-e: 현재 계정의 crontab 정보를 수정
-r: 현재 계정의 crontab 정보를 모두 삭제
-u: 특정 사용자의 crontab 정보를 다루게 해주며 root 권한 필요해 sudo와 함께 사용</p>
<h2 id="14-ssh">14. SSH</h2>
<p>Secure SHell의 준말로 네트워크를 통해 다른 컴퓨터에 접근하거나 그 컴퓨터에서 명령을 실행할 수 있도록 해주는 프로토콜입니다. 즉, SSH를 통해 다른 컴퓨터에서 리눅스에 접속하여 명령어 및 프로그램을 실행할 수 있습니다.
(예시: [AWS] 아마존 가상 서버에서 Jupyter Notebook 사용하기)</p>
<p>Telnet: SSH 이전에 다른 컴퓨터에 접근하거나 명령을 실행하는 등을 할 수 있도록 해주는 프로토콜이었으나, 보안적으로 매우 치명적인 결함이 존재.
패킷 데이터가 암호화되어있지 않아서 도중에 탈취될 경우 비밀번호 등의 민감정보가 노출되는.. 치명적인..! 때문에 SSH에는 데이터가 암호화되어 있음.</p>
<p>우분투에서는 openssh라는 패키지를 통해 SSH를 구동할 수 있는데, 우분투 설치 후에는 기본적으로 openssh-client만이 설치되어 있습니다. 다른 컴퓨터에서 우분투에 접속하려면 openssh-server 패키지를 설치해야 합니다.</p>
<p>dpkg -l | grep openssh 명령어를 통해 openssh 설치 여부 확인이 가능합니다. 또한, sudo apt-get install open-ssh-server를 통해 설치가 가능합니다.</p>
<p><strong>14-1. ssh 서버 실행</strong>
sudo service ssh start
service --status-all | grep +
종료 시에는 start 대신 stop을, 재시작에는 restart을 입력하면 됩니다.
이상의 명령어를 차례로 입력하면 리스팅이 되는데, ssh만 보고 싶은 경우에는 service --status-all | grep ssh를 입력하면 됩니다.</p>
<p><strong>14-2. ssh 포트 확인하기</strong>
ssh를 사용하기 위해서는 다른 컴퓨터에서 해당 컴퓨터에 어떤 포트로 접속할지를 알아야 합니다. 이를 위해 sudo netstat -antp 명령어를 통해 실행하고 있는 ssh의 포트를 확인할 수 있습니다. PID와 함께 현재 실행중인 프로세스들과 포트를 확인할 수 있습니다.</p>
<p><strong>14-3. ssh 포트 접속하기</strong>
ssh [서버 아이디] @[IP || 서버이름 || 도메인을 입력하면 해당 서버로의 접속이 가능합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tableau quick table calculation]]></title>
            <link>https://velog.io/@zero-pepsi/40</link>
            <guid>https://velog.io/@zero-pepsi/40</guid>
            <pubDate>Wed, 11 Sep 2024 13:37:24 GMT</pubDate>
            <description><![CDATA[<h2 id="quick-table-calculation">Quick Table Calculation</h2>
<ul>
<li><p>Running Total</p>
</li>
<li><p>Difference</p>
</li>
<li><p>Percent Difference</p>
</li>
<li><p>Rank</p>
</li>
<li><p>Ratio Difference
YOY growth rate
percentile
moving average</p>
</li>
<li><p>YTD 총계</p>
</li>
<li><p>통합 성장률</p>
</li>
<li><p>작년 대비 성장률</p>
</li>
<li><p>YTD 성장률</p>
</li>
</ul>
<h3 id="running-total">Running Total</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a9e9b3e1-8143-420f-9f09-6dd51cd1658f/image.png" alt=""></p>
<p><strong>Blue - Monthly Sales
Orange - Sales accumulation</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/ad468cbf-aa37-4827-b85a-c2499ceef3e2/image.png" alt=""></p>
<h3 id="difference">Difference</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/578525f9-dbdd-4618-b66f-8d33cdd883bf/image.png" alt=""></p>
<p><strong>Expressed as difference from the previous quarter for total sales from Q2 2016 to Q4 2019</strong></p>
<p><strong>null is because there is no data for comparison in the first quarter of 2016</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/c97ae610-dcb6-40cf-8f0e-bb0e0bc69297/image.png" alt=""></p>
<p><strong>Difference - difference foramt example</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b4aaeaa0-4201-44b0-ac59-d33cb3c1ab66/image.png" alt=""></p>
<p>Comparison based on the first value</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/c6ae62c0-31fa-4e55-b20f-c9e863565f91/image.png" alt=""></p>
<p>Comparison based on January value of each year</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/39fd56d0-8670-4de1-b96c-268c990458b0/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/c83fd487-a919-414e-9bbc-ebad64d27754/image.png" alt=""></p>
<h3 id="percent-of-total">Percent of Total</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/3f6b7204-123e-47e7-90a9-028e1ffc78a9/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/27df6526-179b-4624-92ee-9ddda55882ae/image.png" alt=""></p>
<p>Proportion of &quot;중분류&quot;</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/45bbc05f-6b02-4726-b21f-49b6d45509ee/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/19011ff4-cb95-4498-864a-c5b6dcf27945/image.png" alt=""></p>
<h3 id="rank">Rank</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/cc38aa5d-c0d4-46f9-a2ea-4b0ab2fddfc2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/52f5f68c-97fc-46b5-8271-ef2f3c840020/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/30f0f256-0986-4611-aed4-93364d984357/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/3c6dfa63-04f3-4582-99a9-b6408706a086/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/16aa0302-bc72-418e-ba60-727ad8872be7/image.png" alt=""></p>
<p><strong>The first ranking is based on the entire table, 
the second ranking is based on the panel within each product category.</strong></p>
<h3 id="percent-difference">Percent Difference</h3>
<p>-&gt; growth rate</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/fa393037-ca13-4b37-9f9f-38ec87e619c7/image.png" alt=""></p>
<h3 id="year-over-year-growth">Year Over Year Growth</h3>
<p><strong>Year-on-year growth rate -&gt; Comparison with previous year in the same month</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/bc332250-e38d-48a6-ab5a-f9a88a7f1133/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e616e1ed-ec91-49b2-aefd-6e93182ac6d0/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a527df6c-5d7a-45ca-8f98-7dcba926d1fd/image.png" alt=""></p>
<h3 id="percentile">Percentile</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/4a86ae5e-c9fa-4760-859a-c7deaa0c54d5/image.png" alt=""></p>
<p><strong>Percentile (expressed as top percent 5%, 10%, etc.)</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/954c1fd1-058e-4b36-93a2-5b45eb78f7c6/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/937eb762-42f8-4e05-a58e-0abff09b5320/image.png" alt=""></p>
<h3 id="moving-average">Moving average</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/3aa74796-f10b-4724-9850-4fed9ceec6f9/image.png" alt=""></p>
<p><strong>Moving average (set the period to calculate the average and then divide by the number of periods)</strong></p>
<p><strong>used for Test score average, Stock data</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/ebe21784-60ab-49f0-a65d-7eb235042406/image.png" alt=""></p>
<p><strong>The average for 2019 2nd quarter 3rd quarter 4th quarter is 337,600,948</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/c7e4d438-fc19-49aa-bb87-73cc6861b5f5/image.png" alt=""></p>
<p>Change the averaging period</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b5127f7b-64d7-443a-8645-9fd16ec9098c/image.png" alt=""></p>
<p>Above the orange moving average line, performance is relatively good, while below the moving average line, the performance is poor due to relative performance.</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/c59381e6-5c03-4df6-a120-2004794ac376/image.png" alt=""></p>
<h3 id="ytd-total">YTD Total</h3>
<p>(From the start of the year to the present) Total up to a certain point in time</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a179161e-2a39-4053-afe6-243ad4f46da0/image.png" alt=""></p>
<p>Sales 2016 sum of January and February is YTD February value</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0871f3e7-8500-41d2-9f2c-04d2ca65cccd/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0cdd1f00-8beb-400b-848f-a78f9254558c/image.png" alt=""></p>
<h3 id="compound-annual-growth-rate-cagr">Compound Annual Growth Rate (CAGR)</h3>
<p>= average annual growth rate</p>
<ul>
<li>The growth rate over several years is converted to an average, and the annual growth rate is converted to a geometric average, not an arithmetic average.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b2f1d69d-6299-4d96-818e-0bb7f6ce75fc/image.png" alt=""></p>
<h3 id="yoy-growth">YOY growth</h3>
<p>Growth rate compared to last year</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/496f798e-915e-4a55-9012-4da961d9c0da/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - HackerRank Certi ]]></title>
            <link>https://velog.io/@zero-pepsi/SQL-HackerRank-Certi</link>
            <guid>https://velog.io/@zero-pepsi/SQL-HackerRank-Certi</guid>
            <pubDate>Wed, 11 Sep 2024 13:15:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f2e7d45d-7abc-4bc0-b86b-f70436706bb5/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[A/B testing study]]></title>
            <link>https://velog.io/@zero-pepsi/38</link>
            <guid>https://velog.io/@zero-pepsi/38</guid>
            <pubDate>Tue, 10 Sep 2024 12:54:28 GMT</pubDate>
            <description><![CDATA[<h3 id="ab-testing-steps">A/B testing steps</h3>
<ol>
<li>Pre-requisites</li>
<li>Experiment Design</li>
<li>Running Experiment</li>
<li>Result to Decision</li>
<li>Post-launch Monitoring</li>
</ol>
<hr>
<h3 id="1pre-requisites">1.Pre-requisites</h3>
<ul>
<li>Objective &amp; Key Metrics<ul>
<li>Key Metric<ul>
<li>Revenue</li>
<li>Fair when N(control) = N(treatment)</li>
<li>Normalize revenue by # of users</li>
<li>Revenue per user</li>
</ul>
</li>
</ul>
</li>
<li>Vatiants<ul>
<li>Control group : checkout</li>
<li>Treatment group 1: display similar products in checkout</li>
<li>Treatment group 2: popup similar products window in checkout</li>
</ul>
</li>
<li>Randomization units<ul>
<li>Users</li>
<li>Assume enough users</li>
</ul>
</li>
</ul>
<h3 id="2experiment-design">2.Experiment Design</h3>
<ul>
<li><strong>User to target</strong><ul>
<li>All users?</li>
<li>Specific segment of users?</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6fb7d728-0d57-4b0d-9af6-39ceea140bae/image.png" alt=""></p>
<p>If choose users from &quot;Land on homepage&quot;, most of them won&#39;t see the feature
therefore, target users should be from &quot;Start checkout&quot;</p>
<ul>
<li><strong>Practical significane boundary</strong><ul>
<li>Assume pratical significane:    <ul>
<li>Revenue incrase : $2 per user</li>
</ul>
</li>
<li>Power of the test : 80% (indsutrial standard)</li>
<li>Significan level : 5% (indsutrial standard)</li>
<li>Sample size 
(sigma = Standard deviation of population / delta = difference between treatment &amp; control
<img src="https://velog.velcdn.com/images/zero-pepsi/post/cd72c1b0-1749-4449-b218-fb91e1e93800/image.png" alt=""></li>
</ul>
</li>
</ul>
<p>Assume sigma is 20 for this example :</p>
<p>16*20^2 / 2^2 = 1600 (we need 1600 unique users in each variant)</p>
<p>therefore 4800 unique users for 3 variants</p>
<pre><code>Other case - Need more samples when

Smaller change, sigma = $1 per suser
Smaller significane level, alpha = 2.5%</code></pre><p><strong>Decide how long to run (consider 4 factors)</strong></p>
<ul>
<li><ol>
<li>Rump-up plan: Start with dozens of users</li>
</ol>
<ul>
<li>No bugs</li>
<li>Traffic can be handled</li>
<li>Expose to a small population</li>
<li>Gradually increase percentage</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e9b0135a-e3d4-468d-bd43-90e27f1f0e19/image.png" alt=""></p>
<p>Assume 2000 users per day entering checkout</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b53cdc7c-7c4f-4442-99ea-a80e0c4fff8a/image.png" alt=""></p>
<ul>
<li><ol start="2">
<li>Day of week effect</li>
</ol>
<ul>
<li>People behave differently (People make more purchases on wage day)</li>
</ul>
</li>
</ul>
<p><strong>Recommended - Run experiment for more then 1 whole week</strong></p>
<ul>
<li><ol start="3">
<li>Seasonality</li>
</ol>
<ul>
<li>Holiday season (Surge in sales during Black Friday)</li>
</ul>
</li>
</ul>
<p><strong>so the data during the holidays can not be used for analysis and run experiment longer</strong></p>
<ul>
<li><ol start="4">
<li>Primacy and novelty effects</li>
</ol>
<ul>
<li>users respond to changes differently</li>
</ul>
</li>
</ul>
<h3 id="3running-experiment">3.Running Experiment</h3>
<p>running the experiment based on experiment design and collecting log data</p>
<p><strong>Running experiment for too long will not imporve precision any further</strong></p>
<h3 id="4result-to-decision">4.Result to Decision</h3>
<p><strong>Before into analysis</strong></p>
<ul>
<li>Sanity checks<ul>
<li>Unreliable if assumptions are violated</li>
</ul>
</li>
</ul>
<p>Things need to check</p>
<ol>
<li>number of users assigned to groups</li>
<li>Latency when loading the webpage (user experience is consistant among each group)</li>
</ol>
<ul>
<li>Hypotheses test to make recommendation</li>
</ul>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/2e752490-4f33-4796-9dc3-5412f0b6ea20/image.png" alt=""></p>
<p><strong>Recommend launching a change when</strong></p>
<ol>
<li>Statistically significant</li>
<li>Practically significant</li>
</ol>
<p><strong>Treatment 1 vs control</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/587fba6e-93b0-42b4-b174-82862309e2bb/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/8ae9d671-8337-4af3-98c7-e942355745b2/image.png" alt=""></p>
<p><strong>Result of treatment 1 (arguable)</strong></p>
<ul>
<li>No impact at all 
or</li>
<li>Impact is significant enough</li>
</ul>
<p><strong>Recommendation of treatment 1</strong></p>
<p>Due to some uncertainty</p>
<ul>
<li>Do not launch the change</li>
<li>Run a follow-up test with more power</li>
</ul>
<p><strong>Treatment 2 vs control</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a24d22bf-d79d-4ff7-b57a-705ccad1629e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b14dcdba-ea1c-4981-b80d-0b0af69d391e/image.png" alt=""></p>
<p><strong>Recommendation of treatment 2</strong></p>
<ul>
<li>Run a follow-up test with more power</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Data analysis dashboard (Excel)]]></title>
            <link>https://velog.io/@zero-pepsi/33</link>
            <guid>https://velog.io/@zero-pepsi/33</guid>
            <pubDate>Fri, 06 Sep 2024 13:08:57 GMT</pubDate>
            <description><![CDATA[<p><strong>Name of the file : Data Analysis of Coca-Cola 2023 &amp; 2024 USA Sales Performance</strong></p>
<p><strong>Data source :</strong> <a href="https://www.kaggle.com/datasets/sanjanamurthy392/coca-cola-sales">kaggle</a></p>
<hr>
<h3 id="data-analysis-dashboard-practice-using-excel">Data analysis dashboard practice using Excel</h3>
<ol>
<li>Structure</li>
<li>Analysis</li>
<li>Visuals</li>
<li>Slicers</li>
</ol>
<h3 id="1-structure">1. Structure</h3>
<p><strong>Setup the basic structure for dashboard</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/78f48a2e-c7b4-43f4-b346-fcf2cdaf2a8d/image.png" alt=""></p>
<h3 id="2-analysis">2. Analysis</h3>
<p><strong>Analysis with pivot table</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/5e2d360a-4f21-4531-ac61-9ddca6ed4c0c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f021ad97-e150-40d8-9dc0-32139620d9e1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a2de0d78-73d3-49ce-9fc7-397cbf39f2f1/image.png" alt=""></p>
<h3 id="3-visuals">3. Visuals</h3>
<p><strong>Visual representation through charts and tables</strong></p>
<p>1.Sales </p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e6df9362-f1ec-4f70-a1a8-3c42ac445244/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b622e9dc-100e-435b-84ad-94f87e292e00/image.png" alt=""></p>
<ol start="2">
<li>KPI&#39;s</li>
</ol>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/54f374c8-dee7-4201-a1dd-c99f2e150998/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e54b024d-d3e1-40be-a5f1-22e29ce1ac78/image.png" alt=""></p>
<ol start="3">
<li>Sales and margin chart</li>
</ol>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/84d75004-c015-4190-b726-3bce3a3b42d4/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/abc955d9-e46c-45c7-9071-85e3ae64ec0c/image.png" alt=""></p>
<h3 id="4-adding-slicers">4. Adding slicers</h3>
<p><strong>Make dashboard more dynamic</strong></p>
<p>Region - Midwest</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/d53a0c61-e943-445d-9280-9ffdf8a08b7e/image.png" alt=""></p>
<p>Region - South</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/7f89883c-1630-4db9-9f98-2ac7d43e8c6f/image.png" alt=""></p>
<p>Region - South</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6423ae9f-3f49-419e-a80d-2acf672023b3/image.png" alt=""></p>
<p>default (all regions and all years)</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e0fbc2be-7f04-4f3e-9487-b54f77bd4d0e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tableau dashboard]]></title>
            <link>https://velog.io/@zero-pepsi/32</link>
            <guid>https://velog.io/@zero-pepsi/32</guid>
            <pubDate>Fri, 06 Sep 2024 13:08:53 GMT</pubDate>
            <description><![CDATA[<h3 id="action-6-options">Action (6 options)</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e409662f-2f2f-4777-b27b-f6d881cfdd4c/image.png" alt=""></p>
<h3 id="filter--highlight">Filter + Highlight</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6d1f2343-2926-4c3b-af41-efac6a8070c4/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/3712d5e0-33e6-4600-86c0-4961113337ea/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/4481a15f-d5e3-45e8-b5da-6028152249ac/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0b8d7df1-e7cc-4129-9552-6e0e224ac900/image.png" alt=""></p>
<h3 id="go-to-sheet">Go to sheet</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/081a2312-9b28-4dca-9137-0609b5c4ba82/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/1cd55a6a-21a0-4ced-8c41-c36e28e32aac/image.png" alt=""></p>
<h3 id="change-parameter">Change parameter</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0f41aa3d-2f9a-461b-82ce-65869134d331/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/ce0ff4fe-1d39-4a27-b5b1-611d4af1cbc2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6a8bd9f7-c909-4b3c-a064-1e2bd2bc145d/image.png" alt=""></p>
<p><strong>Parameter Dashboard</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/21b7ca1e-a29c-440a-bd53-554f6d63218e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/97fa87f1-bb6d-45fc-ba86-7bd18fec7907/image.png" alt=""></p>
<h3 id="change-set-values">Change set values</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/34adc033-314a-4321-a3d5-1eba15364c00/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/fa746e88-a79c-4386-98a8-b477f32fdf0e/image.png" alt=""></p>
<h3 id="url">URL</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/25adeb5b-7a7a-4519-bd5e-17c80e7ee1ff/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/430f3536-ec3e-4efd-8e94-e2c16f33f50f/image.png" alt=""></p>
<hr>
<h3 id="layout-modification">Layout modification</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/fc685f9b-0306-44d2-a54a-be10256d0584/image.png" alt=""></p>
<h3 id="story-collection-of-dashboards">Story (collection of dashboards)</h3>
<ul>
<li>Is the topic of interest to the audience?</li>
<li>Ultimately, what do I want to say?</li>
<li>Planning according to the flow from start to finish</li>
<li>Avoid using too much data or computational parameters unnecessarily.</li>
<li>If complex calculations are made with data, it takes a long time to load the dashboard.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/1da38055-6182-4154-8272-5737470a3880/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/9da41182-cff4-4634-89d6-b71c806f0506/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - HackerRank Certi ]]></title>
            <link>https://velog.io/@zero-pepsi/31</link>
            <guid>https://velog.io/@zero-pepsi/31</guid>
            <pubDate>Fri, 06 Sep 2024 13:08:49 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/fcb73f45-513b-45b9-9e37-c667fe843e03/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Coffee shops analysis (MySQL)]]></title>
            <link>https://velog.io/@zero-pepsi/SQL-Mini-Task-AWSPython-Eng</link>
            <guid>https://velog.io/@zero-pepsi/SQL-Mini-Task-AWSPython-Eng</guid>
            <pubDate>Wed, 04 Sep 2024 07:50:13 GMT</pubDate>
            <description><![CDATA[<h2 id="problem-1">Problem 1.</h2>
<p>Create a project-related database in AWS RDS (MySQL) and create an accessible user account.</p>
<p>Database Name: oneday
User Name / Password: oneday / 1234</p>
<p><strong>Call required module</strong></p>
<pre><code>pip install mysql-connector-python
import mysql.connector

import mysql.connector
mydb = mysql.connector.connect(
    host = &quot;your aws rds&#39;s host name&quot;,
    port = 3306,
    user = &quot;your ID&quot;,
    password = &quot;your password&quot;
)

cursor = mydb.cursor(buffered = True)</code></pre><p><strong>Account setting</strong></p>
<pre><code>sql = &#39;create database oneday default character set utf8mb4&#39;
cursor.execute(sql)

cursor.execute(&quot;create user &#39;oneday&#39;@&#39;%&#39; identified by &#39;1234&#39;&quot;)
cursor.execute(&quot;grant all on oneday.* to &#39;oneday&#39;@&#39;%&#39;&quot;)</code></pre><p><strong>Checking</strong></p>
<ul>
<li>Database creation statement query result: SHOW CREATE DATABASE oneday;</li>
<li>User permission check result: SHOW GRANT FOR ‘oneday’@‘%’</li>
</ul>
<pre><code>result1 = &quot;show create database oneday&quot;
cursor.execute(result1)

result1 = cursor.fetchall()
for i in result1:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/8b988269-1594-4d2c-b49d-62ff19fdadf2/image.png" alt=""></p>
<pre><code>result2 = &quot;show grants for &#39;oneday&#39;@&#39;%&#39;&quot;
cursor.execute(result2)

result2 = cursor.fetchall()
for i in result2:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0cff0969-0f8c-4260-92d8-d071b145beda/image.png" alt=""></p>
<h2 id="problem-2">Problem 2.</h2>
<p>Create a table to store Starbucks Ediya data</p>
<pre><code>cursor.execute(&#39;use oneday&#39;)

cBrand = &quot;create table COFFEE_BRAND(id int not null auto_increment primary key, name varchar(12))&quot;
cursor.execute(cBrand)

cStore = &quot;create table COFFEE_STORE(id int not null auto_increment primary key, brand int, name varchar(32) not null, gu_name varchar(5) not null, address varchar(128) not null, lat decimal(16,14) not null, lng decimal(17,14) not null, foreign key (brand) references COFFEE_BRAND(id))&quot;
cursor.execute(cStore)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/87a7d15e-6a70-4cd1-a3ae-487662b812c5/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e2bce484-e466-4234-8b22-9ac69834d0c1/image.png" alt=""></p>
<p><strong>Checking</strong></p>
<ul>
<li>Table creation result: Desc COFFEE_BRAND; Desc COFFEE_STORE;</li>
<li>COFFEE_BRAND query result: SELECT * FROM COFFEE_BRAND;</li>
</ul>
<pre><code>result3 = &#39;desc COFFEE_BRAND&#39;
cursor.execute(result3)

result3 = cursor.fetchall()
for i in result3:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/09117373-a080-4c5c-8679-d5062b4fa401/image.png" alt=""></p>
<pre><code>result4 = &#39;desc COFFEE_STORE&#39;
cursor.execute(result4)

result4 = cursor.fetchall()
for i in result4:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0fffaf9b-1244-4977-97fc-265d21e08ed2/image.png" alt=""></p>
<h2 id="problem-3">Problem 3.</h2>
<p>Enter and check the COFFEE_BRAND data with Python code as follows.</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/3f0b55c0-c1c6-4d68-843c-57ae2bb4d21a/image.png" alt=""></p>
<pre><code>cursor = mydb.cursor(buffered = True)
cursor.execute(&quot;insert into COFFEE_BRAND values (1, &#39;STARBUCKS&#39;), (2, &#39;EDIYA&#39;)&quot;)
conn.commit()</code></pre><p><strong>Checking</strong></p>
<pre><code>result5 = &quot;select * from COFFEE_BRAND&quot;
cursor.execute(result5)

result5 = cursor.fetchall()
for i in result5:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/85765979-4ae9-41c7-a8f6-8907d1f056f0/image.png" alt=""></p>
<h2 id="problem-4">Problem 4.</h2>
<p>When importing data from the Starbucks page with Python code, modify it to enter directly into the COFFEE_STORE table.</p>
<pre><code>url = &quot;https://www.starbucks.co.kr/store/store_map.do&quot;
driver = webdriver.Chrome()
driver.get(url)

driver.find_element(By.CSS_SELECTOR,&#39;#container &gt; div &gt; form &gt; fieldset &gt; div &gt; section &gt; article.find_store_cont &gt; article &gt; header.loca_search &gt; h3 &gt; a&#39;).click()
time.sleep(0.5)
driver.find_element(By.CSS_SELECTOR, &#39;.set_sido_cd_btn&#39;).click()
time.sleep(0.5)

xpath = &#39;//*[@id=&quot;mCSB_2_container&quot;]/ul/li[1]/a&#39;
tag = driver.find_element(By.XPATH, xpath)
tag.click()
time.sleep(0.5)</code></pre><pre><code>soup = BeautifulSoup(driver.page_source, &quot;html.parser&quot;)
seoul_list = driver.find_elements(By.CSS_SELECTOR, &#39;#mCSB_3_container ul li&#39;)
soup.select_one(f&#39;#mCSB_3_container &gt; ul &gt; li:nth-child(100) &gt; p&#39;).text[:-9]</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/032946e0-791f-4817-bb0c-f3fad77b6226/image.png" alt=""></p>
<p>Read entire data</p>
<pre><code>cursor = mydb.cursor(buffered=True)

sql = &quot;insert into COFFEE_STORE (brand, name, gu_name, address, lat, lng) values (1, %s, %s, %s, %s, %s)&quot;

cnt = 1

for content in tqdm_notebook(seoul_list):
    name = content.get_attribute(&#39;data-name&#39;)
    address = soup.select_one(f&#39;#mCSB_3_container &gt; ul &gt; li:nth-child({cnt}) &gt; p&#39;).text[:-9]
    lat = content.get_attribute(&#39;data-lat&#39;)
    lng = content.get_attribute(&#39;data-long&#39;)
    gu_name = address.split()[1] if address else &#39;&#39;

    cnt += 1

    cursor.execute(sql, (name, gu_name, address, lat, lng))
    conn.commit()

    driver.close()</code></pre><p>Count Records</p>
<pre><code>count_query = &#39;SELECT COUNT(*) FROM COFFEE_STORE where brand = 1;&#39;
cursor.execute(count_query)

record_count = cursor.fetchone()[0]
record_count</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b1a5d363-7225-419e-b6cc-a50e65b2ce02/image.png" alt=""></p>
<p>Checking 10 records</p>
<pre><code>check = &quot;select * from COFFEE_STORE where brand = 1 limit 10&quot;
cursor.execute(check)

result = cursor.fetchall()
for i in result:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/043cb25e-4b2f-4e79-bd25-03e2c1611e78/image.png" alt=""></p>
<h2 id="problem-5">Problem 5.</h2>
<p>When importing data from the Ediya page with Python code, modify it to enter directly into the COFFEE_STORE table.</p>
<p>Collecting Data</p>
<pre><code>driver = webdriver.Chrome() 
driver.get(&#39;https://www.ediya.com/contents/find_store.html&#39;)
driver.find_element(By.CSS_SELECTOR, &#39;#contentWrap &gt; div.contents &gt; div &gt; div.store_search_pop &gt; ul &gt; li:nth-child(2) &gt; a&#39;).click()

sql = &quot;INSERT INTO COFFEE_STORE (brand, name,gu_name, address, lat, lng) VALUES (2, %s, %s, %s, %s, %s)&quot;

for gu in tqdm_notebook(gu_list):

    keyword = driver.find_element(By.CSS_SELECTOR, &#39;#keyword&#39;)
    keyword.clear()
    keyword.send_keys(gu)

    driver.find_element(By.CSS_SELECTOR, &#39;#keyword_div &gt; form &gt; button&#39;).click()

    time.sleep(1)  

    html = driver.page_source
    soup_ed = BeautifulSoup(html, &#39;html.parser&#39;)
    contents = soup_ed.select(&#39;#placesList li&#39;)

    for content in contents:
        name = content.select_one(&#39;dt&#39;).text
        address = content.select_one(&#39;dd&#39;).text
        gu_name = address.split(&#39; &#39;)[1]

        print(f&#39;{name}--{address}--{gu_name}&#39;)

        cursor.execute(sql,(name, gu_name, address, lat, lng))
        conn.commit()

        driver.close()</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/fd3a5967-e48c-4348-8d1b-0c558c422854/image.png" alt=""></p>
<p>Recoords count</p>
<pre><code>count_query = &#39;SELECT COUNT(*) FROM COFFEE_STORE where brand = 2;&#39;
cursor.execute(count_query)

record_count = cursor.fetchone()[0]
record_count</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6d8b837d-e04a-485f-82b4-c39785027e91/image.png" alt=""></p>
<p>Checking 10 records</p>
<pre><code>cursor.execute(&quot;select * from COFFEE_STORE where brand = 2 limit 10;&quot;)
result = cursor.fetchall()
for row in result:
    print(row)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/1d41722b-b439-4354-bec7-6535032c6001/image.png" alt=""></p>
<p><strong>Checking</strong></p>
<ul>
<li>Main distribution areas of Starbucks stores (names of top 5 districts with the most stores, output of number of stores)</li>
</ul>
<pre><code>strb = &quot;select s.gu_name, count(s.brand) from COFFEE_BRAND as b, COFFEE_STORE as s where b.id = s.brand and b.name=&#39;STARBUCKS&#39; group by s.gu_name order by count(s.brand) desc limit 5&quot;

cursor.execute(strb)
result = cursor.fetchall()

for row in result:
    print(row)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/d8268605-1a55-4914-878e-f04cad6d0fd5/image.png" alt=""></p>
<ul>
<li>Ediya store main distribution area (name of top 5 districts with most stores, output number of stores)</li>
</ul>
<pre><code>edy = &quot;select s.gu_name, count(s.brand) from COFFEE_BRAND as b, COFFEE_STORE as s where b.id = s.brand and b.name=&#39;EDIYA&#39; group by s.gu_name order by count(s.brand) desc limit 5&quot;

cursor.execute(edy)
result = cursor.fetchall()

for row in result:
    print(row)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b84124cf-be60-40f5-a0d3-8463a304ddef/image.png" alt=""></p>
<ul>
<li>Search the number of stores for each distinct brand (output old name, brand name, number of stores)</li>
</ul>
<pre><code>  gu_each_st = &quot;select gu_name, &#39;스타벅스&#39; as brand, count(brand) as count from COFFEE_STORE where brand = 1 group by gu_name&quot;

  cursor.execute(gu_each_st)
  result = cursor.fetchall()

  for row in result:
      print(row)

  gu_each_ed = &quot;select gu_name, &#39;이디야&#39; as brand, count(brand) as count from COFFEE_STORE where brand = 2 group by gu_name&quot;

  cursor.execute(gu_each_ed)
  result = cursor.fetchall()

  for row in result:
      print(row)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f9a4a7bf-e0f9-48f9-a76c-8f351a1080f6/image.png" alt=""></p>
<ul>
<li>Check the number of stores for each brand (output old name, number of Starbucks stores, number of Ediya stores)</li>
</ul>
<pre><code>count = (&quot;select s.gu_name, &quot;
         &quot;sum(s.brand=1) as count1, &quot;
         &quot;sum(s.brand=2) as count2 &quot;
         &quot;from COFFEE_BRAND b, COFFEE_STORE s &quot; 
         &quot;where b.id = s.brand &quot; 
         &quot;group by s.gu_name &quot; 
         &quot;order by s.gu_name;&quot;)

cursor.execute(count)
result = cursor.fetchall()

for row in result:
    gu_name, count1, count2 = row
    print(f&#39;({gu_name}, {count1}, {count2})&#39;)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6c02a22f-0b6a-4901-8444-007b0770b9ae/image.png" alt=""></p>
<h2 id="problem-6">Problem 6.</h2>
<p> Save as CSV file. (Working with Python code)</p>
<pre><code>final = (&quot;select A.*, B.* from (select * from COFFEE_STORE where brand=1) as A join (select * from COFFEE_STORE where brand=2) as B on B.gu_name = A.gu_name&quot;)

cursor.execute(final)
result = cursor.fetchall()

df = pd.DataFrame(result)
df.columns = [&#39;s_id&#39;, &#39;s_brand&#39;, &#39;s_name&#39;, &#39;s_gu&#39;, &#39;s_address&#39;, &#39;s_lat&#39;, &#39;s_lng&#39;, 
              &#39;e_id&#39;, &#39;e_brand&#39;, &#39;e_name&#39;, &#39;e_gu&#39;, &#39;e_address&#39;, &#39;e_lat&#39;, &#39;e_lng&#39;]

df.to_csv(&#39;./starbucks_ediya.csv&#39;, index = False, encoding = &quot;euc-kr&quot;)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - Contest Leaderboard]]></title>
            <link>https://velog.io/@zero-pepsi/29</link>
            <guid>https://velog.io/@zero-pepsi/29</guid>
            <pubDate>Sat, 31 Aug 2024 13:52:43 GMT</pubDate>
            <description><![CDATA[<p>You did such a great job helping Julia with her last coding contest challenge that she wants you to work on this one, too!</p>
<p>The total score of a hacker is the sum of their maximum scores for all of the challenges. Write a query to print the hacker_id, name, and total score of the hackers ordered by the descending score. If more than one hacker achieved the same total score, then sort the result by ascending hacker_id. Exclude all hackers with a total score of  from your result.</p>
<p><strong>Input Format</strong></p>
<p>The following tables contain contest data:</p>
<ul>
<li>Hackers: The hacker_id is the id of the hacker, and name is the name of the hacker.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/634e6932-6054-484e-8720-9c04ae699b2f/image.png" alt=""></p>
<ul>
<li>Submissions: The submission_id is the id of the submission, hacker_id is the id of the hacker who made the submission, challenge_id is the id of the challenge for which the submission belongs to, and score is the score of the submission.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/48a97c06-7987-4828-8ace-b43cd76ebcd3/image.png" alt=""></p>
<p><strong>Sample Input</strong></p>
<p>Hackers Table:</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/13a82b43-269b-457a-9e6e-e1ad47bb8c1e/image.png" alt=""></p>
<p>Submissions Table:</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b7d84948-557a-4d6b-a41d-a7716504c1a6/image.png" alt=""></p>
<p><strong>Sample Output</strong></p>
<pre><code>4071 Rose 191
74842 Lisa 174
84072 Bonnie 100
4806 Angela 89
26071 Frank 85
80305 Kimberly 67
49438 Patrick 43</code></pre><p><strong>Explanation</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/44c448a0-a14d-46aa-8e99-e0b1b9027ba4/image.png" alt=""></p>
<hr>
<p>Answer : </p>
<pre><code>SELECT h.hacker_id, h.name, SUM(score) FROM (
    SELECT hacker_id, challenge_id, MAX(score) AS score FROM SUBMISSIONS
    GROUP BY hacker_id, challenge_id
)t 
JOIN Hackers h on t.hacker_id = h.hacker_id
GROUP BY h.hacker_id, h.name
HAVING SUM(score) &gt; 0
ORDER BY SUM(score) desc, h.hacker_id</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - Project Planning]]></title>
            <link>https://velog.io/@zero-pepsi/28</link>
            <guid>https://velog.io/@zero-pepsi/28</guid>
            <pubDate>Sat, 31 Aug 2024 13:52:38 GMT</pubDate>
            <description><![CDATA[<p>You are given a table, Projects, containing three columns: Task_ID, Start_Date and End_Date. It is guaranteed that the difference between the End_Date and the Start_Date is equal to 1 day for each row in the table.</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/8bd17789-d8cd-4334-9f25-2daa94411c18/image.png" alt=""></p>
<p>If the End_Date of the tasks are consecutive, then they are part of the same project. Samantha is interested in finding the total number of different projects completed.</p>
<p>Write a query to output the start and end dates of projects listed by the number of days it took to complete the project in ascending order. If there is more than one project that have the same number of completion days, then order by the start date of the project.</p>
<p><strong>Sample Input</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6f56286d-7a53-4260-a590-24480fbb6198/image.png" alt=""></p>
<p><strong>Sample Output</strong></p>
<pre><code>2015-10-28 2015-10-29
2015-10-30 2015-10-31
2015-10-13 2015-10-15
2015-10-01 2015-10-04</code></pre><p><strong>Explanation</strong></p>
<p>The example describes following four projects:</p>
<ul>
<li><p>Project 1: Tasks 1, 2 and 3 are completed on consecutive days, so these are part of the project. Thus start date of project is 2015-10-01 and end date is 2015-10-04, so it took 3 days to complete the project.</p>
</li>
<li><p>Project 2: Tasks 4 and 5 are completed on consecutive days, so these are part of the project. Thus, the start date of project is 2015-10-13 and end date is 2015-10-15, so it took 2 days to complete the project.</p>
</li>
<li><p>Project 3: Only task 6 is part of the project. Thus, the start date of project is 2015-10-28 and end date is 2015-10-29, so it took 1 day to complete the project.</p>
</li>
<li><p>Project 4: Only task 7 is part of the project. Thus, the start date of project is 2015-10-30 and end date is 2015-10-31, so it took 1 day to complete the project.</p>
</li>
</ul>
<hr>
<p>Answer :</p>
<pre><code>/* A date is a start-date if it&#39;s not end-date for anyone */
WITH START_DATES AS (
    SELECT Start_Date
    FROM Projects
    WHERE Start_Date NOT IN (
        SELECT DISTINCT End_Date FROM Projects
    )
),
/* A date is a end-date if it&#39;s not start-date for anyone */
END_DATES AS (
    SELECT End_Date
    FROM Projects
    WHERE End_Date NOT IN (
        SELECT DISTINCT Start_Date FROM Projects
    )
)
SELECT 
    S.Start_Date AS SD, 
    /* For each start-date, corresponding end-date is the nearest end-date which is higher than start-date */
    (SELECT MIN(E.End_Date) FROM END_DATES E WHERE E.End_Date &gt; S.Start_Date) AS ED
FROM 
    START_DATES S
ORDER BY
    (ED - SD) ASC,
    SD ASC;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Gas station analysis (MySQL)]]></title>
            <link>https://velog.io/@zero-pepsi/27</link>
            <guid>https://velog.io/@zero-pepsi/27</guid>
            <pubDate>Sat, 31 Aug 2024 13:52:31 GMT</pubDate>
            <description><![CDATA[<p><strong>Call required module and connect to database in AWS RDS</strong></p>
<pre><code>import mysql.connector

conn = mysql.connector.connect(
    host = &quot;your host&quot;,
    port = 3306,
    user = &quot;xxx&quot;,
    password = &quot;xxx&quot;,
    database = &quot;xxx&quot;
)

cursor = conn.cursor(buffered=True)</code></pre><h3 id="problem-1">Problem 1.</h3>
<p>Create a table to store gas station data with the following structure.</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a95b80fa-2f6d-472a-83f7-cb18fd4ebda8/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/52037ed7-0bec-4406-9238-1da4c52a9e7c/image.png" alt=""></p>
<pre><code># gas_brand
sql_b = &quot;CREATE TABLE GAS_BRAND(&quot; + \
            &quot;id int not null auto_increment primary key, &quot; + \
            &quot;name varchar(16) not null)&quot;

cursor.execute(sql_b)

# gas_station
sql_s = &quot;CREATE TABLE GAS_STATION(&quot; + \
            &quot;id int auto_increment primary key, &quot; +\
            &quot;brand int not null, &quot; +\
            &quot;name varchar(64) not null, &quot; +\
            &quot;city char(2) not null, &quot; +\
            &quot;gu varchar(10) not null, &quot; +\
            &quot;address varchar(128) not null, &quot; +\
            &quot;gasoline int not null, &quot; +\
            &quot;diesel int not null, &quot; +\
            &quot;self boolean not null, &quot; +\
            &quot;car_wash boolean not null, &quot; +\
            &quot;charging_station boolean not null, &quot; +\
            &quot;car_maintenance boolean not null, &quot; +\
            &quot;convenience_store boolean not null, &quot; +\
            &quot;24_hours boolean not null, &quot; +\
            &quot;lat decimal(16,14) not null, &quot; +\
            &quot;lng decimal(17,14) not null, &quot; +\
            &quot;foreign key (brand) references GAS_BRAND(id));&quot;

cursor.execute(sql_s)</code></pre><h3 id="problem-2">Problem 2.</h3>
<p>Enter and check the GAS_BRAND data with Python code as follows.</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/9c5011d3-b32c-4f33-8aa3-e36fbb7886aa/image.png" alt=""></p>
<pre><code>cursor.execute(&quot;insert into GAS_BRAND values (1, &#39;SK에너지&#39;)&quot;)
cursor.execute(&quot;insert into GAS_BRAND values (2, &#39;현대오일뱅크&#39;)&quot;)
cursor.execute(&quot;insert into GAS_BRAND values (3, &#39;GS칼텍스&#39;)&quot;)
cursor.execute(&quot;insert into GAS_BRAND values (4, &#39;S-OIL&#39;)&quot;)
cursor.execute(&quot;insert into GAS_BRAND values (5, &#39;알뜰주유소&#39;)&quot;)
cursor.execute(&quot;insert into GAS_BRAND values (6, &#39;자가상표&#39;)&quot;)
connect.commit()</code></pre><p>Table creation result: Desc GAS_BRAND; Desc GAS_STATION;</p>
<pre><code>sql_result = &quot;DESC GAS_STATION&quot;
cursor.execute(sql_result)

result = cursor.fetchall()
for i in result:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e9525d1f-7ec2-4d48-842b-3289e6b868f1/image.png" alt=""></p>
<p>GAS_BRAND query result: SELECT * FROM GAS_BRAND;</p>
<pre><code>sql_result = &quot;SELECT * FROM GAS_BRAND&quot;
cursor.execute(sql_result)

result = cursor.fetchall()
for i in result:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/9f07dbbd-1197-4c6c-947b-e4878dda7bd7/image.png" alt=""></p>
<h3 id="problem-3">Problem 3.</h3>
<p>Write the following function and test it</p>
<p>a. function that takes the currency unit character type as input and returns it as a numeric type (test input: ‘1,000’)</p>
<pre><code>def stringToInt(s):
    if s != &#39;&#39;:
        s = s.replace(&#39;,&#39;, &#39;&#39;)
        return int(s)
    else: 
        return None

stringToInt(&#39;1,000&#39;)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/aa60d199-5b7d-42fd-a9ae-50cd486a62b4/image.png" alt=""></p>
<p>b. When a gas station brand is entered, a function returns an ID by referring to GAS_BRAND data (test input: ‘SK Energy’) - A function that receives an address and returns the district name (test input: ‘730 Heolleung-ro, Gangnam-gu, Seoul’)</p>
<pre><code>def getID(brand):
    sql_result = &quot;SELECT * FROM GAS_BRAND&quot;
    cursor.execute(sql_result)
    result = cursor.fetchall()
    for i in result:
        if i[1] == brand:
            return i[0]
        elif brand == &#39;알뜰(ex)&#39;:
            return 5

getID(&#39;SK에너지&#39;)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/1b9f060e-fa7e-446b-a47a-07c34e1c8ab3/image.png" alt=""></p>
<pre><code>def getGu(add):
    addList = add.split()
    return addList[1]

getGu(&#39;서울시 강남구 헌릉로 730&#39;)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/696a8dba-b609-4f39-a0d2-abd41813a01a/image.png" alt=""></p>
<p>c. A function that receives an address and returns latitude and longitude (test input: ‘730 Heolleung-ro, Gangnam-gu, Seoul’)</p>
<pre><code>import googlemaps
gmaps_key = &quot;AIzaSyBn4xqGnCRJRbB-y4uCvBjqNu97pCuXcnc&quot;
gmaps = googlemaps.Client(key = gmaps_key)

def getLL(add):
    tmp = gmaps.geocode(add, language=&#39;ko&#39;)
    lat = tmp[0].get(&quot;geometry&quot;)[&quot;location&quot;][&quot;lat&quot;]
    lng = tmp[0].get(&quot;geometry&quot;)[&quot;location&quot;][&quot;lng&quot;]

    return lat, lng

getLL(&#39;서울시 강남구 헌릉로 730&#39;)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/13918801-a69b-464b-a6ba-59f952da2d32/image.png" alt=""></p>
<h3 id="problem-4">Problem 4.</h3>
<p>When importing data from the gas station page in the Python code, modify it to enter directly into the GAS_STATION table.</p>
<pre><code>import time 
from selenium import webdriver
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
from tqdm import tqdm_notebook

url = &#39;https://www.opinet.co.kr/searRgSelect.do&#39;
driver = webdriver.Chrome()
driver.get(url)</code></pre><pre><code>sido_list_raw = driver.find_element(By.ID, &quot;SIDO_NM0&quot;)
sido_list = sido_list_raw.find_elements(By.TAG_NAME, &quot;option&quot;)</code></pre><pre><code>seoul_select = sido_list[1].get_attribute(&quot;value&quot;)
sido_list_raw.send_keys(seoul_select)</code></pre><pre><code>gu_list_raw = driver.find_element(By.ID, &quot;SIGUNGU_NM0&quot;)
gu_list = gu_list_raw.find_elements(By.TAG_NAME, &quot;option&quot;)

gu_names = [option.get_attribute(&quot;value&quot;) for option in gu_list]
gu_names = gu_names[1:]</code></pre><pre><code>sql = &quot;INSERT INTO GAS_STATION (brand, name, city, gu, address, gasoline, diesel, self, &quot; +\
        &quot;car_wash, charging_station, car_maintenance, convenience_store, 24_hours, lat, lng) &quot; +\
        &quot;VALUES (%s, %s, &#39;서울&#39;, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)&quot;</code></pre><pre><code>def check(data, tag):
    return &#39;off&#39; not in data.select_one(tag)[&#39;src&#39;]</code></pre><pre><code>sqltmp = &quot;ALTER TABLE GAS_STATION MODIFY diesel int NULL;&quot;
cursor.execute(sqltmp)
conn.commit()

for gu in tqdm_notebook(gu_names):
    element = driver.find_element(By.ID, &#39;SIGUNGU_NM0&#39;)
    element.send_keys(gu)
    time.sleep(0.5)

    html = driver.page_source
    soup = BeautifulSoup(html, &#39;html.parser&#39;)

    cnt = int(driver.find_element(By.ID, &#39;totCnt&#39;).text)

    for i in range(1, cnt+1):

        station = driver.find_element(By.CSS_SELECTOR, f&#39;#body1 &gt; tr:nth-child({i}) &gt; td.rlist &gt; a&#39;)
        station.click()

        html = driver.page_source
        soup = BeautifulSoup(html, &#39;html.parser&#39;)

        data = soup.select(&#39;#os_dtail_info&#39;)[0]

        # brand
        brand = getID(data.select_one(&#39;#poll_div_nm&#39;).text)

        # name
        name = data.select_one(&#39;.header&#39;).text.strip()

        # address
        address = data.select_one(&#39;#rd_addr&#39;).text

        # gasoline
        gasoline = stringToInt(data.select_one(&#39;#b027_p&#39;).text)

        # diesel
        diesel = stringToInt(data.select_one(&#39;#d047_p&#39;).text)

        # self 
        slf = data.select_one(&#39;#SPAN_SELF_VLT_YN_ID&#39;)
        if type(slf.find(&#39;img&#39;)) == type(None):
            is_self = False
        else:
            is_self = True

        # car_wash
        car_wash = check(data, &#39;#cwsh_yn&#39;)

        # charging_station
        charging_station = check(data, &#39;#lpg_yn&#39;)

        # car_maintenance
        car_maintenance = check(data, &#39;#maint_yn&#39;)

        # convenience_store
        convenience_store = check(data, &#39;#cvs_yn&#39;)

        # 24_hours
        sel24 = check(data, &#39;#sel24_yn&#39;)

        tmp = gmaps.geocode(address, language=&#39;ko&#39;)
        # lat
        lat = tmp[0].get(&#39;geometry&#39;)[&#39;location&#39;][&#39;lat&#39;]

        # lng
        lng = tmp[0].get(&#39;geometry&#39;)[&#39;location&#39;][&#39;lng&#39;]

        cursor.execute(sql, (brand, name, gu, address, gasoline, diesel, 
                            is_self, car_wash, charging_station, car_maintenance, convenience_store, sel24, lat, lng))

        conn.commit()

cursor.execute(&quot;select count(*) from GAS_STATION&quot;)
result = cursor.fetchall()
print(result[0])

cursor.execute(&quot;select * from GAS_STATION limit 10&quot;)
result = cursor.fetchall()
for i in result:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/2f0a845c-7ac0-49b7-8dda-c25cf43d00bf/image.png" alt=""></p>
<h3 id="problem-5">Problem 5.</h3>
<p>For visualization, query using the following rules and save as a CSV file. (written in Python code)</p>
<ul>
<li><p>Full data is being imported, but the brand name should be displayed instead of the gas station brand ID. (Sort by gas station store ID)</p>
</li>
<li><p>It must be saved in the following format (note the brand name and column name, id: GAS_STORE.id)</p>
</li>
</ul>
<pre><code>import pandas as pd

sql = &quot;select s.id, b.name &#39;brand&#39;, s.name, s.city, s.gu, s.address, s.gasoline, s.diesel, s.self, &quot; +\
        &quot;s.car_wash, s.charging_station, s.car_maintenance, s.convenience_store, s.24_hours, &quot; +\
        &quot;s.lat, s.lng &quot; +\
        &quot;from GAS_BRAND b, GAS_STATION s &quot; +\
        &quot;where b.id = s.brand ORDER BY s.id&quot;

cursor.execute(sql)
result = cursor.fetchall()

columns = [i[0] for i in cursor.description]</code></pre><pre><code>df = pd.DataFrame(result)
df.columns = columns
df.head()

df.to_csv(&#39;./sql2_oil_station_data.csv&#39;, index=False, encoding=&#39;utf-8&#39;)

df = pd.read_csv(&#39;./sql2_oil_station_data.csv&#39;, index_col=0, thousands=&#39;,&#39;, encoding=&#39;utf-8&#39;)
df.head()</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/3bd422e2-6b54-421e-8926-25fd6b519ece/image.png" alt=""></p>
<h3 id="problem-6">Problem 6.</h3>
<p>Search for information on gas stations located within 1 kilometer from Miwang Building using latitude and longitude information.</p>
<ul>
<li>Gas station ID, gas station brand name, gas station store name, address, distance from Miwang Building (km)</li>
</ul>
<pre><code>lat, lng = getLL(&#39;서울 강남구 강남대로 364&#39;)
lat, lng</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0addcd17-f14b-45af-93ba-e03ec9eea65c/image.png" alt=""></p>
<pre><code>cursor.execute(&#39;set @location = point(127.02915553846, 37.495435686811)&#39;)

sql = &quot;select s.id, b.name &#39;brand&#39;, s.name, s.address, ST_Distance_Sphere(@location, point(lng, lat))/1000 &#39;distance&#39; &quot; +\
        &quot;from GAS_BRAND b, GAS_STATION s &quot; +\
        &quot;where s.brand = b.id &quot; +\
        &quot;having distance &lt;= 1 &quot; +\
        &quot;order by distance&quot;
cursor.execute(sql)
result = cursor.fetchall()

for i in result:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/213accf7-3a2f-4181-97d7-6ea48d7aa421/image.png" alt=""></p>
<h3 id="problem-7">Problem 7.</h3>
<p>Using latitude and longitude information, search for the 10 nearest gas stations that allow self-fueling at Miwang Building, are open 24 hours a day, and have a convenience store, sorted in order of lowest gasoline price.</p>
<ul>
<li>Gas station ID, gas station brand name, gas station store name, address, gasoline price, additional information (self-service, 24-hour, convenience store), distance from Miwang Building (km)</li>
</ul>
<pre><code>sql = &quot;select * &quot; +\
        &quot;from (select s.id, b.name &#39;brand&#39;, s.name, s.address, s.gasoline, s.self, s.24_hours, s.convenience_store, ST_Distance_Sphere(@location, point(lng, lat))/1000 &#39;distance&#39;&quot; +\
        &quot;from GAS_BRAND b, GAS_STATION s &quot; +\
        &quot;where s.brand = b.id and s.self=1 and s.24_hours=1 and s.convenience_store=1 &quot; +\
        &quot;order by distance limit 10) as tmp &quot; +\
        &quot;order by tmp.gasoline;&quot;
cursor.execute(sql)
result = cursor.fetchall()

for i in result:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/5b8e0989-92cb-40aa-8bfd-800deb51823f/image.png" alt=""></p>
<h3 id="problem-8">Problem 8.</h3>
<p>Search for the average price of gasoline by gas station brand and print it in descending order.</p>
<ul>
<li>District name, gas station brand name, average price of gasoline</li>
</ul>
<pre><code>sql = &quot;select s.gu, b.name, avg(s.gasoline) &quot; +\
        &quot;from GAS_STATION as s, GAS_BRAND as b &quot; +\
        &quot;where b.id = s.brand &quot; +\
        &quot;group by s.gu, b.name &quot; +\
        &quot;order by s.gu, avg(s.gasoline)&quot;

cursor.execute(sql)
result = cursor.fetchall()
for i in result:
    print(i)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/9cc67b3d-50ac-4ecf-9759-d5ce17d37e2a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tableau chart part 2]]></title>
            <link>https://velog.io/@zero-pepsi/26</link>
            <guid>https://velog.io/@zero-pepsi/26</guid>
            <pubDate>Sat, 31 Aug 2024 13:52:24 GMT</pubDate>
            <description><![CDATA[<p><strong>Using various functions</strong></p>
<h3 id="group">Group</h3>
<p>Two items</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a7af0ecf-45f4-4476-abe9-6162a1a307b8/image.png" alt=""></p>
<p>Three items</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/41d05981-bbf0-4c50-b9cd-a8ecbd36789d/image.png" alt=""></p>
<h3 id="set">Set</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/59e2d4fa-a31d-4d92-94dc-dd19a61dbbe9/image.png" alt=""></p>
<ul>
<li>No difference in &quot;group&quot; and &quot;set&quot; when using two items
Three or more items then use only &quot;group&quot; function**</li>
</ul>
<h3 id="combined-set">Combined Set</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/de203926-4f5f-497c-bfe2-e5ca3e4de8f5/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/cacb5a12-75a6-4e7e-b549-e0642a146f9f/image.png" alt=""></p>
<h3 id="hierarchy">Hierarchy</h3>
<p>All can be checked on one sheet -&gt; Efficient use of dashboard</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e72356d3-b5cd-4f01-8243-963ab6faedb1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e028cd11-44b3-422a-8626-77686e5dc5f3/image.png" alt=""></p>
<h3 id="map-chart">Map chart</h3>
<p><strong>Normal map chart</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/2ff9df54-967b-4c45-af26-41db025f53bb/image.png" alt=""></p>
<p><strong>Map chart with tooltip</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f10593db-a41b-4aed-b584-924328bb1e0d/image.png" alt=""></p>
<p><strong>Map chart with filters</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/4a3ad3a3-6395-4b3b-8b3b-d7238e314893/image.png" alt=""></p>
<h3 id="wordcloud">Wordcloud</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0c8dc763-f171-453c-a962-457be9d11695/image.png" alt=""></p>
<h3 id="calendar-heatmap">Calendar Heatmap</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/8be51c3b-a690-49ba-aeb1-0aeb51d16c21/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Simple data analysis (Excel)]]></title>
            <link>https://velog.io/@zero-pepsi/25</link>
            <guid>https://velog.io/@zero-pepsi/25</guid>
            <pubDate>Fri, 30 Aug 2024 14:15:22 GMT</pubDate>
            <description><![CDATA[<p><strong>Name of the file : Billionaires Statistics Dataset</strong></p>
<p><strong>Data source :</strong> <a href="https://www.kaggle.com/datasets/nelgiriyewithana/billionaires-statistics-dataset">kaggle</a></p>
<hr>
<h3 id="simple-data-analysis-practice-using-excel">Simple data analysis practice using Excel</h3>
<ol>
<li>Data Cleaning</li>
<li>Data Analysis</li>
<li>Data visualization</li>
</ol>
<p><strong>Check data</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/8f76ec7e-9364-49bd-bf98-58978e9f7272/image.png" alt=""></p>
<h3 id="1-data-cleaning">1. Data Cleaning</h3>
<p><strong>Find and remove duplicates</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/94a3fece-85c7-479e-8566-40252a89ca81/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f7f6f3c6-44f0-4aaf-93e9-86e96ae2a5ac/image.png" alt=""></p>
<p><strong>Check and change values (easy to see and understand)</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/8f344e39-e3ff-4931-a9a1-e5c27842f5c3/image.png" alt=""></p>
<p>M -&gt; Male  /  F -&gt; Female</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/66a0f727-b5b2-4a45-b701-c53f5197f574/image.png" alt=""></p>
<p><strong>Clean up unnecessary information or convert it into necessary information</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/bb6456c1-29a6-405f-9ea2-c44e5bfbd0d5/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/5bec83ef-c5b7-4543-8eab-90d589084d90/image.png" alt=""></p>
<p>Check and convert data type</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/fafcaeb7-3cad-4c88-bc52-016c8c921fad/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/ee938d55-9ef1-4ec9-a0aa-436dae9229fd/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a6181820-79d2-4c8a-898c-5367e28bcefd/image.png" alt=""></p>
<h3 id="2data-analysis">2.Data Analysis</h3>
<p><strong>Descrittive statistics</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/747356c4-4f42-4138-a142-19e18cec2f94/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/71040182-db3c-4049-817f-642e993d5131/image.png" alt=""></p>
<p><strong>Basic analysis with descrittive statistics</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/9625b1a1-62d8-4c3c-81e0-9e77a9d3a2b4/image.png" alt=""></p>
<p><strong>Advanced analysis with pivot tables</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/1a220ee6-02ca-4fbe-a5d5-78466e4e15db/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/57188638-3b36-454d-9a4c-9df21c91a45a/image.png" alt=""></p>
<p><strong>Find interesting or meaningful insights</strong></p>
<p>a. Find top 10 overall</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/8b63e97c-ab06-413a-a61d-ec7fad01a7ea/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0b8ec6a3-a157-4696-9a98-6a478e631783/image.png" alt=""></p>
<p>Sort by largest to smallest</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b8b077cf-ada1-4a5a-904b-b43b5f19fb62/image.png" alt=""></p>
<p><strong>b. billionaires by age</strong></p>
<p>change the value to count</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/871f0175-1f68-4514-8592-f9c45b39fea4/image.png" alt=""></p>
<p>group function</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/927f4b63-5de3-45fb-be2b-7fdaae9ae8ad/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/fd5ba7de-9035-4357-b43a-b03aa1445354/image.png" alt=""></p>
<p>checking detail</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/5138d453-9110-4edd-b3dd-5a79fd0ffbff/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/824f1dff-9be7-4695-bb75-e2ac756d7d3d/image.png" alt=""></p>
<h3 id="3-data-visualization">3. Data visualization</h3>
<p>Make it more dynamic (sory by each industry,gender etc...)</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/2afc6798-be27-424d-a1d8-781e3be58da3/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/887d1bab-a1a8-415f-9967-9bd87f9ee16d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b60758e6-8070-4b4b-8087-960df6cc4012/image.png" alt=""></p>
<p>Connect this to age table as well</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f02bab76-c26f-4099-ad3d-db849d602aea/image.png" alt=""></p>
<p>Graphs for visual impact</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6041cd2f-dae1-4999-8f2e-a686a50499a6/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/c095ac50-4ffd-47ff-8244-0a3e0e0cdd6a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f47614c5-812f-43be-bfec-42e077c864b0/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/bd81834d-bff9-4b9d-ba63-072214fc4c5a/image.png" alt=""></p>
<p>Make it like a dashboard</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a011251d-9de3-4139-8908-5f74780fa1b7/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - Binary Tree Nodes]]></title>
            <link>https://velog.io/@zero-pepsi/24</link>
            <guid>https://velog.io/@zero-pepsi/24</guid>
            <pubDate>Fri, 30 Aug 2024 14:15:09 GMT</pubDate>
            <description><![CDATA[<p>You are given a table, BST, containing two columns: N and P, where N represents the value of a node in Binary Tree, and P is the parent of N.</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/2d2a0231-2665-449b-bc18-c8ff6f2c645f/image.png" alt=""></p>
<p>Write a query to find the node type of Binary Tree ordered by the value of the node. Output one of the following for each node:</p>
<ul>
<li>Root: If node is root node.</li>
<li>Leaf: If node is leaf node.</li>
<li>Inner: If node is neither root nor leaf node.</li>
</ul>
<p><strong>Sample Input</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/878d4ffe-1fb8-46f2-b2be-3658154871a0/image.png" alt=""></p>
<p><strong>Sample Output</strong></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/56a36b6b-1fab-4f53-aedc-7364b0927649/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0c0c4f7b-f842-4af7-b850-86a36267d895/image.png" alt=""></p>
<hr>
<p>Answer : </p>
<pre><code>SELECT CASE
    WHEN P IS NULL THEN CONCAT(N, &#39; Root&#39;)
    WHEN N IN (SELECT DISTINCT P FROM BST) THEN CONCAT(N, &#39; Inner&#39;)
    ELSE CONCAT(N, &#39; Leaf&#39;)
    END
FROM BST
ORDER BY N ASC</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e763bb88-92ab-48da-8f21-41316609ee9c/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - 재구매가 일어난 상품과 회원]]></title>
            <link>https://velog.io/@zero-pepsi/23</link>
            <guid>https://velog.io/@zero-pepsi/23</guid>
            <pubDate>Fri, 30 Aug 2024 14:15:03 GMT</pubDate>
            <description><![CDATA[<p><strong>문제 설명</strong>
다음은 어느 의류 쇼핑몰의 온라인 상품 판매 정보를 담은 ONLINE_SALE 테이블 입니다. ONLINE_SALE 테이블은 아래와 같은 구조로 되어있으며 ONLINE_SALE_ID, USER_ID, PRODUCT_ID, SALES_AMOUNT, SALES_DATE는 각각 온라인 상품 판매 ID, 회원 ID, 상품 ID, 판매량, 판매일을 나타냅니다.</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/d1da2a74-9f06-4b86-bc9c-6c643447b30d/image.png" alt=""></p>
<p>동일한 날짜, 회원 ID, 상품 ID 조합에 대해서는 하나의 판매 데이터만 존재합니다.</p>
<p><strong>문제</strong>
ONLINE_SALE 테이블에서 동일한 회원이 동일한 상품을 재구매한 데이터를 구하여, 재구매한 회원 ID와 재구매한 상품 ID를 출력하는 SQL문을 작성해주세요. 결과는 회원 ID를 기준으로 오름차순 정렬해주시고 회원 ID가 같다면 상품 ID를 기준으로 내림차순 정렬해주세요.</p>
<hr>
<p>Answer : </p>
<pre><code>SELECT USER_ID,PRODUCT_ID
FROM ONLINE_SALE
GROUP BY USER_ID,PRODUCT_ID
HAVING COUNT(PRODUCT_ID) &gt; 1
ORDER BY USER_ID, PRODUCT_ID DESC</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/1a43eac2-fafc-42ec-99a9-1c82e6c1874f/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - Placements]]></title>
            <link>https://velog.io/@zero-pepsi/22</link>
            <guid>https://velog.io/@zero-pepsi/22</guid>
            <pubDate>Fri, 30 Aug 2024 14:14:57 GMT</pubDate>
            <description><![CDATA[<p>You are given three tables: Students, Friends and Packages. Students contains two columns: ID and Name. Friends contains two columns: ID and Friend_ID (ID of the ONLY best friend). Packages contains two columns: ID and Salary (offered salary in $ thousands per month).</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/7ff635be-357a-4bac-aa5d-76ee114d157b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/cb9743e2-9682-4392-b82d-aa0323d685de/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/c08d7698-dc2c-467d-922c-b51edbc0b24c/image.png" alt=""></p>
<p>Write a query to output the names of those students whose best friends got offered a higher salary than them. Names must be ordered by the salary amount offered to the best friends. It is guaranteed that no two students got same salary offer.</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a2d8c65a-f0ab-4cde-aeaa-fa897cfe8a2e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/5ea59b33-9f1b-4096-9792-dc081810085b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a98324b8-92fc-4513-9d67-626f4a507cee/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/6d2ab220-fb85-4352-ba73-fd320f2029af/image.png" alt=""></p>
<p>Now,</p>
<ul>
<li>Samantha&#39;s best friend got offered a higher salary than her at 11.55</li>
<li>Julia&#39;s best friend got offered a higher salary than her at 12.12</li>
<li>Scarlet&#39;s best friend got offered a higher salary than her at 15.2</li>
<li>Ashley&#39;s best friend did NOT get offered a higher salary than her</li>
</ul>
<p>The name output, when ordered by the salary offered to their friends, will be:</p>
<ul>
<li>Samantha</li>
<li>Julia</li>
<li>Scarlet</li>
</ul>
<hr>
<p>Answer : </p>
<pre><code>Select S.Name
From ( Students S join Friends F Using(ID)
       join Packages P1 on S.ID=P1.ID
       join Packages P2 on F.Friend_ID=P2.ID)
Where P2.Salary &gt; P1.Salary
Order By P2.Salary;</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f3140175-7155-46ac-8ba5-1b3385d65ac7/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[National museum/art gallery data analysis]]></title>
            <link>https://velog.io/@zero-pepsi/10</link>
            <guid>https://velog.io/@zero-pepsi/10</guid>
            <pubDate>Thu, 29 Aug 2024 13:08:34 GMT</pubDate>
            <description><![CDATA[<h3 id="data-preparation-steps">Data preparation steps</h3>
<p>Target Data (Json): National Museum and Art Gallery Information Standard Data
Source: <a href="https://www.data.go.kr/data/15017323/standard.do">Public Data Portal</a>
DownLoad: <a href="https://www.data.go.kr/download/15017323/standard.do?dataType=json">National Museum and Art Gallery Information Standard Data.json</a></p>
<hr>
<p><strong>Call required module</strong></p>
<pre><code>import json

with open(&#39;../data/전국박물관미술관정보표준데이터.json&#39;, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f:
    json_data = json.load(f)
</code></pre><h3 id="step-1-create-dataframe-with-json-data">Step 1: Create DataFrame with Json Data</h3>
<p><strong>1-1 Creating a Pandas DataFrame with Json Data</strong></p>
<pre><code>df_target = pd.json_normalize(json_data, record_path=&quot;records&quot;)
df_target.head(2)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/0eef6d7d-9b4c-48d4-a79c-e08d15918c49/image.png" alt=""></p>
<h3 id="step-2-preprocessing-dataframe-01">Step 2: Preprocessing DataFrame 01</h3>
<p><strong>2-1) Basic preprocessing</strong></p>
<p>The null value of the corresponding json_data is composed of &quot;&quot;, so if you check the null value using df_target.info() or df_target.isna(), etc., it will say that there is no null value. Therefore, in order to properly check this data, insert a Null value instead of &quot;&quot;.</p>
<ul>
<li><p>Condition 1: (&quot;&quot;or &#39;&#39;) consists only of double quotation marks (or single quotation marks) without spaces.</p>
</li>
<li><p>Condition 2: Change &quot;&quot;(or &#39;&#39;) to a null value (None).</p>
</li>
<li><p>Condition 3: Do not change the index or order.</p>
</li>
<li><p>Condition 4: Assign the result DataFrame to the &#39;df_target&#39; variable.</p>
</li>
</ul>
<pre><code>df_target.replace(&quot;&quot;, None, inplace=True)

df_target.isnull().sum()</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b0716dc3-b83e-4791-9f72-7b35343d99f8/image.png" alt=""></p>
<p><strong>2-2 Basic preprocessing 02</strong></p>
<p>When creating json data as Pandas DataFrame, numeric data was recognized as string.</p>
<ul>
<li><p>Condition 1: Change the Column Data of type_int_col below to integer (int) type Data.</p>
</li>
<li><p>Condition 2: Change the Column Data of type_float_col below to float type Data.</p>
</li>
<li><p>Condition 3: If there is a null value in the Data to be changed, fill it with 0.</p>
</li>
<li><p>Condition 4: Do not change the index or order.</p>
</li>
<li><p>Condition 5: Assign the result DataFrame to the &#39;df_target&#39; variable.</p>
</li>
</ul>
<pre><code>type_int_col = [&#39;어른관람료&#39;, &#39;청소년관람료&#39;, &#39;어린이관람료&#39;]
type_float_col = [&#39;위도&#39;, &#39;경도&#39;]

# con 1, 2

df_target[type_int_col] = df_target[type_int_col].astype(&#39;int&#39;)
df_target[type_float_col] = df_target[type_float_col].astype(&#39;float&#39;)

# con 3

df_target[&#39;경도&#39;] = df_target[&#39;경도&#39;].fillna(0)
df_target.head(2)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/825245f6-06ad-43c2-93d7-4650082e02fb/image.png" alt=""></p>
<p><strong>2-3 Basic Preprocessing 03</strong></p>
<p>Improve the readability of the data by deleting the data of the column that is not related to the analysis.</p>
<ul>
<li><p>Condition 1: Delete the column data of drop_col below.</p>
</li>
<li><p>Condition 2: Do not change the index or order.</p>
</li>
<li><p>Condition 3: Assign the result DataFrame to the &#39;df_target&#39; variable.</p>
</li>
</ul>
<pre><code>drop_cols = [&#39;소재지지번주소&#39;, &#39;위도&#39;, &#39;경도&#39;, &#39;운영기관전화번호&#39;,&#39;운영기관명&#39;, &#39;운영홈페이지&#39;, &#39;편의시설정보&#39;, &#39;휴관정보&#39;, 
            &#39;관람료기타정보&#39;, &#39;박물관미술관소개&#39;, &#39;교통안내정보&#39;, &#39;관리기관전화번호&#39;, &#39;관리기관명&#39;, &#39;제공기관코드&#39;, &#39;제공기관명&#39;]

df_target.drop(drop_cols, axis=1, inplace=True)
df_target.head(2)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f23f5c3f-45ad-4bbf-b355-26065e7f8f06/image.png" alt=""></p>
<p><strong>2-4 Basic preprocessing 04</strong></p>
<p>If the admission fee for adults, teenagers, and children is strange, delete the row data itself.</p>
<ul>
<li><p>Condition 1: The column related to the admission fee is type_int_col defined above.</p>
</li>
<li><p>Condition 2: If the admission fee is not divisible by 10 won, it is judged as an outlier. Delete the row.</p>
</li>
<li><p>Condition 3: If the admission fee is 100,000 won or more, it is judged as an outlier. Delete the row.</p>
</li>
<li><p>Condition 4: Do not change the index or order.</p>
</li>
<li><p>Condition 5: Assign the result DataFrame to the &#39;df_target&#39; variable.</p>
</li>
</ul>
<pre><code>for col in type_int_col:
    df_target.drop(df_target[(df_target[col] % 10 != 0) |
                             (df_target[col] &gt;= 100000)].index, inplace=True)

df_target.head(2)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f8057756-69f4-4c72-aa21-d77b923154ea/image.png" alt=""></p>
<h3 id="step-3-dataframe-preprocessing-02">Step 3: DataFrame Preprocessing 02</h3>
<p><strong>3-1 Advanced preprocessing 01</strong></p>
<p>delete data of museums/art galleries that are closed or duplicated.
In addition to the conditions below, there are duplicate data, but this test proceeds by deleting only the duplicate data that meets the conditions below.</p>
<ul>
<li><p>Condition 1: If the Facility Name Column data contains the word &#39;Closed&#39;, the corresponding row is deleted.</p>
</li>
<li><p>Condition 2: If the Facility Name Column data is duplicated, the data with the latest &#39;Data Reference Date&#39; of the corresponding row is left and the row that is not the latest is deleted.</p>
</li>
<li><p>Condition 3: Whether the Facility Name Column data is duplicated is determined as a duplicate museum/art gallery if the value of the Facility Name Column data with the spaces removed matches.</p>
</li>
<li><p>Condition 4: Do not change the Index or order. - If you changed the order to solve the problem, sort it again in the Index order.</p>
</li>
<li><p>Condition 5: Assign the result DataFrame to the &#39;df_target&#39; variable.</p>
</li>
</ul>
<pre><code>df_target.drop(df_target[df_target[&#39;시설명&#39;].str.contains(&#39;휴관&#39;)].index, inplace=True)

df_target.sort_values(by=&#39;데이터기준일자&#39;, ascending=False, inplace=True)
df_target = df_target[~df_target.duplicated([&#39;시설명&#39;])]

df_target = df_target[~df_target[&#39;시설명&#39;].str.replace(&#39; &#39;, &#39;&#39;).duplicated()]

df_target = df_target.sort_index()</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/92b8d033-de8c-467f-b7b6-7798ae06cb0d/image.png" alt=""></p>
<p><strong>3-2 Advanced preprocessing 02</strong></p>
<p>find out the &#39;opening hours&#39; that tell me how many hours a museum/art gallery is open during the day on weekdays and public holidays.</p>
<ul>
<li><p>Condition 1: The opening hours on weekdays are from &#39;Weekday opening time&#39; to &#39;Weekday opening time&#39;. Create a &#39;Weekday opening hours&#39; column and enter the opening hours on weekdays.</p>
</li>
<li><p>Condition 2: The opening hours on public holidays are from &#39;Holiday opening time&#39; to &#39;Holiday closing time&#39;. Create a &#39;Holiday opening hours&#39; column and enter the opening hours on public holidays.</p>
</li>
<li><p>Condition 3: &#39;Weekday opening hours&#39; and &#39;Holiday opening hours&#39; are expressed as floats in hours.</p>
</li>
<li><p>Condition 4: Do not change the index or order.</p>
</li>
<li><p>Condition 5: Assign the result DataFrame to the &#39;df_target&#39; variable.</p>
</li>
</ul>
<pre><code>time_cols = [&#39;평일관람시작시각&#39;, &#39;평일관람종료시각&#39;, &#39;공휴일관람시작시각&#39;, &#39;공휴일관람종료시각&#39;]
for idx, row in df_target[time_cols].iterrows():
    open_hour, open_min = map(int, row.평일관람시작시각.split(&#39;:&#39;))
    close_hour, close_min = map(int, row.평일관람종료시각.split(&#39;:&#39;))
    total = (close_hour - open_hour) + round((close_min - open_min) / 60, 2)
    df_target.loc[idx, &#39;평일관람가능시간&#39;] = 24 if total &gt; 23 else total

    open_hour, open_min = map(int, row.공휴일관람시작시각.split(&#39;:&#39;))
    close_hour, close_min = map(int, row.공휴일관람종료시각.split(&#39;:&#39;))
    total = (close_hour - open_hour) + round((close_min - open_min) / 60, 2)
    df_target.loc[idx, &#39;공휴일관람가능시간&#39;] = 24 if total &gt; 23 else total</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/317c88b3-48a1-4d30-97ec-a6a08152475b/image.png" alt=""></p>
<p><strong>3-3 Advanced preprocessing 03</strong></p>
<p>process the data of the &#39;Local Road Name Address&#39; Column and divide it into Metropolitan Autonomy-Basic Autonomy (Administrative City)-Detailed Address.</p>
<ul>
<li><p>Condition 1: The first word of the &#39;Local Road Name Address&#39; Column data always means the name of the metropolitan autonomous government. Create a &#39;Metropolitan&#39; Column and enter the name of the metropolitan autonomous government for the corresponding row data.
&#39;Sejong Special City&#39; has now been renamed to &#39;Sejong Special Self-Governing City&#39;. Please reflect this.</p>
</li>
<li><p>Condition 2: The second word of the &#39;Local Road Name Address&#39; Column data mostly means the name of the basic autonomous government. Create a &#39;Basic&#39; Column and enter the name of the basic autonomous government for the corresponding row data. - In the case of &#39;Jeju Special Self-Governing Province&#39;, there is no basic autonomous body, but the administrative city (&#39;Jeju-si&#39;, &#39;Seogwipo-si&#39;) is located in the second word of the &#39;Location Road Name Address&#39; Column data. Enter the administrative city in the &#39;Basic&#39; Column. - In the case of &#39;Sejong Special Self-Governing City&#39;, there is no basic autonomous body. In the case of &#39;Sejong Special Self-Governing City&#39;, enter a null value (None) in the &#39;Basic&#39; Column data.</p>
</li>
<li><p>Condition 3: In the &#39;Location Road Name Address&#39; Column data, create a &#39;Detailed&#39; Column and enter data that is not included in the metropolitan/basic autonomous body (including administrative city).</p>
</li>
<li><p>Condition 4: The data in the &#39;Location Road Name Address&#39;, &#39;Metropolitan&#39;, &#39;Basic&#39;, and &#39;Detailed Column (Row) must not have spaces before and after the data.</p>
</li>
<li><p>Condition 5: Do not change the index or order.</p>
</li>
<li><p>Condition 6: Assign the resulting DataFrame to the &#39;df_target&#39; variable.</p>
</li>
</ul>
<pre><code>for idx, value in df_target[&#39;소재지도로명주소&#39;].items():
    if &#39;세종특별&#39; in value:
        wide = &#39;세종특별자치시&#39;
        basic = None
        detail = tuple(value.split(&#39; &#39;, 1))[1]
    else:
        wide, basic, detail = tuple(value.split(&#39; &#39;, 2))

    df_target.loc[idx, &#39;광역&#39;] = wide
    df_target.loc[idx, &#39;기초&#39;] = basic
    df_target.loc[idx, &#39;상세&#39;] = detail</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/58ccfc9e-0d1b-45b2-a843-2761a96a3f07/image.png" alt=""></p>
<h3 id="step-4-get-the-information">Step 4: Get the information</h3>
<p><strong>4-1 Get the information 01</strong></p>
<p>Check the total number of museums/art galleries by metropolitan government.</p>
<ul>
<li><p>Condition 1: Please display the total number of museums/art galleries by metropolitan government using the metropolitan government data in the &#39;metropolitan&#39; Column of df_target.</p>
</li>
<li><p>Condition 2: The index of the result DataFrame is the metropolitan government. The priority of the metropolitan government is provided by the value of the province_dict below. Please list the order of the index according to the priority of the metropolitan government.
Source: Ministry of the Interior and Safety</p>
</li>
<li><p>Condition 3: The name of the Column that displays the total number of museums/art galleries in the result DataFrame is &#39;Number of Museums/Art Galleries&#39;.</p>
</li>
<li><p>Condition 4: Assign the result DataFrame to the &#39;df_result&#39; variable.</p>
</li>
</ul>
<pre><code>province_dict = {
    &#39;서울특별시&#39;: 0,
    &#39;부산광역시&#39;: 1,
    &#39;대구광역시&#39;: 2,
    &#39;인천광역시&#39;: 3,
    &#39;광주광역시&#39;: 4,
    &#39;대전광역시&#39;: 5,
    &#39;울산광역시&#39;: 6,
    &#39;세종특별자치시&#39;: 7,
    &#39;경기도&#39;: 8,
    &#39;강원도&#39;: 9,
    &#39;충청북도&#39;: 10,
    &#39;충청남도&#39;: 11,
    &#39;전라북도&#39;: 12,
    &#39;전라남도&#39;: 13,
    &#39;경상북도&#39;: 14,
    &#39;경상남도&#39;: 15,
    &#39;제주특별자치도&#39;: 16
}

df_result = df_target.groupby(&#39;광역&#39;).size().to_frame(name=&#39;박물관미술관수&#39;)
df_result = df_result.sort_index(key=lambda x: x.map(province_dict))

display(df_result)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/2eb84a90-21e2-487a-8070-45aa7aceee3f/image.png" alt=""></p>
<p><strong>4-2 Get the information 02</strong></p>
<p>check the metropolitan-basic autonomous governments (administrative cities) where the total number of museums/art galleries is 8.</p>
<ul>
<li><p>Condition 1: Using the metropolitan autonomous government/basic autonomous government (administrative city) data in the &#39;metropolitan&#39; and &#39;basic&#39; columns of df_target, find the places where the total number of museums/art galleries is 8 by metropolitan autonomous government-basic autonomous government (administrative city).</p>
</li>
<li><p>Condition 2: Enter the metropolitan autonomous government in the &#39;metropolitan&#39; column of the result DataFrame and the basic autonomous government (administrative city) in the &#39;basic&#39; column.</p>
</li>
<li><p>Condition 3: List the &#39;metropolitan&#39; column in order of metropolitan autonomous government priority, as in problem 4-1. Refer to province_dict in 4-1</p>
</li>
<li><p>Condition 4: If there is the same metropolitan autonomous body, list the data of the &#39;Basic&#39; Column in reverse alphabetical order.</p>
</li>
<li><p>Condition 5: The name of the Column that indicates the total number of museums/art galleries in the result DataFrame is &#39;Number of Museums/Art Galleries&#39;.</p>
</li>
<li><p>Condition 6: Set the Index in ascending order of numbers (integers).</p>
</li>
<li><p>Condition 7: Assign the result DataFrame to the &#39;df_result&#39; variable.</p>
</li>
</ul>
<pre><code>df_result = df_target.groupby([&#39;광역&#39;, &#39;기초&#39;], dropna=False).size().to_frame(name=&#39;박물관미술관수&#39;)

df_result = df_result[df_result[&#39;박물관미술관수&#39;] == 8]

df_result = df_result.sort_index(level=1, ascending=False).sort_index(level=0, key=lambda x: x.map(province_dict), sort_remaining=False)

df_result = df_result.reset_index()
df_result.head(5)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/f2a07266-2d52-479b-8394-b67bb8e21a99/image.png" alt=""></p>
<p>4-3 Getting the information 03</p>
<p>find out the average admission fee difference between metropolitan governments and museum art gallery categories (private, national, public, university).</p>
<ul>
<li><p>Condition 1: Using the metropolitan government/museum art gallery category data in the &#39;metropolitan&#39; and &#39;museum art gallery category&#39; columns of df_target, find the largest and smallest differences between the average adult admission fee and the average child admission fee by metropolitan government-museum art gallery category.
However, if either the adult admission fee or the child admission fee is 0 won (free), please exclude museums/art galleries from the average calculation.</p>
</li>
<li><p>Condition 2: Enter the metropolitan government in the &#39;metropolitan&#39; Index of the result DataFrame, and the museum art gallery category in the &#39;museum art gallery category&#39; Index.</p>
</li>
<li><p>Condition 3: List the &#39;metropolitan&#39; Index in order of metropolitan government priority, as in problem 4-1. - Refer to province_dict in 4-1</p>
</li>
<li><p>Condition 4: The &#39;Adult Admission Fee&#39; Column of the result DataFrame is the average adult admission fee by metropolitan government-museum/art gallery division, the &#39;Children&#39;s Admission Fee&#39; Column is the average children&#39;s admission fee by metropolitan government-museum/art gallery division, and the &#39;Admission Fee Difference&#39; Column is the average adult admission fee by metropolitan government-museum/art gallery division - average children&#39;s admission fee (difference). - For the adult/child admission fee and admission fee difference, enter an integer value rounded to the first decimal place from the average value. - Example: 2,978.5 won -&gt; 2,980.0 won (rounded to the first decimal place) -&gt; 2,980 won (integer value)</p>
</li>
<li><p>Condition 5: Assign the result DataFrame to the &#39;df_result&#39; variable.</p>
</li>
</ul>
<pre><code>df_result = df_target[~((df_target[&#39;어른관람료&#39;] == 0) | (df_target[&#39;어린이관람료&#39;] == 0))]

df_result = df_result.pivot_table(index=[&#39;광역&#39;, &#39;박물관미술관구분&#39;],
                      values=[&#39;어른관람료&#39;, &#39;어린이관람료&#39;],
                      aggfunc=&#39;mean&#39;)

df_result = df_result.apply(lambda x: round(x, -1))

df_result[&#39;어른관람료&#39;] = df_result[&#39;어른관람료&#39;].astype(int)
df_result[&#39;어린이관람료&#39;] = df_result[&#39;어린이관람료&#39;].astype(int)

df_result[&#39;관람료차이&#39;] = df_result[&#39;어른관람료&#39;] - df_result[&#39;어린이관람료&#39;]

df_result = df_result[(df_result[&#39;관람료차이&#39;] == df_result[&#39;관람료차이&#39;].min()) |
                      (df_result[&#39;관람료차이&#39;] == df_result[&#39;관람료차이&#39;].max())]

df_result.head(2)</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b18b5284-7a11-4a9b-a900-74847f2fdf8b/image.png" alt=""></p>
<p><strong>4-4 Get the information 04</strong></p>
<p>A family (2 adults, 1 teenager, 1 child) wants to visit an art gallery in Jeju-si, Jeju Special Self-Governing Province on a public holiday. 
Please show a list of art galleries with a total admission fee of 20,000 won or less and a viewing period of 4 hours or more on a public holiday.</p>
<ul>
<li><p>Condition 1: The total admission fee for a family (2 adults, 1 teenager, 1 child) must be 20,000 won or less.</p>
</li>
<li><p>Condition 2: We want to go to an art gallery in Jeju-si, Jeju Special Self-Governing Province.
Art Gallery: In this test, we define &#39;Art Gallery&#39; as the data in the facility name column of df_target that contains the letters &lt;&#39;Art Gallery&#39; or &#39;Gallery&#39; or &#39;Art&#39;&gt;.</p>
</li>
<li><p>Condition 3: We want to go on a public holiday. It must be an art gallery that can be viewed for 4 hours or more on a public holiday.</p>
</li>
<li><p>Condition 4: The Frame of the Art Gallery List is the same as df_target.</p>
</li>
<li><p>Condition 5: Assign the result DataFrame to the &#39;df_result&#39; variable.</p>
</li>
</ul>
<pre><code>money = (df_target[&#39;어른관람료&#39;] * 2 + df_target[&#39;청소년관람료&#39;] + df_target[&#39;어린이관람료&#39;]) &lt;= 20000
location = df_target[&#39;기초&#39;] == &#39;제주시&#39;
gallery = df_target[&#39;시설명&#39;].str.contains(&#39;미술관|갤러리|아트&#39;)
holiday = df_target[&#39;공휴일관람가능시간&#39;] &gt;= 4

df_result = df_target[money &amp; location &amp; gallery &amp; holiday]</code></pre><p><img src="https://velog.velcdn.com/images/zero-pepsi/post/d56abbc4-46db-4a2b-919b-7641958994f0/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tableau chart]]></title>
            <link>https://velog.io/@zero-pepsi/9</link>
            <guid>https://velog.io/@zero-pepsi/9</guid>
            <pubDate>Thu, 29 Aug 2024 13:08:27 GMT</pubDate>
            <description><![CDATA[<h3 id="table-chart">Table chart</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/ce0cc068-9fcf-468a-a52d-b323318fd4d2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/43df8d26-2046-4ace-b8fe-4b568cf16ee9/image.png" alt=""></p>
<h3 id="bar-chart-frequently-used">Bar chart (Frequently used)</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/e5677a7b-295f-4fc0-a261-3256818b4cac/image.png" alt=""></p>
<h3 id="line-chart">Line chart</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/4e4dafb5-e772-4875-a352-266b46212e13/image.png" alt=""></p>
<h3 id="pie-chart">Pie chart</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/b086dee2-9bfc-49d8-bad8-7af7a4ef60f4/image.png" alt=""></p>
<h3 id="treemaps">Treemaps</h3>
<p> <img src="https://velog.velcdn.com/images/zero-pepsi/post/d4359826-d8c9-4a34-a7d2-77246bdbc3df/image.png" alt=""></p>
<h3 id="stacked-bar-chart">Stacked Bar chart</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/56c83a3e-e51a-421b-a0ce-a376b0040d5a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/a3da521c-7d9c-4962-bbb6-4404e7668b1b/image.png" alt=""></p>
<h3 id="dashboard">Dashboard</h3>
<p>Important considerations when creating a dashboard</p>
<p><strong>Purpose</strong></p>
<ul>
<li>Who will use it</li>
<li>What information do you want to convey</li>
</ul>
<p><strong>Display environment</strong></p>
<ul>
<li>Tablet? Phone? PC? or even hard copy</li>
</ul>
<p><strong>Layout arrangement</strong></p>
<ul>
<li>Key content is located in the upper left</li>
</ul>
<h4 id="dashboard-01">Dashboard 01</h4>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/8dbfb7c1-d8ea-4e6d-81be-6f87feeb6b80/image.png" alt=""></p>
<h3 id="scatter-chart">Scatter chart</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/9b6da59f-23fc-4b39-b7da-eeb345eb4488/image.png" alt=""></p>
<h3 id="combination-chart">Combination chart</h3>
<p><strong>1.    Bar + Line with dual axes</strong> (Frequently used)</p>
<p> <img src="https://velog.velcdn.com/images/zero-pepsi/post/4d001841-425d-4b4a-acb4-efcf03bbed14/image.png" alt=""></p>
<p><strong>2.    Line char with dual axes</strong> - 트랜드와 함께 매출 강조
 <img src="https://velog.velcdn.com/images/zero-pepsi/post/6bd4b5db-661f-4054-aa5e-85b54c994a9d/image.png" alt=""></p>
<p><strong>3.    Line + Area chart with dual axes</strong></p>
<p> <img src="https://velog.velcdn.com/images/zero-pepsi/post/22c41758-a3cb-4f31-9820-c451bc845f4e/image.png" alt=""></p>
<h3 id="donut-chart-frequently-used">Donut chart (Frequently used)</h3>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/45b8c199-c4da-4103-9dc5-8d8dd5c3d774/image.png" alt=""></p>
<h4 id="dashboard-2">Dashboard 2</h4>
<p>Action filter added</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/437a0910-146a-4841-89e2-9ee019604453/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/684fb43e-2461-49e4-963a-a838789b9df2/image.png" alt=""></p>
<p>Action Highlight added</p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/daee25cd-5d03-4925-8786-e9cee03c8333/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/3ed2d322-dd90-4d34-b16b-71e1afcb4a5d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/zero-pepsi/post/9b7a5bf0-5a9e-4c35-b444-73737c938fce/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>