<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jj_study.log</title>
        <link>https://velog.io/</link>
        <description>Data Science 스터디로그</description>
        <lastBuildDate>Tue, 19 Mar 2024 11:35:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jj_study.log</title>
            <url>https://velog.velcdn.com/images/jj_study/profile/ea26f947-9396-44ae-ada8-ce008368a31e/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jj_study.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jj_study" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[SQL - Python with MySQL]]></title>
            <link>https://velog.io/@jj_study/SQL-Python-with-MySQL</link>
            <guid>https://velog.io/@jj_study/SQL-Python-with-MySQL</guid>
            <pubDate>Tue, 19 Mar 2024 11:35:41 GMT</pubDate>
            <description><![CDATA[<h3 id="1-mysql-연결">1. MySQL 연결</h3>
<ul>
<li><p>VSCode에서 jupyter Notebook 실행 ds_study 환경 작업</p>
</li>
<li><p>Jupyter Notebook MySQL은 모두 sql_ws 같은 폴더에서 작업</p>
</li>
<li><p>AWS RDS가 생성한 databae-1이 접속 상태인지 확인</p>
</li>
<li><p>ds_study 환경으로 새로운 Jupyter Notebook 파일 생성</p>
</li>
<li><p>Python에서 MySQL 사용을 위한 MySQL Driver 설치</p>
</li>
</ul>
<p>(1) MySQL 접속</p>
<ul>
<li><p>MySQL 접속위한 connect 생성</p>
<ul>
<li>pip install mysql-connector-python  #cmd 창
주의!!!  연결 후는 반드시 연결 해제할 것
(예제)<ul>
<li>LOCAL DB 연결 시 및 연결해제<pre><code>mydb = mysql.connector.connect(
   host = &quot;localhost&quot;,
   user = &quot;root&quot;,
   password = &quot;******&quot;,
   database = &quot;databae_name&quot;
)
mydb.close()</code></pre></li>
<li>AWS RDS (database-1) 연결 시 및 연결해제<pre><code>mydb = mysql.connector.connect(
   host = &quot;database-1.*********.rds.amazonaws.com&quot;,             #RDS 엔드포인트
   port = 3306,
   user = &quot;admin&quot;,
   password = &quot;********&quot;
   database = &quot;database_name&quot;
)
mydb.close()</code></pre>(2) Query 실행</li>
</ul>
</li>
</ul>
</li>
<li><p>SQL 쿼리 실행하기 위한 cursor 객체 생성<br>  AWS RDS로 연결시</p>
<pre><code>      mydb = mysql.connector.connect(
         host = &quot;database-1.*********.rds.amazonaws.com&quot;,             #RDS 엔드포인트
         port = 3306,
         user = &quot;admin&quot;,
         password = &quot;********&quot;
         database = &quot;database_name&quot;
      )
      mycursor = mydb.cursor()
      mycursor.execute(&quot;query_statement&quot;)
      mydb.close()</code></pre><p>  (예제)
  (1) TABLE 생성</p>
<pre><code>  ```
   remote = mysql.connector.connect(
      host = &quot;database-1.us-east-2.rds.amazonaws.com&quot;,
      port = 3306,
      user = &quot;admin&quot;,
      password = &quot;***********&quot;,
      database = &quot;zerobase&quot;
  )

  cur = remote.cursor()
  cur.execute(&quot;CREATE TABLE sql_file (id int, filename varchar(16))&quot;)
  ```</code></pre><ul>
<li><p>TABLE 확인</p>
<pre><code>  ```</code></pre><p>desc sql_file;    </p>
<pre><code>  ```</code></pre><p>(2) TABLE 삭제</p>
<pre><code>  cur = remote.cursor()
  cur.execute(&quot;DROP TABLE sql_file&quot;)

  remote.close()</code></pre></li>
</ul>
</li>
</ul>
<hr>
<p>(2) SQL파일 실행</p>
<ul>
<li><p>SQL파일 실행을 위한 코드</p>
<pre><code>  import mysql.connector

  mydb = mysql.connector.connect(
          host = &quot;host_name&quot;,
          port = port_number,
          user = &quot;user_name&quot;,
          password = &quot;password&quot;,
          database = &quot;database_name&quot;
  )
  mycursor = mydb.cursor()

  sql = open(&quot;file_name.sql&quot;).read()

  ### * One Query
      mycursor.execute(sql)

  ### * Multi Query : Query가 여러개 존재하는 경우
  mycursor.execute(sql, multi=True)

  mydb.close()</code></pre><hr>
<h4 id="--one-query">- ONE QUERY</h4>
<p>(예제1) test03.sql 파일 생성 (CREATE TABLE sql_file( id int, filename varchar(16)); 후 실행</p>
<pre><code></code></pre><pre><code>  remote = mysql.connector.connect(
           host = &quot;database-1.***.amazonaws.com&quot;,
           port = 3306,
           user = &quot;admin&quot;,
           password = &quot;***********&quot;,
           database = &quot;zerobase&quot;
  )
  cur = remote.cursor()
  sql = open(&quot;test03.sql&quot;).read()
  cur.execute(sql)

  remote.close()</code></pre><pre><code></code></pre><h4 id="--multi-query">- MULTI QUERY</h4>
<p>(예제 2) test04.sql 파일 생성 </p>
<pre><code>    INSERT INT sql_file VALUES (1, &quot;test01.sql&quot;)
   INSERT INT sql_file VALUES (2, &quot;test02.sql&quot;)
   INSERT INT sql_file VALUES (3, &quot;test03.sql&quot;)
   INSERT INT sql_file VALUES (4, &quot;test04.sql&quot;)

   후에 실행
   ```
   ```
      remote = mysql.connector.connect(
               host = &quot;database-1.us-east-2.rds.amazonaws.com&quot;,
               port = 3306,
               user = &quot;admin&quot;,
               password = &quot;************&quot;,
               database = &quot;zerobase&quot;
      )

      cur = remote.cursor()
      sql = open(&quot;test04.sql&quot;).read()

      for result_iterator in cur.execute(sql, multi=True):
          if result_iterator.with_rows:
              print(result_iterator.fetchall())
          else:
              print(result_iterator.statement)

      remote.commit()
      remote.close()
      ```</code></pre><ul>
<li><p>FETCH ALL</p>
<ul>
<li><p>cursor.fetchall()</p>
<ul>
<li>SELECT 문 실행해 테이블의 tuple데이터 가지고 올 때 사용</li>
<li>읽어올 데이터 양이 많은 경우 buffered = True옵션</li>
</ul>
<p>(예제) sql_file 테이블 조회</p>
<pre><code>remote = mysql.connector.connect(
        host = &quot;database-1.us-east-2.rds.amazonaws.com&quot;,
        port = 3306,
        user = &quot;admin&quot;,
        password = &quot;*************&quot;,
        database = &quot;zerobase&quot;
)

cur = remote.cursor(buffered=True)
cur.execute(&quot;SELECT * FROM sql_file&quot;)

result = cur.fetchall()
print(result)

for result_iter in result:
   print(result_iter)

remote.close()</code></pre><p>=====================================================</p>
<h3 id="2-csv-데이터로-db-테이블-만들기">2. CSV 데이터로 DB 테이블 만들기</h3>
</li>
</ul>
</li>
</ul>
</li>
<li><p>CSV에 있는 데이터를 Python으로 읽어와 MySQL(INSERT)를 이용해 데이터베이스 테이블로 만듬</p>
</li>
</ul>
<p>(1) CSV 파일 읽기
    - police_station.csv 파일을 Pandas로 읽어와 데이터를 확인 (한글 깨질때 encoding = &#39;euc-kr&#39;)
    ```
    import pandas as pd</p>
<pre><code>df = pd.read_csv(&quot;police_station.csv&quot;)
```</code></pre><p>(2) MySQL연결
    - AWS RDS의 (database-1)으로 연결
        <code></code>
       import mysql.connector</p>
<pre><code>    connector = mysql.connector.connect(
                host = &quot;database-1.*****.rds.amazonaws.com&quot;,
                port = 3306,
                user = &quot;zero&quot;,
                password = &quot;zerobase&quot;,
                database = &quot;zerobase&quot;
    )</code></pre><p>``            ```
(3) CURSOR 생성
    - 읽어올 데이터 양이 많으면 cursor 생성 시 buffer = True</p>
<pre><code>```
cursor = connector.cursor(buffered=True)
```</code></pre><p>(4) INSERT 문
    - pandas.DataFrame 형태의 데이터를 police_station 테이블의 데이터로 넣기 위한          INSERT Query문 생성
        <code>sql = &quot;INSERT INTO police_station VALUES (%s, %s)&quot;</code></p>
<p>(5) 데이터 입력
    ```
    mysql.connector execute()
       commit() :  데이터베이스에 적용하기</p>
<pre><code> for idx, row in df.iterrows():
    cursor.execute(sql, tuple(row))
    connector.commit()
 ```       </code></pre><p>(6) 결과 확인
    데이터베이스에 데이터가 잘 반영되어 있는지 확인</p>
<pre><code>```
cursor.execute(&quot;SELECT * FROM police_station&quot;)
result = cursor.fetchall()
for row in result:
    print(row)

connector.close()
```</code></pre><p>(7) DataFrame으로 결과읽기</p>
<pre><code>```
 result_df = pd.DataFrame(result)
```</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - AWS RDS]]></title>
            <link>https://velog.io/@jj_study/SQL-AWS-RDS</link>
            <guid>https://velog.io/@jj_study/SQL-AWS-RDS</guid>
            <pubDate>Tue, 19 Mar 2024 10:21:01 GMT</pubDate>
            <description><![CDATA[<h3 id="1-aws-rds">1. AWS RDS</h3>
<ul>
<li><ul>
<li><p>Amazon Relational Database Service는 AWS에서 제공하는 관계형 데이터베이스 서비스
&lt;사용방법&gt;
(1) AWS RDS에 생성한 DB &#39;database-1&#39;에 접속
  mysql -h &lt;엔드포인트&gt; -P &lt;포트&gt; -u&lt;마스터 사용자&gt; -p&lt;패스워드&gt;
(2) DB(zerobase) 생성 </p>
<pre><code>  CREATE DATABASE zerobase DEFAULT CHARACTER SET utf8mb4  #이모지 사용가능
  SHOW DATABASES;</code></pre><p>(3) 사용자 (zero) 추가하고 확인  (사용자 추가)</p>
<pre><code>  CREATE USER &#39;zero&#39;@&#39;%&#39; IDENTIFIED BY &#39;zerobase&#39;;
  # 사용자 삭제를 하고 싶으면
  # DROP USER &#39;zero&#39;@&#39;%&#39;;

  USE (사용하고자 하는 database);
  SELECT host, user FROM user;</code></pre><ul>
<li>(4) 사용자 (zero)에게 외부에서 접근해 zerobase 데이터 베이스 사용할 수 있는 권한 부여하고 접근<pre><code>GRANT ALL ON zerobase.* TO &#39;zero&#39;@&#39;%&#39;;
REVOKE ALL ON zerobase.* FROM &#39;zero&#39;@&#39;%&#39;;
</code></pre></li>
</ul>
<h1 id="권한-확인">권한 확인</h1>
<p>SHOW GRANTS FOR &#39;zero&#39;@&#39;%&#39;;</p>
<pre><code>(5) 현재 접속 종료하고 AWS RDS를 통해 zerobase Database에 접근하고자 하는 경우</code></pre><p>exit
mysql - h &lt;엔드포인트&gt; -P&lt;포트&gt; -u zero -pzerobase
```</p>
<h3 id="2-sql-file">2. SQL FILE</h3>
</li>
</ul>
</li>
<li><p>  (1) SQL 파일 생성</p>
<pre><code>  Visual Studio 의 sql_ws폴더에서 새 파일 만듦  (test01.sql)
  그 안에 police_station 만듬
  ```
  CREATE TABLE police_station
  (
      name VARCHAR(16),
      address VARCHAR(128)
  );
  ```</code></pre><p>  (2) SQL 파일 실행</p>
<pre><code>  - MySQL내서 실행
      - MySQL에 로그인 상태에서 SQL 파일 실행
      - source : SQL 파일 실행하는 명령어 대신 \. 사용 가능
          ```
           mysql&gt; source /path/file_name.sql
          또는
          mysql&gt; \. /path/file_name.sql
          ```
      - SQL 파일이 있는 현재 폴더에서 로그인 했다면 path는 생략
     ```
      # sql file이 있는 현재 폴더에서 MySQL에 로그인함과 동시에 DB에 바로 접근
      C:\Documents\sql_ws % mysql -uroot -p********* db_name

      # sql file 실행
      mysql&gt; source file_name.sql
      ``` 
    - MySQL밖에서 실행
      - MySQL에 로그인 하지 않은 상태로 외부에서 SQL파일을 바로 실행
      ```
      DB_name &lt; /path/file_name.sql에서 &lt;은 파일을 DB로 갸져오도록 함
      &gt;mysql -u user_name -p password DB_name &lt; /path/file_name.sql
      ```</code></pre><h3 id="3-backup-sql-file">3. BACKUP SQL FILE</h3>
<ul>
<li><p>데이터베이스나 데이터베이스 내 테이블을 SQL파일로 만들어 사용가능
(1) 백업파일 생성</p>
<pre><code>  - mysqldump 명령어 : 명령으를 사용하는 현재 폴더에 백업파일 생성
```
DB_name &gt; backup_file.sql에서 &gt;은 데이터베이스의 데이터를 파일로 내보냄

# 특정 DB의 백업 파일 생성
&gt;mysqldump -u user_name -p DB_name &gt; backup_file.sql
# 모든 DB의 백업 파일 생성
&gt;mysqldump -u user_name -p --all-databases &gt; backup_file.sql
```</code></pre><h3 id="4-database-복구">4. DATABASE 복구</h3>
</li>
<li><p>DB 백업한 SQL 실행하여 백업한 그 시점에서 복구</p>
</li>
</ul>
<h3 id="5-database-이전">5. DATABASE 이전</h3>
<ul>
<li><p>DB 백업한 SQL 파일 활용해 다른  DB로 이전 가능</p>
</li>
<li><p>로컬 아닌 외부 데이터베이스인  AWS RDS로 이전 가능</p>
<pre><code>mysql -h(host) &lt;엔드포인트&gt; -P(Port) &lt;포트&gt; -u &lt;마스터&gt; -p&lt;password&gt;</code></pre></li>
<li><p>zerobase DB 백업 파일을 AWS RDS (database-1)로 이전 후 접속</p>
<pre><code> C:\Documents\sql_ws&gt;mysql -h database-1.us-east-2.rds.amazonaws.com
                            -P 3306 -u admin -p
 mysql&gt; CREATE DATABASE zerobase DEFAULT CHARACTER SET utf8mb4;
 mysql&gt; USE zerobase;
 mysql&gt; source backup_DB_zerobase.sql
</code></pre><h3 id="6-테이블-backup">6. 테이블 BACKUP</h3>
<ul>
<li>Table을 SQL 파일로 만들 때도 mysqldump 명령어 사용 (백업파일 만들고자하는 폴더에서 명령어 실행)<pre><code>&gt;mysqldump -u user_name -p DB_name Table_name &gt; backup_file.sql</code></pre></li>
</ul>
</li>
<li><p>테이블 내 데이터를 제외하고 테이블 생성 쿼리만 백업</p>
<ul>
<li>특정 테이블 schema Backup<pre><code>   mysqldump -d -u user_name -p db_name table_name &gt; backup_file.sql</code></pre></li>
<li>DB내 모든 테이블 schema Backup<pre><code>   mysqldump -d -u user_name -p db_name &gt; backup_file.sql</code></pre><h3 id="7-복구--이전">7. 복구 / 이전</h3>
</li>
<li>Table을 백업한 SQL 파일을 실행하여 백업한 그 시점으로 복구</li>
<li>Table을 백업한 SQL 파일을 활용해 다른 DB로 Table을 이전 가능<pre><code># 삭제해도  백업한 파일로 복구
mysql&gt; DROP TABLE celeb;
mysql&gt; \. backup_TB_celeb.sql</code></pre></li>
</ul>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - UNION / JOIN / Subquery]]></title>
            <link>https://velog.io/@jj_study/SQL-UNION-JOIN-Subquery-t9el3v2b</link>
            <guid>https://velog.io/@jj_study/SQL-UNION-JOIN-Subquery-t9el3v2b</guid>
            <pubDate>Tue, 19 Mar 2024 08:58:15 GMT</pubDate>
            <description><![CDATA[<h3 id="1-union---수직결합">1. UNION - 수직결합</h3>
<ul>
<li>여러 개의 SQL문을 합쳐서 하나의 SQL문으로 만들어 줌</li>
<li>각 SQL문의 컬럼의 개수가 동일해야 오류 생기지 않음</li>
</ul>
<p>(1) UNION :  중복값 제거 후 검색 반환
(2) UNION ALL : 중복된 값을 포함해 모두 반환</p>
<pre><code>    SELECT column1, column2, ... FROM table_A;
    UNION | UNION ALL
    SELECT column1, column2, ... FROM table_B;</code></pre><p>(예제)
(1) 성별이 여자인 데이터를 검색하는 쿼리와
소속사가 YG엔터테이먼트인 데이터를 검색하는 쿼리를 UNION으로 실행</p>
<pre><code>SELECT name, sex, agency FROM celeb WHERE sex = &quot;f&quot;
UNION ALL
SELECT name, sex, agency FROM celeb WHERE agency = &quot;YG엔터테인먼트&quot;;</code></pre><p>(2) 가수가 직업인 연예인의 이름, 직업을 검색하는 쿼리와,
1980년대에 태어난 연예인의 이름, 생년월일, 나이를 검색하는 쿼리를 UNION으로 실행</p>
<ul>
<li><p>이 경우  컬럼 개수가 달라서 오류 발생</p>
<pre><code>SELECT name, job_title FROM celeb WHERE job_title LIKE &quot;%가수%&quot;
UNION
SELECT name, birthday, age FROM celeb WHERE birthday BETWEEN &#39;1980-01-01&#39; AND &#39;1989-12-31&#39;; </code></pre><h3 id="2-join---수평결합">2. JOIN - 수평결합</h3>
</li>
<li><p>두 개 이상의 테이블을 특정 컬럼 기준으로 결합하는 명령어</p>
</li>
<li><p>INNER JOIN / FULL OUTER / LEFT JOIN  / RIGHT JOIN</p>
</li>
<li><p>snl_show 테이블 이용 (ID SEASON  EPISODE  BROADCAST_DATE  HOST)</p>
</li>
</ul>
<p>(1) INNER JOIN
두 개의 테이블에서 공통된 요소들을 통합해 결합하는 조인 방식. 일종의 교집합
ON : 조인의 기준.  해당 컬럼의 값이 같을 때 조인</p>
<pre><code>SELECT tableA.column1, tableA.column2, ..., tableB.column1,         tableB.column2, ...
FROM tableA
INNER JOIN tableB
ON tableA.column_name = tableB.column_name WHERE condition;</code></pre><p>(예제)
(1) snl_show에 호스트로 출연한 셀럽을 기준으로 celeb Table과 snl_show Table을 INNER JOIN</p>
<pre><code>SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb INNER JOIN snl_show
ON celeb.name = snl_show.host;</code></pre><p>(2) LEFT JOIN
두 개 테이블에서 공통 영역 포함하고 왼쪽 테이블에만 있는 다른 데이터도 포함한 조인 방식</p>
<pre><code>SELECT tableA.column1, tableA.column2, ..., tableB.column1, tableB.column2, 
FROM tableA       # 왼쪽 table
LEFT JOIN tableB  # 오른쪽 table
ON tableA.column_name = tableB.column_name WHERE condition;</code></pre><p>(예제) 
(1) snl_show에 호스트로 출연한 셀럽을 기준으로 celeb Table과 snl_show Table을 LEFT JOIN</p>
<pre><code>SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb 
LEFT JOIN snl_show
ON celeb.name = snl_show.host;</code></pre><p>(2) RIGHT JOIN
두 개 테이블에서 공통 영역 포함하고 오른쪽 테이블에만 있는 다른 데이터도 포함한 조인 방식</p>
<pre><code>SELECT tableA.column1, tableA.column2, ..., tableB.column1, tableB.column2,  FROM tableA
RIGHT JOIN tableB
ON tableA.column_name = tableB.column_name WHERE condition;</code></pre><p>(예제)
(1) snl_show에 호스트로 출연한 셀럽을 기준으로 celeb Table과 snl_show Table을 RIGHT JOIN</p>
<pre><code>SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb
RIGHT JOIN snl_show
ON celeb.name = snl_show.host;</code></pre><p>(3) FULL OUTER JOIN</p>
<ul>
<li>두 개 테이블에서 공통 영역 포함하고 양쪽 테이블의 다른 영역도 모두 포함시키는 조인 방식 (MySQL 에서 지원하지 않아서 FULL OUTER JOIN 과 같은 결과를 내는 다른 방식)<pre><code>SELECT tableA.column1, tableA.column2, ..., tableB.column1, tableB.column2, 
FROM tableA FULL OUTER JOIN tableB
ON tableA.column_name = tableB.column_name WHERE condition;</code></pre>(예제)
(1) snl_show에 호스트로 출연한 셀럽을 기준으로 celeb Table과 snl_show Table을 FULL OUTER JOIN<pre><code>SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb LEFT JOIN snl_show ON celeb.name = snl_show.host
UNION
SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb RIGHT JOIN snl_show ON celeb.name = snl_show.host;</code></pre>(4) SELF JOIN</li>
<li>INNER JOIN과 같은 결과를 도출하는 조인 방식.  조인되는 테이블 간에 공통된 데이터를 가져 옴<pre><code>SELECT tableA.column1, tableA.column2, ..., tableB.column1, tableB.column2, FROM tableA, tableB, ...
WHERE condition;  # WHERE 절에 결합의 기준을 명시</code></pre>(예제)
(1) celeb Table의 연예인 중 snl_show에 host로 출연했고
영화배우는 아니면서 YG엔터테이먼트 소속이거나 40세 이상이면서 YG엔터테이먼트 소속이 아닌 연예인의 이름과 나이, 직업, 소속사, 시즌, 에피소드 정보를 검색<pre><code>SELECT celeb.name, celeb.age, celeb.job_title, celeb.agency, snl_show.episode
FROM celeb, snl_show
WHERE celeb.name = snl_show.host AND ((job_title NOT LIKE &quot;%영화배우%&quot; AND agency!=&quot;YG엔터테인먼트&quot;) OR (age &gt;= 40 AND agency !=&quot;YG엔터테인먼트&quot;));</code></pre>====================================================================<h3 id="3-sql-subquery">3. SQL Subquery</h3>
</li>
<li>하나의 SQL문 안에 포함되어 있는 또 다른 SQL문</li>
<li>메인 쿼리가 서브쿼리 포함</li>
<li>주의사항 : 서브쿼리는 괄호로 묶어 사용 / 단일 행 혹은 복수 행 비교연산자와 함께 사용 가능 / 서브쿼리에서는 ORDER BY 사용할 수 없음</li>
</ul>
<p>(1) Scalar Subquery
    - SELECT 절에 사용
    - 결과는 하나의 컬럼
    <code>SELECT column1, (SELECT column2 FROM table2_name WHERE condition)
    FROM table1_name WHERE condition;</code>
   (예제)
   (1) 서울은평경찰서의 강도 검거 건수와 서울시 경찰서 전체의 평균 강도 검거 건수를 조회</p>
<pre><code>    SELECT case_number 은평경찰서 강도검거건수, (SELECT AVG(case_number) FROM crime_status WHERE crime_type LIKE &#39;강도&#39; AND status_type LIKE &#39;검거&#39;) 서울시 경찰서 검거 평균
    FROM crime_status
    WHERE police_station = &quot;은평&quot; AND crime_type = &quot;강도&quot; AND status_type = &quot;검거&quot;;</code></pre><p>(2) Inline View
    - FROM 절에 사용
    - 메인 쿼리에서는 인라인뷰에서 조회한 컬럼만 사용 가능
    <code>SELECT a.column_name, b.column_name, ...
    FROM table1_name a, (SELECT column1, column2, ... FROM table2_name) b
    WHERE condition;</code>
    (예제) 
    (1) 경찰서 별로 가장 많이 발생한 범죄 건수와 범죄 유형을 조회
    <code>SELECT c.police_station, c.crime_type, c.case_number
    FROM crime_status c, (SELECT police_station, MAX(case_number) count
                          FROM crime_status
                          WHERE status_type = &quot;발생&quot;
                          GROUP BY police_station) m
    WHERE c.police_station = m.police_station AND c.case_number = m.count</code>
(3) Nested Subquery
    - WHERE 절에서 사용
    ((1)) (SINGLE ROW) : 하나의 행 검색하는 서브쿼리 (서브쿼리가 비교연산자와 사용하는 경우)  괄호가 없거나 한 개 이상의 결과값 가지는 경우 에러 발생
            <code>SELECT column_names,... 
            FROM table_name
            WHERE column_name = (SELECT column_name FROM table_name WHERE                 condition)
            ORDER BY column_names;</code>
            (예제)
            (1) SNL에 출연한 연예인 중 id가 1인 연예인
            <code>SELECT name FROM celeb WHERE name = (SELECT host FROM snl_show WHERE id=1);</code>
    ((2)) Multiple Row
          - 하나 이상의 행을 검색하는 서브쿼리
          - IN : 서브쿼리 결과 중 포함되는 경우
          <code>SELECT column_names,... 
          FROM table_name
          WHERE column_name IN (SELECT column_name FROM table_name WHERE condition)
          ORDER BY column_names;</code>
          (예제)
          (1) SNL에 출연한 영화배우를 조회
          <code>SELECT host 
          FROM snl_show
          WHERE host IN (SELECT name FROM celeb WHERE job_title LIKE &#39;%영화배우%&#39;;</code>
          - EXISTS :  서브쿼리 결과에 값이 있으면 True 반환
          <code>SELECT column_names,... 
          FROM table_name
          WHERE EXISTS (SELECT column_name 
                        FROM table_name 
                        WHERE condition)
          ORDER BY column_names;</code>
          (예제)
          (1)  범죄 검거 혹은 발생 건수가 2000건 보다 큰 경찰서 조회
          <code>SELECT name FROM police_station p
          WHERE EXISTS (SELECT police_station FROM crime_status c
                        WHERE p.name = c.reference AND case_number &gt; 2000);</code>
          - ANY : 서브쿼리 결과 중에 최소한 하나라도 만족하면 반환
          <code>SELECT column_names,... 
          FROM table_name
          WHERE column_name = ANY (SELECT column_name 
                                   FROM table_name 
                                   WHERE condition)
          ORDER BY column_names;</code>
          (예제)
          (1) SNL에 출연한 적이 있는 연예인 이름 조회
          <code>SELECT name 
          FROM celeb
          WHERE name = ANY (SELECT host 
                            FROM snl_show);</code>
          - ALL : 서브쿼리 결과를 모두 만족하면 반환 (비교연산자 사용)
          <code>SELECT column_names,... 
          FROM table_name
          WHERE column_name = ALL (SELECT column_name 
                                   FROM table_name 
                                   WHERE condition)
          ORDER BY column_names;</code>
          (예제)
          (1) SNL에 출연한 적이 있는 연예인 이름 조회
          <code>SELECT name 
          FROM celeb
          WHERE name = ALL (SELECT host 
                            FROM snl_show 
                            WHERE id=1);</code>
    ((3)) Multiple Column
    - 하나 이상의 열을 검색하는 서브쿼리
    - 서브쿼리 내에 메인 쿼리 컬럼을 가져와 같이 사용되는 경우
    <code>SELECT column_names, ...
    FROM table1_name a
    WHERE (a.column1, a.column2, ...)
            IN (SELECT b.column1, b.column2, ...
            FROM table2_name b
            WHERE a.column_name = b.column_name)
    ORDER BY column_names;</code>
    (예제)
    (1) 강동원과 성별, 소속사가 같은 연예인의 이름, 성별, 소속사를 조회
    <code>SELECT name, sex, agency 
    FROM celeb
    WHERE (sex, agency) IN (SELECT sex, agency 
                               FROM celeb
                            WHERE name = &quot;강동원&quot;);</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - CONCAT/ALIAS/DISTINCT/LIMIT/Scalar Functions/PRIMARY KEY/FOREIGN KEY]]></title>
            <link>https://velog.io/@jj_study/SQL-CONCATALIASDISTINCTLIMITScalar-FunctionsPRIMARY-KEYFOREIGN-KEY</link>
            <guid>https://velog.io/@jj_study/SQL-CONCATALIASDISTINCTLIMITScalar-FunctionsPRIMARY-KEYFOREIGN-KEY</guid>
            <pubDate>Tue, 19 Mar 2024 06:28:26 GMT</pubDate>
            <description><![CDATA[<h3 id="1-concat">1. CONCAT</h3>
<ul>
<li><p>여러 문자열을 하나로 합치거나 연결</p>
<pre><code>SELECT CONCAT(&#39;string1&#39;, &#39;string2&#39;, ...);</code></pre><p>예제
  SELECT CONCAT(&#39;concat&#39;, &#39; &#39;, &#39;test&#39;);
  +-------------------------------+
  | CONCAT(&#39;concat&#39;, &#39; &#39;, &#39;test&#39;) |
  +-------------------------------+
  | concat test                   |
  +-------------------------------+</p>
<p>  SELECT CONCAT(&#39;이름 : &#39;, name) FROM celeb;
  +---------------------------+
  | CONCAT(&#39;이름 : &#39;, name)   |
  +---------------------------+
  | 이름 : 아이유              |
  | 이름 : 이미주              |
  | 이름 : 송강                |
  | 이름 : 강동원              |
  | 이름 : 유재석              |
  | 이름 : 차승원              |
  | 이름 : 이수현              |
  +---------------------------+</p>
<h3 id="2-alias">2. ALIAS</h3>
</li>
<li><p>컬럼이나 테이블에 붙이는 별칭</p>
</li>
<li><p>ALIAS가 출력 됨   (~AS 는 생략 가능)</p>
<pre><code>SELECT column1 AS alias1, column2 AS alias2, ... FROM table_name;
SELECT column1 alias1, column2 alias2, ... FROM table_name alias;
SELECT column1, column2, ... FROM table_name AS alias;</code></pre><h3 id="3-distinct">3. DISTINCT</h3>
</li>
<li><p>검색에 대한 중복 제거</p>
<pre><code>SELECT DISTINCT column1, column2, ... FROM table_name;</code></pre><p>예제
(1) 연예인 소속사 정보 검색 </p>
</li>
<li><p>중복 데이터 출력하며 다 보여주기</p>
<pre><code>SELECT agency FROM celeb;</code></pre></li>
<li><p>중복 데이터 제외하며 보여주기</p>
<pre><code>SELECT DISTINCT agency FROM celeb;</code></pre><p>(2) 가수 중 성별과 직업별 종류 검색</p>
</li>
<li><p>중복 데이터 출력하며 다 보여주기</p>
<pre><code>SELECT sex, job_title FROM celeb WHERE job_title LIKE &#39;%가수%&#39;;</code></pre></li>
<li><p>중복 데이터 제외하며 보여주기</p>
<pre><code>SELECT DISTINCT sex, job_title FROM celeb WHERE job_title LIKE &#39;%가수%&#39;; </code></pre><h3 id="4-limit">4. LIMIT</h3>
</li>
<li><p>검색 결과를 정렬된 순에서 LIMIT로 주어진 숫자만큼 조회</p>
<pre><code>SELECT column1, column2, ... FROM table_name WHERE condition LIMIT number;</code></pre><p>예제
(1) celeb 테이블에서 id로 정렬된 데이터 3개</p>
<pre><code>SELECT * FROM celeb LIMIT 3;</code></pre><p>(2) 나이가 가장 적은 연예인 4명 검색</p>
<pre><code>SELECT * FROM celeb ORDER BY age LIMIT 4;</code></pre><p>===============================================================</p>
<h3 id="5-scalar-functions">5. SCALAR Functions</h3>
<p>실습환경 : AWS RDS (database-1) zerobase DB, sandwich 테이블</p>
</li>
<li><p>입력값을 기준으로 단일 값을 반환</p>
</li>
</ul>
<h4 id="-ucase">* UCASE</h4>
<ul>
<li>영문을 대문자로 변환<pre><code>  SELECT UCASE(&quot;string&quot;);</code></pre>  SELECT UCASE(&#39;This is ucase test.&#39;);
  +------------------------------+
  | UCASE(&#39;This is ucase test.&#39;) |
  +------------------------------+
  | THIS IS UCASE TEST.          |
  +------------------------------+<pre><code></code></pre>(예제) $15넘는 메뉴를 대문자로 조회<pre><code>SELECT UCASE(menu), price FROM sandwich WHERE price &gt; 15;</code></pre><h4 id="-lcase">* LCASE</h4>
</li>
<li>영문을 소문자로 변환<pre><code>SELECT LCASE(&quot;string&quot;);
</code></pre></li>
</ul>
<p>SELECT LCASE(&quot;This IS LCASE Test.&quot;);
    +------------------------------+
    | LCASE(&quot;This IS LCASE Test.&quot;) |
    +------------------------------+
    | this is lcase test.          |
    +------------------------------+</p>
<pre><code>(예제) 가격이 $5 보다 작은 메뉴를 소문자 조회</code></pre><p>SELECT LCASE(menu), price FROM sandwich WHERE price &lt; 5;</p>
<pre><code>#### * MID
- 문자열의 부분을 위치 등에 따라 골라서 반환</code></pre><p>SELECT MID(&quot;string&quot;, start_position, lenth);  (string, start, length)</p>
<pre><code>예제
(1) 1번 위치에서 4글자 조회</code></pre><p>SELECT MID(&#39;This is mid test&#39;, 1, 4);</p>
<pre><code>(2) 6번 위치에서 5글자 조회</code></pre><p>SELECT MID(&#39;This is mid test&#39;, 6, 5);</p>
<pre><code>(3) -4번 위치(뒤에서 4번째 위치)에서 4글자 조회</code></pre><p>SELECT MID(&#39;This is mid test&#39;, -4, 4);</p>
<pre><code>(4) -8번 위치(뒤에서 8번째 위치)에서 3글자를 조회</code></pre><p>SELECT MID(&#39;This is mid test&#39;, -8, 3);</p>
<pre><code>(5) 11위 카페이름 중 두번째 단어만 조회: 6번 위치에서 4글자
하나씩 단계별 조회해서 추출할 단어 위치를 찾기</code></pre><p> mysql&gt; SELECT cafe FROM sandwich WHERE ranking=11;
    +-----------+
    | cafe      |
    +-----------+
    | Lula Cafe |
    +-----------+</p>
<pre><code>mysql&gt; SELECT MID(cafe, 6, 4) FROM sandwich WHERE ranking=11;
+-----------------+
| MID(cafe, 6, 4) |
+-----------------+
| Cafe            |
+-----------------+</code></pre><pre><code>#### * LENGTH
- 문자열 길이 반환</code></pre><p>SELECT LENGTH(&quot;string&quot;);</p>
<pre><code>(예제)
(1) 문장의 길이 조회</code></pre><p>SELECT LENGTH(&#39;This is len test.&#39;);</p>
<pre><code>(2) &#39;&#39;에 공백이 없는 경우 길이는 0</code></pre><p>SELECT LENGTH(&#39;&#39;);</p>
<pre><code>(3) &#39;&#39;에 공백이 있는 경우 길이는 1</code></pre><p>SELECT LENGTH(&#39; &#39;);</p>
<pre><code>(4) NULL의 경우 길이가 없으므로 결과는 NULL</code></pre><p>SELECT LENGTH(NULL);</p>
<pre><code>(5) sandwich Table에서 Top 3의 주소 길이를 검색</code></pre><p>SELECT LENGTH(address), address FROM sandwich ORDER BY ranking LIMIT 3;
또는
SELECT LENGTH(address), address FROM sandwich WHERE ranking &lt;= 3;</p>
<pre><code>#### * ROUND
- 지정한 자리에서 숫자 반올림 (0은 소수점 첫째 자리)</code></pre><p>SELECT ROUND(number, deciamls_place);  </p>
<pre><code>(예제)
(1) 위치를 지정하지 않을 경우, 소수점 첫번째 자리(0)에서 반올림</code></pre><p>SELECT ROUND(315.625);    답: 316</p>
<pre><code>(2) 소수점 첫번째 위치는 0</code></pre><p>SELECT ROUND(315.625, 0);  답: 316</p>
<pre><code>(3) 두번째 소수점 위치는 1</code></pre><p>SELECT ROUND(315.625, 1);  답: 315.6</p>
<pre><code>(4) 세번째 소수점 위치는 2</code></pre><p>SELECT ROUND(315.625, 2);  답: 315.63</p>
<pre><code>(5) 자연수 일단위 위치는 -1</code></pre><p>SELECT ROUND(315.625, -1);  답: 320</p>
<pre><code>(6) 자연수 십단위 위치는 -2</code></pre><p>SELECT ROUND(315.625, -2);   답: 300</p>
<pre><code>(7) sandwich 테이블에서 소수점 자리는 반올림하여 1달러 단위까지만 표시 (단, 최하위 3개만 표시)</code></pre><p>SELECT ranking, price, ROUND(price, 0) FROM sandwich
ORDER BY ranking DESC
LIMIT 3</p>
<pre><code>#### * NOW
- 현재 날짜 및 시간 반환</code></pre><p>SELECT NOW();   2024-02-27 17:42:33 이렇게 반환</p>
<pre><code>#### * FORMAT
- 문자나 숫자를 천단위 콤마 있는 형식으로 반환</code></pre><p>SELECT FORMAT(number, decimals_place);  decimal은 소수점 위치</p>
<pre><code>(예제)
(1) 소수점을 표시하지 않을 경우 0</code></pre><p>SELECT FORMAT(12345.6789, 0);   정답 : 12,346</p>
<pre><code>(2) 소수점 두자리까지 표시할 경우 2</code></pre><p>SELECT FORMAT(12345.6789, 2);   정답 : 12,345.68</p>
<pre><code>(3) 소수점 열자리까지 표시</code></pre><p>SELECT FORMAT(12345.6789, 10);</p>
<pre><code>(4) oil_price Table에서 가격이 백원단위에서 반올림 했을 때 2000원 이상인 경우. 천원 단위에 콤마를 넣어서 조회</code></pre><p>SELECT FORMAT(가격, 0) FROM oil_price WHERE ROUND(가격, -3) &gt;= 2000;</p>
<pre><code>===============================================================
### 6. PRIMARY KEY
- 후보키 (Candidate Key)들 중 개체(Table) 구별을 위해 선택된 하나의 키
- 후보키 (Candidate Key) - 하나의 릴레이션(Relation)에서 유일성과 최소성을 가지고 있는 모든 속성 혹은 속성 집합
- 기본키로 선택된 속성은 중복되지 않는 고유값 보유
- 정의되지 않은 NULL 값을 포함할 수 없다. → NOT NULL
- 다른 테이블의 외래키에 의해 참조될 수 있음

#### (1) PRIMARY KEY 문법  
- 테이블 생성시 지정
    ```
    CREATE TABLE table_name(
    column1 datatype NOT NULL,
    column2 datatype NOT NULL,
    ...
    [CONSTRAINT constraint_name] PRIMARY KEY (column1, column2, ...)
    );
    --&gt; CONSTRAINT은 생략 가능. 생략하면 자동으로 생성 됨.
    ```

- 이미 정의되어 있는 테이블에 기본키를 설정하는 방법
    ```
    ALTER TABLE table_name ADD PRIMARY KEY (column1, column2, ...)
    ```
---------------------------------------------------------------------
- 테이블 삭제시
    ```
    ALTER TABLE table_name DROP PRIMARY KEY;
    ```
---------------------------------------------------------------------
(예제)
(1) person 테이블 생성하면서 Primary Key 지정
    ```
    CREATE TABLE person(
        pid int NOT NULL,
        name varchar(16),
        age int,
        sex char,
        PRIMARY KEY (pid)
    );
    ```
(2) person 테이블 기본키 삭제
    ```
     ALTER TABLE person DROP PRIMARY KEY;
    ```
(3) 이미 정의 되어 있는 person 테이블의 기본키 설정
    ```
     ALTER TABLE person ADD PRIMARY KEY (pid);
    ```
====================================================================
### 7. FOREIGN KEY
- 외래키는 두 Relation 간의 관계를 맺어줄 때 사용되는 키
- 외래키로 정의된 속성(Attribute)는 반드시 상대 Relation의 기본키여야 함
- 기본키와 달리 외래키는 한 테이블 내에 여러 개일 수 있음. 즉, 여러 개의 테이블 참조 가능
    - 외래키 확인을 위해 CONSTRAINT으로 지정한 이름을 확인 가능
    - CONSTRAINT를 생략하면 이름이 자동 생성
    - 이 constraint_name을 알아야 해당 외래키를 삭제(DROP) 가능

#### (1) FOREIGN KEY 문법  
- 테이블 생성 후에도 ALTER TABLE을 통해 FOREIGN KEY를 지정 가능

*** 테이블 생성 시 지정</code></pre><pre><code>CREATE TABLE table_name(
        column1 datatype NOT NULL,
        column2 datatype NOT NULL,
        column3 datatype,
        column4 datatype,
        ...
        [CONSTRAINT constraint_name] PRIMARY KEY (column1, column2, ...)
        [CONSTRAINT constraint_name]
           PRIMARY KEY (column3, column4, ...) REFERENCES                     REF_tablename(REF_column)
);</code></pre><pre><code>- 기존 테이블에서 외래키 설정</code></pre><pre><code>ALTER TABLE table_name ADD FOREIGN KEY (column) REFERENCES REF_tablename(REF_column)
--&gt; CONSTRAINT이 생략되어 있지만 자동으로 생성</code></pre><pre><code>- 자동 생성된 CONSTRAINT 확인</code></pre><p>SHOW CREATE TABLE table_name;</p>
<pre><code>*** 테이블 삭제 시 지정
    - 외래키는 한 테이블에 여러 개가 존재할 수 있으므로 삭제하려는 외래키를 지정해 줘야 함</code></pre><p>ALTER TABLE table_name DROP FOREIGN KEY FK_constrain_name;</p>
<pre><code>(예제)
(1)  CREATE TABLE 에서 외래키 지정</code></pre><pre><code> CREATE TABLE orders(
        oid int NOT NULL,
        order_no varchar(16),
        pid int,
        PRIMARY KEY (oid),
        [CONSTRAINT FK_person] FOREIGN KEY (pid) REFERENCES person(pid)
);
SHOW CREATE TABLE orders;   #pid의 key가 MUL로 나옴</code></pre><pre><code>(2) CREATE TABLE에서 외래키를 지정하는 경우, CONSTRAINT를 생략 가능</code></pre><p>   CREATE TABLE job(
            jid int NOT NULL,
            name varchar(16),
            pid int,
            PRIMARY KEY (jid),
            FOREIGN KEY (pid) REFERENCES person(pid)
    );
    SHOW CREATE TABLE job;</p>
<pre><code>(3) 이미 정의 되어 있는 orders 테이블에서 외래키 설정</code></pre><p>ALTER TABLE orders
            ADD [CONSTRAINT FK_person] FOREIGN KEY (pid) REFERENCES person(pid);
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - 부속 질의어]]></title>
            <link>https://velog.io/@jj_study/SQL-%EB%B6%80%EC%86%8D-%EC%A7%88%EC%9D%98%EC%96%B4</link>
            <guid>https://velog.io/@jj_study/SQL-%EB%B6%80%EC%86%8D-%EC%A7%88%EC%9D%98%EC%96%B4</guid>
            <pubDate>Mon, 18 Mar 2024 15:07:12 GMT</pubDate>
            <description><![CDATA[<h3 id="1-affiliated-dml-부속-질의어">1. Affiliated DML (부속 질의어)</h3>
<ul>
<li>celeb 테이블 생성 
  ID (int)
  Name (varchar)
  BIRTHDAY (date)
  AGE (int)
  SEX (char)
  JOB_TITLE (varchar)
  AGENCY (varchar)</li>
</ul>
<p>(1) WHERE  (조건 추가)
    - Table 내에서 조건을 만족하는 데이터 조회</p>
<pre><code>    SELECT column1, colunm2, ... FROM table_name WHERE condition;</code></pre><p>(2) 비교 연산자</p>
<ul>
<li>관련 문제
이름이 &#39;아이유&#39;인 데이터의 이름과 나이, 성별, 직업, 소속사를 조회<pre><code>select name, age, sex, job_title, agency from celeb where name=&#39;아이유&#39;;</code></pre>소속사가 &#39;YG엔터테이먼트&#39;가 이닌 데이터의 이름, 직업, 소속사를 조회<pre><code>select name, job_title, agency from celeb where agency!=&#39;YG엔터테이먼트&#39;;</code></pre>나이가 50세 미만인 데이터의 성별, 소속사, 이름, 나이를 조회<pre><code>select sex, agency, name, age from celeb where age &lt; 50;</code></pre>(3) 논리 연산자</li>
<li>AND : 조건을 모두 만족하는 경우 TRUE<pre><code>SELECT column1, column2, ... FROM table_name
WHERE condition1 AND condition2 AND condition3 ...;</code></pre></li>
<li>AND 연산자가 OR 연산자보다 우선 순위가 높음<pre><code>select * from celeb
where (age&lt;29 AND sex=&#39;f&#39;) OR (age&gt;30 AND sex=&#39;m&#39;)
order by age;</code></pre></li>
<li>NOT : 조건을 만족하지 않을 때<pre><code>SELECT column1, column2, ... FROM table_name WHERE NOT condition;</code></pre>예제
(1) 남자이면서 YG엔터테이먼트 소속이거나, 나이가 30세 보다 작은 데이터를 나이, 소속사 순으로 정렬하여 검색<pre><code>select * from celeb
where (sex=&#39;m&#39; AND agency=&#39;YG엔터테이먼트&#39;) OR age&lt;30
order by age, agency;</code></pre>(2) 아이디가 홀수면서 성별이 남자이거나, 아이디가 짝수면서 소속사가 YG엔터테이먼트인 데이터를 나이순으로 정렬하여 검색 <pre><code>select * from celeb
where ((id%2)=1 and sex=&#39;m&#39;) or ((id%2)=0 and agency=&#39;YG엔터테이먼트&#39;)
order by age;</code></pre>(3) 생일이 1990년 이후이면서 여자가 아니거나, 생일이 1979년 이전이면서 소속사가 안테나가 아닌 데이터를 검색<pre><code>select * from celeb
where (birthday&gt;19891231 AND NOT sex=&#39;f&#39;) OR (birthday&lt;19800101 AND NOT agency=&#39;안테나&#39;);</code></pre>================================================
(4) BETWEEN A AND B
조건값이 A ≤ column_value ≤ B 범위 사이<pre><code>SELECT column1, column2, ... FROM table_name
WHERE col_name BETWEEN p_value AND q_value;
</code></pre></li>
</ul>
<p>-- 둘은 같은 결과 도출 --
WHERE col_name &gt;= p_value AND col_name &lt;= q_value;</p>
<pre><code>예제
(1) 생년월일이 1980년에서 1995년 사이가 아니면서 여자이거나, 소속사가 &#39;YG엔터테이먼트&#39;이면서 나이가 20세에서 45세 사이가 아닌 데이터 검색</code></pre><p>select * from celeb 
where (NOT birthday BETWEEN 19800101 AND 19951231 and sex=&#39;f&#39;)
or (agency=&#39;YG엔터테이먼트&#39; and NOT age BETWEEN 20 AND 45);</p>
<pre><code>(2) 나이가 30세에서 60세 사이이고 성별이 남자인 데이터를 나이순으로 정렬하여 조회</code></pre><p>select * from celeb where age BETWEEN 30 AND 60 and sex=&#39;m&#39; order by age;</p>
<pre><code>(3) 나이가 30세에서 60세 사이가 아니거나 &#39;YG엔터테이먼트&#39; 소속인 데이터를 나이의 역순으로 정렬하여 조회</code></pre><p>select * from celeb
where NOT age BETWEEN 30 AND 60 or agency=&#39;YG엔터테이먼트&#39; 
order by age desc;</p>
<pre><code>(4) 아이디가 1에서 5 사이의 값이면서 성별이 여자이거나, 아이디가 홀수이면서 성별이 남자이면서 나이가 20에서 30세 사이인 데이터를 조회</code></pre><p>select * from celeb
where (id BETWEEN 1 AND 5 and sex=&#39;f&#39;)
or ((id%2)=1 and sex=&#39;m&#39; and age BETWEEN 20 AND 30);</p>
<pre><code>====================================
(5) IN / NOT IN
- 집합 연산자로 조건값이 목록에 있음</code></pre><p>SELECT column1, column2,... FROM table_name
WHERE col_name IN (value1, value2,...);</p>
<p>SELECT column1, column2, ... FROM table_name 
WHERE NOT column_name IN (value1, value2, ...);</p>
<pre><code>예제
(1) 소속사가 나무엑터스, 안테나, 울림엔터테이먼트가 아니면서, 성별이 여자이거나 나이가 45세 이상인 데이터 검색</code></pre><p>select * from celeb
where NOT agency IN (&#39;나무엑터스&#39;, &#39;안테나&#39;, &#39;울림엔터테이먼트&#39;) and (sex=&#39;f&#39; or age&gt;=45);</p>
<pre><code>(2) 아이유, 이미주, 송강 중에서 소속사가 &#39;나무엑터스&#39;인 데이터를 조회</code></pre><p>select * from celeb where name IN (&#39;아이유&#39;,&#39;이미주&#39;,&#39;송강&#39;) and agency=&#39;나무엑터스&#39;;</p>
<pre><code>(3) 소속사가 안테나, YG엔터테이먼트 중 하나가 아니고, 성별이 여자인 데이터를 조회</code></pre><p> select * from celeb
where NOT agency IN (&#39;안테나&#39;, &#39;YG엔터테이먼트&#39;) and sex=&#39;f&#39;;</p>
<pre><code>(4) 아이유, 송강, 강동원, 차승원 중에 YG엔터테이먼트 소속이 아니거나 나이가 40세에서 50세 사이인 사람을 찾아본다.</code></pre><p>select * from celeb
where name IN (&#39;아이유&#39;, &#39;송강&#39;, &#39;강동원&#39;, &#39;차승원&#39;) and (agency!=&#39;YG엔터테이먼트&#39; or age between 40 and 50);</p>
<pre><code>(6) LIKE / NOT LIKE
- 패턴 연산자로 조건값이 패턴에 맞는지</code></pre><p>SELECT column1, column2, ... FROM table_name WHERE col_name LIKE pettern;</p>
<pre><code>예제
(1) 소속사 이름이 &#39;YG&#39;로 시작하는 패턴</code></pre><p>SELECT * FROM celeb WHERE agency LIKE &#39;YG%&#39;;</p>
<pre><code>(2) &#39;엔터테이먼트&#39;로 끝나는 소속사 이름을 가진 데이터 검색</code></pre><p>SELECT * FROM celeb WHERE agency LIKE &#39;%엔터에이먼트&#39;;</p>
<pre><code>(3) 직업명에 &#39;가수&#39;가 포함된 패턴의 데이터 검색 &#39;%가수%&#39;는 &#39;가수&#39;로 시작해도 TRUE, &#39;가수&#39;로 끝나도 TRUE</code></pre><p>SELECT * FROM celeb WHERE job_title LIKE &#39;%가수%&#39;;</p>
<pre><code>(4) 소속사 이름의 두번째 글자가 &#39;G&#39;인 패턴의 데이터를 검색  언더바로 글자수를 확보한다. 언더바가 두개면 세번째 글자가 G인 패턴이 된다.</code></pre><p>SELECT * FROM celeb WHERE agency LIKE &#39;_G%&#39;;</p>
<pre><code>(5) 직업명이 &#39;가&#39;로 시작하고 최소 2글자 이상인 패턴의 데이터를 검색  언더바로 최소 두글자를 확보한다.</code></pre><p>SELECT * FROM celeb WHERE job_title LIKE &#39;가_%&#39;;</p>
<pre><code>(6) 직업명이 &#39;가&#39;로 시작하고 최소 4글자 이상인 패턴의 데이터를 검색  언더바를 4개를 추가하면 최소 다섯글자를 확보할 수 있다.</code></pre><p>SELECT * FROM celeb WHERE job_title LIKE &#39;가_ _ _ _%&#39;;</p>
<pre><code>(7) 직업명이 &#39;영&#39;으로 시작하고 &#39;모델&#39;로 끝나는 데이터를 검색  &#39;영%모델&#39; --&gt; &#39;영&#39;으로 시작하고 &#39;모델&#39;로 끝나면서 그 사이에 몇 글자가 와도 상관 없다는 것임</code></pre><p>SELECT * FROM celeb WHERE job_title LIKE &#39;영%모델&#39;;</p>
<pre><code>(8) 직업이 하나 이상인 연예인 중 영화배우 혹은 텔런트가 아닌 연예인 검색</code></pre><p>SELECT * FROM celeb
WHERE job_title LIKE &#39;%,%&#39;
AND NOT (job_title LIKE &#39;%영화배우%&#39; OR job_title LIKE &#39;%텔런트%&#39;);</p>
<pre><code>==============================================
(7) ORDER BY (데이터를 특정 컬럼을 기준으로 오름차순(ASC, Ascending) 혹은 내림차순(DESC, Descending)으로 정렬)</code></pre><p>SELECT col1, col2, ... FROM table_name ORDER BY col_1, col_2, ... ASC;</p>
<p>SELECT col1, col2, ... FROM table_name ORDER BY col_1, col_2, ... DESC;</p>
<pre><code>예제
(1) celeb TABLE에서 이름, 생년월일, 성별, 소속사 컬럼을 소속사 순으로 정렬하여 조회</code></pre><p>SELECT NAME, BIRTHDAY, AGE, AGENCY FROM celeb ORDER BY AGENCY;</p>
<pre><code>(2) celeb TABLE에서 전체 컬럼을 소속사, 이름 순으로 정렬하여 조회</code></pre><p>SELECT * FROM celeb ORDER BY AGENCY, NAME;</p>
<pre><code>(3) 이름, 나이, 직업, 소속사 컬럼을 1. 소속사 순, 2. 나이 역순으로 정렬하여 조회</code></pre><p>SELECT NAME, AGE, JOP_TITLE, AGENCY FROM celeb ORDER BY AGENCY ASC, AGE DESC;</p>
<pre><code>========================================================================
### 2. Aggregate Functions (집계함수 - 하나의 결과값 반환 )

(1) COUNT (해당 컬럼의 총 tuple 수)
- 속성(Column)의 Tuple 데이터 총 개수를 계산하는 함수로 이때 &#39;NULL&#39; 값은 제외 됨</code></pre><p>SELECT COUNT(column_name) FROM table_name WHERE condition;</p>
<pre><code>예제
(1) police_station 테이블에서 데이터는 총 몇개?</code></pre><p>SELECT COUNT(*) FROM police_station;</p>
<pre><code>(2) crime_station 테이블에서 경찰서는 총 몇 개?</code></pre><p>SELECT COUNT(DISTINCT police_station) FROM crime_status;</p>
<pre><code>(3) crime_type (범죄 유형)은 총 몇가지?</code></pre><p>SELECT COUNT(DISTINCT crime_type) FROM crime_status;</p>
<pre><code>============================================
(2) SUM (해당 컬럼의 숫자 데이터의 합계 계산)</code></pre><p>SELECT SUM(column_name) FROM table_name WHERE condition;</p>
<pre><code>예제
(1) 범죄 총 발생 건수?</code></pre><p>SELECT SUM(case_number) FROM crime_status
WHERE status_type = &quot;발생&quot;;</p>
<pre><code>(2) 범죄 유형 중 살인의 총 발생 건수?</code></pre><p>SELECT SUM(case_number) FROM crime_status
WHERE status_type = &quot;발생&quot; AND crime_type = &quot;살인&quot;;</p>
<pre><code>(3) 중부 경찰서에서 검거된 총 범죄 건수?</code></pre><p>SELECT SUM(case_number) FROM crime_status
WHERE status_type = &quot;검거&quot; AND police_station = &quot;중부&quot;;</p>
<pre><code>===============================================
(3) AVG (해당 컬럼에 있는 숫자 데이터들의 평균 계산)</code></pre><p>SELECT AVG(column_name) FROM table_name WHERE condition;</p>
<pre><code>예제
(1) 평균 폭력 검거 건수?</code></pre><p>SELECT AVG(case_number) FROM crime_status 
WHERE crime_type LIKE &quot;폭력&quot; AND status_type LIKE &quot;검거&quot;;</p>
<pre><code>
(2) 중부경찰서의 범죄 평균발생 건수?</code></pre><p>SELECT AVG(case_number) FROM crime_status
WHERE status_type = &quot;발생&quot; AND police_station LIKE &quot;중부&quot;;</p>
<pre><code>============================================================
(4) MIN (해당 컬럼에 있는 숫자 데이터들 중 최소값)</code></pre><p>SELECT MIN(column_name) FROM table_name WHERE condition;</p>
<pre><code>예제
(1) 강도 발생 건수가 가장 적은 경우 건수?</code></pre><p>SELECT police_station, MIN(case_number) FROM crime_status
WHERE crime_type LIKE &quot;강도&quot; AND status_type LIKE &quot;발생&quot;;</p>
<pre><code>
(2) 중부경찰서에서 가장 낮은 검거 건수?</code></pre><p>SELECT MIN(case_number) FROM crime_status
WHERE status_type LIKE &quot;검거&quot; AND police_station LIKE &quot;중부&quot;</p>
<pre><code>=============================================================
(5) MAX (해당 컬럼에 있는 숫자 데이터들 중 최대값)</code></pre><p>SELECT MAX(column_name) FROM tabale_name WHERE condition;</p>
<pre><code>예제
(1) 살인이 가장 많이 검거된 건수?</code></pre><p>SELECT MAX(case_number) FROM crime_status
WHERE crime_type LIKE &quot;살인&quot;;</p>
<pre><code>(2) 강남경찰서에서 가장 맣이 발생한 범죄건수?</code></pre><p>SELECT MAX(case_number) FROM crime_status
WHERE police_station LIKE &quot;강남&quot; AND status_type LIKE &quot;발생&quot;;</p>
<pre><code>================================================================
(6) GROUP BY ~ HAVING (GROUP BY로 그룹화하여 데이터를 조회.  HAVING은 GROUP BY의 조건자 역할)
- 그룹별 데이터 조회시 집계함수 사용
- 조건에 집계함수가 들어갈 때 WHERE 대신 HAVING 사용</code></pre><p>   SELECT column1, column2, ... FROM table_name WHERE condition
   GROUP BY column1, column2, ...   --&gt; 그룹화
   HAVING condition(Aggregate Functions)
   ORDER BY column1, column2, ...;  --&gt; 정렬</p>
<pre><code>예제
(1) 경찰서 별로 발생한 범죄 건수의 합이 4000 건보다 큰 경우 검색</code></pre><p>SELECT police_station, SUM(case_number) count FROM crime_type
WHERE status_type LIKE &quot;발생&quot;
GROUP BY police_station HAVING count &gt; 4000;</p>
<pre><code>(2) 경찰서 별로 발생한 폭력과 절도의 범죄 건수 평균이 2000 이상인 경우를 검색</code></pre><p>SELECT police_station, AVG(case_number) FROM crime_status
WHERE crime_type IN (&quot;폭력&quot; AND &quot;절도&quot;) AND status_type LIKE &quot;발생&quot;
GROUP BY police_station
HAVING AVG(case_number) &gt; 2000;
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - DDL / DML]]></title>
            <link>https://velog.io/@jj_study/SQL-DDL-DML</link>
            <guid>https://velog.io/@jj_study/SQL-DDL-DML</guid>
            <pubDate>Mon, 18 Mar 2024 14:21:16 GMT</pubDate>
            <description><![CDATA[<h3 id="1-ddl-data-definition-language--테이블-생성-변경-삭제">1. DDL (Data Definition Language) : 테이블 생성, 변경, 삭제</h3>
<ul>
<li>Table : 데이터베이스 내에 데이터가 저장되는 형태로 행(Row) 과 열(Column)으로 구성된 데이터 집합</li>
</ul>
<p>(1) CREATE (Table 생성)</p>
<pre><code>    # 테이블 생성
    CREATE TABLE table_name(
          colunm1 data_type,
          colunm2 data_type,
          ...
    );

    # 현재 데이터베이스 내에 모든 테이블의 목록 확인
    SHOW TABLES;

    # Table 정보 확인
    DESC table_name; </code></pre><p>(2) ALTER (Table 변경/수정)</p>
<ul>
<li><p>테이블 이름 변경</p>
<pre><code>  ALTER TABLE tbl_name RENAME new_tbl_name;</code></pre></li>
<li><p>테이블 컬럼 추가</p>
<pre><code>  ALTER TABLE tbl_name ADD COLUMN col_name datatype;</code></pre></li>
<li><p>테이블 컬럼 변경</p>
<pre><code>  # 데이터 자료형 변경
  ALTER TABLE tbl_name MODIFY COLUMN col_name datatype;

  # 컬럼명 변경
  ALTER TABLE tbl_name CHANGE COLUMN old_col_name new_col_name datatype;</code></pre></li>
<li><p>테이블 컬럼 삭제</p>
<pre><code>  ALTER TABLE table_name DROP COLUMN column_name;</code></pre></li>
</ul>
<hr>
<p>(3) DROP (Table 삭제)</p>
<pre><code>    DROP TABLE table_name;</code></pre><p>=================================================</p>
<h3 id="2-dml-data-manipulation-language--테이블-tuple-생성-삭제-편집-조회">2. DML (Data Manipulation Language) : 테이블 tuple 생성, 삭제, 편집, 조회</h3>
<ul>
<li>데이터베이스 생성<pre><code>  # 기본문자는  utf-8, mb4 설정
  CREATE DATABASE zerobase DEFAULT CHARACTER SET utf8mb4</code></pre></li>
<li>사용할 데이터베이스로 이동, 실습용 테이블 생성<pre><code>  USE zerobase;
  CREATE TABLE person(
          id int,
          name varchar(16),
          age int,
          sex char
  );
  DESC person;</code></pre>(1) INSERT INTO (Table에 데이터 추가)<pre><code>  INSERT INTO table_name (col1, col2, ...) VALUES (val1, val2, ...);</code></pre></li>
<li>모든 컬럼에 값을 추가하는 경우 컬럼 이름을 지정하지 않아도 됨.  그러나 입력하는 데이터의 순서가 테이블의 컬럼 순서와 동일해야 함<pre><code>  INSERT INTO person (id, name, age, sex) VALUES (1, &#39;이효리&#39;, 43, &#39;F&#39;);
  INSERT INTO person VALUES (2, &#39;이상순&#39;, 48, &#39;M&#39;);</code></pre>(2) SELECT FROM (Table의 데이터 조회)<pre><code>  SELECT column1, column2, ... FROM table_name;
  SELECT * FROM table_name; </code></pre>(3) UPDATE SET (Table의 데이터 수정)</li>
<li>수정할 데이터 구체적으로 지정하지 않으면 해당 컬럼의 모든 데이터 값이 변하므로 WHERE 조건으로 지정<pre><code> UPDATE table_name SET column1=value1, column2=value2, ...
     WHERE condition;</code></pre></li>
</ul>
<p>(4) DELETE FROM (Table의 데이터 삭제)</p>
<ul>
<li>Where는 삭제할 데이터의 조건을 추가<pre><code>  DELETE FROM table_name WHERE condition;</code></pre></li>
<li>WHERE로 조건이 없이면 해당 컬럼 모든 데이터가 삭제 됨.  테이블 자체를 삭제하고 싶으면 DROP table</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - Database 기본]]></title>
            <link>https://velog.io/@jj_study/SQL-Database-%EA%B8%B0%EB%B3%B8</link>
            <guid>https://velog.io/@jj_study/SQL-Database-%EA%B8%B0%EB%B3%B8</guid>
            <pubDate>Mon, 18 Mar 2024 13:57:16 GMT</pubDate>
            <description><![CDATA[<h3 id="1-데이터베이스-정의">1. 데이터베이스 정의</h3>
<p>여러 사람이 공유하여 사용할 목적으로 체계화해 통합, 관리하는 데이터 집합체</p>
<h3 id="2-dbms-database-management-system">2. DBMS (Database Management System)</h3>
<ul>
<li>사용자와 데이터베이스 사이에서 사용자의 요구에 따라 정보를 생성해주고 데이터베이스를 관리</li>
</ul>
<h3 id="3-rdb-relational-database--관계형-데이터베이스">3. RDB (Relational Database : 관계형 데이터베이스)</h3>
<p>서로간에 관계가 있는 데이터 Table들을 모아둔 데이터 저장 공간</p>
<ul>
<li>행[row] : 튜플[tuple], 레코드[record]</li>
<li>열[column] : 속성[attribute], 필드[field]</li>
</ul>
<p>=================================================</p>
<h3 id="1-sql-structured-query-language">1. SQL (Structured Query Language)</h3>
<ul>
<li>터미널에서 데이터베이스를 검색하기 위해 주로 사용되는 독립 언어</li>
<li>SQL은 데이터베이스에서 데이터를 정의, 조작, 제어하기 위해 사용하는 언어</li>
</ul>
<h4 id="-데이터-정의어-ddl--create--alter--drop-table과-관련">* 데이터 정의어 [DDL] : CREATE / ALTER / DROP (Table과 관련)</h4>
<h4 id="-데이터-조작어-dml--select--update--insert-data-조작과-관련">* 데이터 조작어 [DML] : SELECT / UPDATE / INSERT (Data 조작과 관련)</h4>
<h4 id="-데이터-제어어-dcl--grant--revoke--commit--rollback-권한부여해제-트랜젝션-집행-변경-취소-원상복귀-와-관련">* 데이터 제어어 [DCL] : GRANT / REVOKE / COMMIT / ROLLBACK (권한부여/해제, 트랜젝션 집행, 변경 취소 원상복귀 와 관련)</h4>
<hr>
<h3 id="1-db-관리하기">1. DB 관리하기</h3>
<ul>
<li><p>설치한 MySQL의 root 계정으로 접속</p>
<pre><code>  &gt; mysql -u root -p
  &gt; Enter password: ************

  # 혹은 password를 p 뒤에 이어 입력하고 실행할 수도 있음    
  &gt; mysql -u root -p*****</code></pre></li>
<li><p>데이터베이스 목록 확인</p>
<pre><code>SHOW DATABASES;</code></pre></li>
<li><p>데이터베이스 생성</p>
<pre><code>CREATE DATABASE db_name;</code></pre></li>
<li><p>사용하게 되는 데이터베이스 지정 (로그인 후 지정)</p>
<pre><code>USE db_name;</code></pre></li>
<li><p>데이터베이스 삭제</p>
<pre><code>DROP DATABASE db_name;
</code></pre></li>
</ul>
<pre><code>### 2. 사용자 관리
- mysql 데이터베이스 내 user 테이블에서 사용자 정보를 확인</code></pre><p>USE mysql;
SELECT host, user FROM user;</p>
<pre><code>- 사용자 생성</code></pre><h1 id="로컬-pc에서만-접속-가능한-사용자">로컬 PC에서만 접속 가능한 사용자</h1>
<p>CREATE USER &#39;user_name&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;password&#39;;</p>
<h1 id="외부에서-접속-가능한-사용자">외부에서 접속 가능한 사용자</h1>
<p>CREATE USER &#39;user_name&#39;@&#39;%&#39; IDENTIFIED BY &#39;password&#39;;</p>
<pre><code>- 사용자 삭제
접근 범위에 따라 같은 이름의 사용자여도 별도로 삭제해주어야 함</code></pre><p>DROP USER &#39;user_name&#39;@&#39;localhost&#39;
DROP USER &#39;user_name&#39;@&#39;%&#39;</p>
<pre><code>- 사용자에게 특정 데이터베이스의 모든 권한 부여</code></pre><p>GRANT ALL ON db_name.* TO &#39;user_name&#39;@&#39;localhost&#39;
GRANT ALL ON db_name.* TO &#39;user_name&#39;@&#39;%&#39;</p>
<pre><code>- 사용자에게 특정 데이터베이스의 모든 권한을 삭제</code></pre><p>REVOKE ALL ON db_name.* FROM &#39;user_name&#39;@&#39;localhost&#39;
REVOKE ALL ON db_name.* FROM &#39;user_name&#39;@&#39;%&#39;</p>
<pre><code>- 사용자에게 부여된 모든 권한 목록 확인</code></pre><p>SHOW GRANTS FOR &#39;user_name&#39;@&#39;localhost&#39;
SHOW GRANTS FOR &#39;user_name&#39;@&#39;%&#39;</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - 인구 현황 데이터 분석 (catogram 시각화)]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%9D%B8%EA%B5%AC-%ED%98%84%ED%99%A9-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-catogram-%EC%8B%9C%EA%B0%81%ED%99%94</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%9D%B8%EA%B5%AC-%ED%98%84%ED%99%A9-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-catogram-%EC%8B%9C%EA%B0%81%ED%99%94</guid>
            <pubDate>Mon, 18 Mar 2024 13:27:45 GMT</pubDate>
            <description><![CDATA[<h3 id="카토그램">카토그램</h3>
<ul>
<li>지리적 공간을 나타내는 지도에서 지역의 상대적 크기를 표현하는 방식</li>
<li>특정 변수의 값을 반영하여 지역의 크기를 변형하여 나타냄.  (일반적으로 지도에서는 지역의 면적이나 크기가 실제 지리적 크기와 일치)</li>
<li>통계적 혹은 시각적으로 중요한 데이터를 강조하거나 특정 지역 간의 비교를 용이하게 하기 위해 사용</li>
<li>일반적으로 인구, 경제적 측면, 환경적 특성 등과 같은 변수를 나타내는 경우 사용</li>
</ul>
<h3 id="1-인구-소멸-위기-지역-파악">1. 인구 소멸 위기 지역 파악</h3>
<p>(1) 데이터 정제</p>
<pre><code>import numpy as np
import pandas as pd

population = pd.read_excel(&quot;../data/07_population_raw_data.xlsx&quot;)
population.head()</code></pre><p>Excel 데이터 cell 병합으로 인해 컬럼이 2중으로 되어 있음
<img src="https://velog.velcdn.com/images/jj_study/post/610161e7-60ee-4750-b9a2-1d5176341a46/image.png" alt=""></p>
<hr>
<ul>
<li><p>읽어올 때 필요없는 맨 윗줄 (column_level=0)은 제거하고 가져옴  header = 1부터 사용한다는 것임</p>
<pre><code>population = pd.read_excel(&quot;../data/07_population_raw_data.xlsx&quot;, header=1)</code></pre></li>
<li><p>fillna() : NaN 값 채우기</p>
<pre><code>population.fillna(method=&quot;pad&quot;, inplace=True)
population</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/d4c00772-4431-4901-a35d-b456632b3c07/image.png" alt=""></p>
</li>
<li><p>행과 열 편집, 값 변경 등 데이터 정제
<img src="https://velog.velcdn.com/images/jj_study/post/e5553f33-ac2f-43be-ab13-a05d27e79fc9/image.png" alt=""></p>
</li>
</ul>
<hr>
<p>(2) 인구 소멸 위험 지역 조사</p>
<ul>
<li><p>65세 고령 인구 대비 20-39세 여성인구 비중으로 비율이 &lt; 0.5 이면 30년 내 소멸 가능성이 크다고 봄</p>
</li>
<li><p>소멸 위험지수 = (2-19세 여성인구수) / (65세 이상 인구수)</p>
</li>
<li><p>소멸위험지수가  &lt; 0.5 면 인구 소멸 위허 지역으로 구분</p>
</li>
</ul>
<hr>
<ul>
<li><p>20~39세 여성 인구와 65세 이상 인구수를 구하기 위해 나뉘어진 나이 컬럼을 합</p>
<pre><code>  population[&quot;20-39세&quot;] = (
        population[&quot;20 - 24세&quot;] + population[&quot;25 - 29세&quot;]
      + population[&quot;30 - 34세&quot;] + population[&quot;35 - 39세&quot;]
  )

  population[&quot;65세이상&quot;] = (
        population[&quot;65 - 69세&quot;] + population[&quot;70 - 74세&quot;]
      + population[&quot;75 - 79세&quot;] + population[&quot;80 - 84세&quot;]
      + population[&quot;85 - 89세&quot;] + population[&quot;90 - 94세&quot;]
      + population[&quot;95 - 99세&quot;] + population[&quot;100+&quot;]
  )</code></pre></li>
</ul>
<hr>
<ul>
<li>인구 소멸 위험 지역을 조사하기 위해 필요한 컬럼들을 모아 새로운 DataFrame 생성<pre><code>popul_pivot = pd.pivot_table(
        data=population,
        index=[&quot;광역시도&quot;, &quot;시도&quot;],
        columns=[&quot;구분&quot;],
        values=[&quot;인구수&quot;, &quot;20-39세&quot;, &quot;65세이상&quot;]
  )</code></pre></li>
</ul>
<hr>
<ul>
<li>노인 인구 대비 2030 여성 인구 비율 계산<pre><code>popul_pivot[&quot;소멸지수&quot;]
    = popul_pivot[&quot;20-39세&quot;, &quot;여자&quot;] / popul_pivot[&quot;65세이상&quot;, &quot;합계&quot;]</code></pre></li>
</ul>
<hr>
<ul>
<li>&quot;소멸위험지역&quot; 컬럼 만들고 &quot;소멸지수&quot;가 &lt; 0.5 인 지역은 True값 아니면 False<pre><code>popul_pivot[&quot;소멸위기지역&quot;] = popul_pivot[&quot;소멸지수&quot;] &lt; 0.5</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/b3973a67-c755-49f4-82c7-ed9c239fb65b/image.png" alt=""></li>
</ul>
<hr>
<ul>
<li>Multi index와 Multi column을 단일값으로 만들어 줌<pre><code># index 재정렬
popul_pivot.reset_index(inplace=True)
  popul_pivot.head()
</code></pre></li>
</ul>
<h1 id="column-추가">column 추가</h1>
<p>tmp_cols = [
        popul_pivot.columns.get_level_values(0)[n]
        + popul_pivot.columns.get_level_values(1)[n]
        for n in range(len(popul_pivot.columns.get_level_values(0)))
    ]
    popul_pivot.columns = tmp_cols</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/e5b5f235-89eb-4a5b-aaa2-67851607906d/image.png)
---------------------------
(3) 지역별 ID 만들기
- 지도 시각화를 위해 지역별 ID 필요
- 일반 시에 있는 행정구 데이터 정리</code></pre><pre><code>admin_gu = {
    &quot;수원&quot;: [&quot;장안구&quot;, &quot;권선구&quot;, &quot;팔달구&quot;, &quot;영통구&quot;],
    &quot;성남&quot;: [&quot;수정구&quot;, &quot;중원구&quot;, &quot;분당구&quot;],
    &quot;안양&quot;: [&quot;만안구&quot;, &quot;동안구&quot;],
    &quot;안산&quot;: [&quot;상록구&quot;, &quot;단원구&quot;],
    &quot;고양&quot;: [&quot;덕양구&quot;, &quot;일산동구&quot;, &quot;일산서구&quot;],
    &quot;용인&quot;: [&quot;처인구&quot;, &quot;기흥구&quot;, &quot;수지구&quot;],
    &quot;청주&quot;: [&quot;상당구&quot;, &quot;서원구&quot;, &quot;흥덕구&quot;, &quot;청원구&quot;],
    &quot;천안&quot;: [&quot;동남구&quot;, &quot;서북구&quot;],
    &quot;전주&quot;: [&quot;완산구&quot;, &quot;덕진구&quot;],
    &quot;포항&quot;: [&quot;남구&quot;, &quot;북구&quot;],
    &quot;창원&quot;: [&quot;의창구&quot;, &quot;성산구&quot;, &quot;진해구&quot;, &quot;마산합포구&quot;, &quot;마산회원구&quot;],
    &quot;부천&quot;: [&quot;오정구&quot;, &quot;원미구&quot;, &quot;소사구&quot;],
}</code></pre><pre><code>- 일반 시
    - 일반 도에 포함된 일반 시나 군의 지역 ID는 &quot;시&quot;를 뺀 지역명으로 함
    - row[&quot;시도&quot;][:-1] --&gt; 마지막 한 글자를 제외한 전체 (ex. &#39;강릉시&#39; --&gt; &#39;강릉&#39;, &#39;옥천군&#39; --&gt; &#39;옥천&#39;)
    - 고성군은 강원도와 경상남도에 동일한 이름으로 존재하므로 구분해 줄 것. (ex. 강원도 &#39;고성군&#39; --&gt; &#39;고성(강원)&#39;, 경상남도 &#39;고성군&#39; --&gt; &#39;고성(경남)&#39;)
- 세종특별자치시는 유일함

- 일반 구
    - 특별시, 광역시의 구는 해당 시의 앞 두글자[:2]와 구 이름을 합침
    - 구 이름이 세글자 이상이면 &#39;구&#39;를 제외한 글자[:-1]를 합침

- 행정구
    - 일반시(12개)의 행정구도 해상 시의 앞 두글자와 구이름을 합침
    - 구 이름이 세글자 이상이면 &#39;구&#39;를 제외한 글자[:-1]만 합침
</code></pre><p>  def find_key_by_value(dictionary, value):
      for key, val in dictionary.items():
          if value in val:
              return key
      return None  // 값이 없는 경우</p>
<p>  for idx, row in popul_pivot[[&quot;광역시도&quot;, &quot;시도&quot;]].iterrows():
      if row[&quot;광역시도&quot;][-3:] not in [&quot;광역시&quot;, &quot;특별시&quot;, &quot;자치시&quot;]:
          # 행정구
          if row[&quot;시도&quot;][-1:] == &quot;구&quot;:
              key = find_key_by_value(admin_gu, row[&quot;시도&quot;])<br>              if len(key) &gt; 0:
                  if len(row[&quot;시도&quot;]) == 2:
                      sidoID[idx] = key + &quot; &quot; + row[&quot;시도&quot;]<br>                  elif row[&quot;시도&quot;] in [&quot;마산합포구&quot;, &quot;마산회원구&quot;]:
                      sidoID[idx] = key + &quot; &quot; + row[&quot;시도&quot;][2:-1]<br>                  else:
                      sidoID[idx] = key + &quot; &quot; + row[&quot;시도&quot;][:-1]
          # 고성군
          elif row[&quot;시도&quot;] == &quot;고성군&quot;:
              if row[&quot;광역시도&quot;] == &quot;강원도&quot;:
                  sidoID[idx] = &quot;고성(강원)&quot;
              else: sidoID[idx] = &quot;고성(경남)&quot;
          # 일반시
          else:
              sidoID[idx] = row[&quot;시도&quot;][:-1]</p>
<pre><code>  # 세종특별자치시
  elif row[&quot;광역시도&quot;] == &quot;세종특별자치시&quot;:
      sidoID[idx] = &quot;세종&quot;

  # 특별시/광역시 구
  else:
      if len(row[&quot;시도&quot;]) == 2: // 서구, 중구, 북구, ...
          sidoID[idx] = row[&quot;광역시도&quot;][:2] + &quot; &quot; + row[&quot;시도&quot;]
      else:
          sidoID[idx] = row[&quot;광역시도&quot;][:2] + &quot; &quot; + row[&quot;시도&quot;][:-1]</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/a4094f87-0d89-4278-be3e-9000f6ff01c1/image.png)
=======================
### 2. 카토그램 시각화</code></pre><h1 id="한글화-작업">한글화 작업</h1>
<pre><code>import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import set_matplotlib_hangul
import warnings
warnings.filterwarnings(action=&quot;ignore&quot;)
%matplotlib inline</code></pre><pre><code>(1) 카토그램 구조 
- Excel로 만든 카토그램 큰 구조 읽기</code></pre><p>draw_korea_raw = pd.read_excel(&quot;../data/07_draw_korea_raw.xlsx&quot;)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/dcc65789-c16b-47b7-8e5b-3e03e7c098eb/image.png)

(2) 시각화할 좌표 값 지정</code></pre><pre><code>BORDER_LINES = [
    [(5, 1), (5, 2), (7, 2), (7, 3), (11, 3), (11, 0)], # 인천
    [(5, 4), (5, 5), (2, 5), (2, 7), (4, 7), (4, 9), (7, 9),
     (7, 7), (9, 7), (9, 5), (10, 5), (10, 4), (5, 4)], # 서울
    [(1, 7), (1, 8), (3, 8), (3, 10), (10, 10), (10, 7),
     (12, 7), (12, 6), (11, 6), (11, 5), (12, 5), (12, 4),
     (11, 4), (11, 3)], # 경기도
    [(8, 10), (8, 11), (6, 11), (6, 12)], # 강원도
    [(12, 5), (13, 5), (13, 4), (14, 4), (14, 5),
     (15, 5), (15, 4), (16, 4), (16, 2)], # 충청북도
    [(16, 4), (17, 4), (17, 5), (16, 5), (16, 6), (19, 6), (19, 5),
     (20, 5), (20, 4), (21, 4), (21, 3), (19, 3), (19, 1)], # 전북
    [(13, 5), (13, 6), (16, 6)], # 대전시
    [(13, 5), (14, 5)], # 세종시
    [(21, 2), (21, 3), (22, 3), (22, 4), (24, 4), (24, 2), (21, 2)], # 광주
    [(20, 5), (21, 5), (21, 6), (23, 6)], # 전남
    [(10, 8), (12, 8), (12, 9), (14, 9), (14, 8), (16, 8), (16, 6)], # 충북
    [(14, 9), (14, 11), (14, 12), (13, 12), (13, 13)], # 경북
    [(15, 8), (17, 8), (17, 10), (16, 10), (16, 11), (14, 11)], # 대구
    [(17, 9), (18, 9), (18, 8), (19, 8), (19, 9),
     (20, 9), (20, 10), (21, 10)], # 부산
    [(16, 11), (16, 13)], # 울산
    [(27, 5), (27, 6), (25, 6)] # 제주도
]</code></pre><pre><code>- stack()
Excel에 그려진 각 행정구역 별 위치 좌표 얻어 옴</code></pre><p>draw_kr_carto = pd.DataFrame(draw_korea_raw.stack())
    draw_kr_carto.reset_index(inplace=True)
    draw_kr_carto.rename(
        columns={&quot;level_0&quot;: &quot;y&quot;, &quot;level_1&quot;: &quot;x&quot;, 0: &quot;ID&quot;},
          inplace=True
    )</p>
<pre><code>(3) Sample 카토그램
![](https://velog.velcdn.com/images/jj_study/post/f1ad31a1-4c63-4832-a5d3-1e1cee6e640e/image.png)

(4) 데이터 병합
![](https://velog.velcdn.com/images/jj_study/post/38b41fc7-94d1-4ff6-b7a9-23eec3206474/image.png)

- 인구 데이터와 Cartogram 좌표 데이터를 병합하기 전 검정 </code></pre><pre><code>set(draw_kr_carto[&quot;ID&quot;].unique()) - set(population[&quot;ID&quot;].unique())
//==&gt; set()

tmp_list = list(
  set(population[&quot;ID&quot;].unique()) - set(draw_kr_carto[&quot;ID&quot;].unique())
)
#==&gt; [&#39;수원&#39;, &#39;전주&#39;, &#39;청주&#39;, &#39;천안&#39;, &#39;성남&#39;, &#39;부천&#39;,
#     &#39;고양&#39;, &#39;포항&#39;, &#39;안양&#39;, &#39;용인&#39;, &#39;창원&#39;, &#39;안산&#39;]

for item in tmp_list:
    population.drop(
        population[population[&quot;ID&quot;] == item].index,
        inplace=True
    )

set(population[&quot;ID&quot;].unique()) - set(draw_kr_carto[&quot;ID&quot;].unique())
//==&gt; set()</code></pre><pre><code>- 두 DataFrame을  ID 기준으로 병합</code></pre><p>population = pd.merge(
          population, draw_kr_carto, how=&quot;left&quot;, on=&quot;ID&quot;
    )</p>
<pre><code>(5) 카토그램 그리기
- blockedMap : 인구현황 (population)
- targetData : population에서 그리고 싶은 컬럼</code></pre><p>  def get_data_info(targetData, blockedMap):
      vmin = min(blockedMap[targetData])
      vmax = max(blockedMap[targetData])<br>      white_label_min = (vmax - vmin) * 0.25 + vmin<br>      map_data = blockedMap.pivot_table(
            index=&quot;y&quot;, columns=&quot;x&quot;, values=targetData
      )<br>      return map_data, vmin, vmax, white_label_min</p>
<pre><code></code></pre><p>  def get_data_info_for_zero_center(targetData, blockedMap):
      white_label_min = 5<br>      tmp_max = max(
          [np.abs(min(blockedMap[targetData])),
           np.abs(max(blockedMap[targetData]))]
      )
      vmin, vmax = -tmp_max, tmp_max<br>      map_data = blockedMap.pivot_table(
          index=&quot;y&quot;, columns=&quot;x&quot;, values=targetData
      )<br>      return map_data, vmin, vmax, white_label_min</p>
<pre><code></code></pre><p>  def plot_text(targetData, blockedMap, white_label_min):<br>      for idx, row in blockedMap.iterrows():<br>          if len(row[&quot;ID&quot;].split()) == 2:
              dispname = &quot;{}\n{}&quot;.format(
                  row[&quot;ID&quot;].split()[0], row[&quot;ID&quot;].split()[1]
              )
          elif row[&quot;ID&quot;][:2] == &quot;고성&quot;:
              dispname = &quot;고성&quot;
          else:
              dispname = row[&quot;ID&quot;]</p>
<pre><code>      if len(dispname.splitlines()[-1]) &gt;= 3:
          fontsize, linespacing = 9.5, 1.5 
      else:
          fontsize, linespacing = 11, 1.2

      annocolor = &quot;white&quot; if np.abs(row[targetData]) &gt; white_label_min else &quot;black&quot;

      plt.annotate(
          dispname,
          (row[&quot;x&quot;] + 0.5, row[&quot;y&quot;] + 0.5), # 글자가 중앙에 위치
          weight=&quot;bold&quot;,
          color=annocolor,
          fontsize=fontsize,
          linespacing=linespacing,
          ha=&quot;center&quot;, # 수평 정렬
          va=&quot;center&quot;, # 수직 정렬 
      )</code></pre><pre><code></code></pre><p>  def drawKoreaCartogram(targetData, blockedMap, cmapName, zeroCenter=False):
      if zeroCenter:
          masked_mapdata, vmin, vmax, white_label_min
              = get_data_info_for_zero_center(targetData, blockedMap)
      else:
          masked_mapdata, vmin, vmax, white_label_min
              = get_data_info(targetData, blockedMap)</p>
<pre><code>  plt.figure(figsize=(9, 11))
  plt.pcolor(
      masked_mapdata,
      vmin=vmin,
      vmax=vmax,
      cmap=cmapName,
      edgecolor=&quot;#aaaaaa&quot;,
      linewidth=0.5
  )    
  plot_text(targetData, blockedMap, white_label_min)

  for coord in BORDER_LINES:
      ys, xs = zip(*coord)
      plt.plot(xs, ys, c=&quot;black&quot;, lw=1.5)        

  plt.gca().invert_yaxis()
  plt.axis(&quot;off&quot;)
  plt.tight_layout()

  cb = plt.colorbar(shrink=0.1, aspect=10)
  cb.set_label(targetData)

  plt.show()</code></pre><pre><code>(6) 인구수 합계</code></pre><p>drawKoreaCartogram(
        targetData=&quot;인구수합계&quot;, blockedMap=population, cmapName=&quot;Blues&quot;
    )</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/71538a80-76fc-4732-8e40-4d97fb6d09a6/image.png)

(7) 소멸 위기 지역</code></pre><p>population[&quot;소멸위기지역&quot;] = [
        1 if val else 0 for val in population[&quot;소멸위기지역&quot;]
    ]
    drawKoreaCartogram(&quot;소멸위기지역&quot;, population, &quot;Reds&quot;)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/6cadc74f-1319-4831-8b95-046b0760bcbf/image.png)

### 3. 지도 시각화</code></pre><p>import pandas as pd
import folium
import json</p>
<p>geo_path = &quot;../data/07_skorea_municipalities_geo_simple.json&quot;
geo_json = json.load(open(geo_path, encoding=&quot;utf-8&quot;))</p>
<pre><code>(1) 인구수 합계</code></pre><pre><code>popmap = folium.Map(location=[36.3002, 127.554], zoom_start=7)

folium.Choropleth(
        geo_data=geo_json,
        data=popul_folium[&quot;인구수합계&quot;],
        key_on=&quot;feature.id&quot;,
        columns=[popul_folium.index, popul_folium[&quot;인구수합계&quot;]],
        fill_color=&quot;YlGnBu&quot;
).add_to(popmap)

popmap</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/0613ae75-9c3a-48e8-a4d7-1c81b5578ceb/image.png)

(2) 소멸 위기 지역</code></pre><pre><code>popmap = folium.Map(location=[36.3002, 127.554], zoom_start=7)

folium.Choropleth(
        geo_data=geo_json,
        data=popul_folium[&quot;인구수합계&quot;],
        key_on=&quot;feature.id&quot;,
        columns=[popul_folium.index, popul_folium[&quot;인구수합계&quot;]],
        fill_color=&quot;YlGnBu&quot;
).add_to(popmap)

popmap</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/c1d03fe0-6c61-4eba-b622-591b8df6ac94/image.png)

### 4. Cartogram / 지도
![](https://velog.velcdn.com/images/jj_study/post/b230cc25-1416-4b9b-9e2e-65be63ca5351/image.png)

![](https://velog.velcdn.com/images/jj_study/post/bb1c2ad6-0543-47bc-be80-eee994e048a4/image.png)

</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - 네이버 쇼핑 검색 API]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%84%A4%EC%9D%B4%EB%B2%84-%EC%87%BC%ED%95%91-%EA%B2%80%EC%83%89-API</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%84%A4%EC%9D%B4%EB%B2%84-%EC%87%BC%ED%95%91-%EA%B2%80%EC%83%89-API</guid>
            <pubDate>Mon, 18 Mar 2024 12:42:22 GMT</pubDate>
            <description><![CDATA[<h3 id="상품-몰스킨-검색-쇼핑-정보-취득과정">상품 &quot;몰스킨&quot; 검색, 쇼핑 정보 취득과정</h3>
<h3 id="1-gen_search_url">1. gen_search_url()</h3>
<ul>
<li>검색 요청 URL 생성하는 함수</li>
<li>파라미터들을 URL에 포함시켜야 함</li>
<li>한번에 표시될 수 있는 검색 결과(display)의 최대 수 - 100개</li>
<li>만약 1000개의 데이터 얻고자 하면 start 파라미터 이용해 시작갑 start = 1, start = 101,..., start = 901 방식으로 분리해 지정</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jj_study/post/c8b2e1b9-c137-48f7-b364-ee060242c5ec/image.png" alt=""></p>
<pre><code>   import urllib

    def gen_search_url(api_node, search_text, start_num, disp_num):
        base = &quot;https://openapi.naver.com/v1/search&quot;
        node = &quot;/&quot; + api_node + &quot;.json&quot;
        param_query = &quot;?query=&quot; + urllib.parse.quote(search_text)
        param_start = &quot;&amp;start=&quot; + str(start_num)
        param_disp = &quot;&amp;display=&quot; + str(disp_num)

        return base + node + param_query + param_start + param_disp

    gen_search_url(&quot;shop&quot;, &quot;Test&quot;, 10, 3)
    // &#39;https://openapi.naver.com/v1/search/shop.json?query=Test&amp;start=10&amp;display=3&#39;</code></pre><h3 id="get_result_onepage">get_result_onepage()</h3>
<ul>
<li><p>url로 웹에 접근해 내용을 json으로 가져와 글자로 decode 해 줌</p>
<pre><code>  import json
  import datetime
  from urllib.request import Request, urlopen

  def get_result_onepage(url):
      client_id = &quot;*************&quot;
      client_secret = &quot;******&quot;

      request = Request(url)
      request.add_header(&quot;X-Naver-Client-Id&quot;, client_id)
      request.add_header(&quot;X-Naver-Client-Secret&quot;, client_secret)

      response = urlopen(request)
      print(&quot;[%s] URL Request Success&quot; % datetime.datetime.now())
      return json.loads(response.read().decode(&quot;utf-8&quot;))
  url = gen_search_url(&quot;shop&quot;, &quot;몰스킨&quot;, 1, 5)
  one_result = get_result_onepage(url)

  one_result</code></pre><p>&lt;결과&gt;</p>
</li>
</ul>
<h3 id="3-get_fields">3. get_fields()</h3>
<ul>
<li><p>검색 정보를 pandas DataFrame으로 만듬</p>
<pre><code>  import pandas as pd

  def get_fields(json_data):
      title = [each[&quot;title&quot;] for each in json_data[&quot;items&quot;]]
      link = [each[&quot;link&quot;] for each in json_data[&quot;items&quot;]]
      lprice = [each[&quot;lprice&quot;] for each in json_data[&quot;items&quot;]]
      mall_name = [each[&quot;mallName&quot;] for each in json_data[&quot;items&quot;]]

      # title / lprice / link / mall이 디스플레이됨
      result_df = pd.DataFrame({
          &quot;title&quot;: title,
          &quot;lprice&quot;: lprice,
          &quot;link&quot;: link,
          &quot;mall&quot;: mall_name,
      })
      return result_df

  get_fields(one_result)</code></pre><h3 id="4-delete_tag">4. delete_tag()</h3>
<p>title 부분 텍스트에 붙어 있는 <b> 태그 제거</p>
<pre><code>  def delete_tag(input_str):
      input_str = input_str.replace(&quot;&lt;b&gt;&quot;, &quot;&quot;)
      input_str = input_str.replace(&quot;&lt;/b&gt;&quot;, &quot;&quot;)
      return input_str
  import pandas as pd

  def get_fields(json_data):
      title = [delete_tag(each[&quot;title&quot;]) for each in json_data[&quot;items&quot;]]
      link = [each[&quot;link&quot;] for each in json_data[&quot;items&quot;]]
      lprice = [each[&quot;lprice&quot;] for each in json_data[&quot;items&quot;]]
      mall_name = [each[&quot;mallName&quot;] for each in json_data[&quot;items&quot;]]

      result_df = pd.DataFrame({
          &quot;title&quot;: title,
          &quot;lprice&quot;: lprice,
          &quot;link&quot;: link,
          &quot;mall&quot;: mall_name,
      })
      return result_df

  get_fields(one_result)</code></pre><h3 id="5-actmain">5. actMain()</h3>
<p>지금까지 과정을 통해 1000개의 데이터를 모두 모음</p>
<pre><code>  def actMain(api_node, search_text):
      total_result = []
      # 1부터 1000까지 100개씩
      for n in range(1, 1000, 100):
          url = gen_search_url(api_node, search_text, n, 100)
          json_result = get_result_onepage(url)
          df_result = get_fields(json_result)

          total_result.append(df_result)

      total_result = pd.concat(total_result)
      return total_result
  result_molskin = actMain(&quot;shop&quot;, &quot;몰스킨&quot;)
result_molskin</code></pre><h3 id="6-excel로-저장">6. EXCEL로 저장</h3>
</li>
<li><p>파이썬으로 엑셀을 다루는 xlsxwriter 모듈 이용해 데이터 저장</p>
<pre><code>  writer = pd.ExcelWriter(
      &quot;./result_data/06_molskin_diary_in_naver_shop.xlsx&quot;,
      engine=&quot;xlsxwriter&quot;
  )
  result_molskin.to_excel(writer, sheet_name=&quot;Sheet1&quot;)

  workbook = writer.book 
  worksheet = writer.sheets[&quot;Sheet1&quot;]
  worksheet.set_column(&quot;A:A&quot;, 4)
  worksheet.set_column(&quot;B:B&quot;, 70)
  worksheet.set_column(&quot;C:C&quot;, 10)
  worksheet.set_column(&quot;D:D&quot;, 50)
  worksheet.set_column(&quot;E:E&quot;, 30)
  worksheet.set_column(&quot;F:F&quot;, 10)

  worksheet.conditional_format(&quot;C2:C1001&quot;, {&quot;type&quot;: &quot;3_color_scale&quot;})
  writer.close()</code></pre><h3 id="7-시각화">7. 시각화</h3>
</li>
<li><p>몰스킨 제품이 팔리는 쇼핑몰 별로 보여줌</p>
<pre><code>  plt.figure(figsize=(15, 7))
  sns.countplot(
      data=result_molskin,
      x=result_molskin[&quot;mall&quot;],
      palette=&quot;RdYlGn&quot;,
      order=result_molskin[&quot;mall&quot;].value_counts().index
  )
  plt.xticks(rotation=90)
  plt.show()</code></pre></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[네이버 검색 API 사용하기]]></title>
            <link>https://velog.io/@jj_study/%EB%84%A4%EC%9D%B4%EB%B2%84-%EA%B2%80%EC%83%89-API-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jj_study/%EB%84%A4%EC%9D%B4%EB%B2%84-%EA%B2%80%EC%83%89-API-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 18 Mar 2024 11:56:09 GMT</pubDate>
            <description><![CDATA[<h3 id="1-네이버-api-사용-등록">1. 네이버 API 사용 등록</h3>
<ul>
<li>네이버 개발자 센터
<a href="https://developers.naver.com/main/">https://developers.naver.com/main/</a></li>
<li>Application<ul>
<li>애플리케이션 등록</li>
<li>애플리케이션 이름 ds_study</li>
<li>사용 API<ul>
<li>검색</li>
<li>데이터랩 (검색어 트랜드)</li>
<li>데이터랩 (쇼핑인사이트)</li>
</ul>
</li>
<li>환경추가<ul>
<li>WEB설정</li>
<li><a href="http://localhost">http://localhost</a></li>
</ul>
</li>
<li>Client ID : 본인 소유</li>
<li>Client Secret : 본인 소유
<a href="https://developers.naver.com/apps/#/myapps/EsB6wpVn9dhqFyierBQi/overview">https://developers.naver.com/apps/#/myapps/EsB6wpVn9dhqFyierBQi/overview</a></li>
</ul>
</li>
</ul>
<h3 id="2-네이버-검색-api-사용">2. 네이버 검색 API 사용</h3>
<p>네이버 검색 open API 예제 - 블로그 검색
<PYTHON>
<a href="https://developers.naver.com/docs/serviceapi/search/blog/blog.md#python">https://developers.naver.com/docs/serviceapi/search/blog/blog.md#python</a></p>
<ul>
<li><p>urllib : http 프로토콜에 따라서 서버의 요청/응답을 처리하기 위한 모듈</p>
</li>
<li><p>urllib.request : 웹서버에 웹페이지 요청하고 응답받기 위해 일반적으로ㅗ 브라우저 사용.  클라이언트의 요청을 처리하는 모듈</p>
</li>
<li><p>urllib.response : 서버의 응답을 처리</p>
</li>
<li><p>urllib.parse : URL 주소에 대한 분석</p>
<pre><code>import os
import sys
import urllib.request

client_id = &quot;My_Client_ID&quot;
client_secret = &quot;My_Client_SECRET&quot;

# request url 생성
# 한글을 URL에 추가하기 위해서  UTF-8 형식으로 URL인코딩
encText = urllib.parse.quote(&quot;파이썬&quot;)
# JSON 요청 URL (여기서/search/blog?query  하면 blog,  책이면 book, 카페면 cafe, 쇼핑이면 shopping, 백과사전이면 encyc 대체해서 넣기)
url = &quot;https://openapi.naver.com/v1/search/blog?query=&quot; + encText
# encText에 이어 + &quot;&amp;display=3&amp;sort=count&quot; 를 붙여 (따옴표 포함  요청 URL + 요청 변수 보여주기.  naver api사이트에서 확인가능)
# XML 요청 URL  (여기서/search/blog?query  하면 blog,  책이면 book, 카페면 cafe, 쇼핑이면 shopping, 백과사전이면 encyc 대체해서 넣기)
 url = &quot;https://openapi.naver.com/v1/search/blog.xml?query=&quot; + encText

# REQUEST 객체 (URL요청과 관련된 정보를 담는 추상화된 클래스) 생성 및 Header 추가.  add_header 메소드로 헤더정보 추가.  네이버 API 사용하려면 클라이언트 정보를 헤더에 포함시켜야 함
request = urllib.request.Request(url)
request.add_header(&quot;X-Naver-Client-Id&quot;,client_id)
request.add_header(&quot;X-Naver-Client-Secret&quot;,client_secret)

# urlopen 및 response 획득 (url string 혹은 request객체를 전달 받음.  header 정보 포함한 request 객체 전달)
response = urllib.request.urlopen(request)
rescode = response.getcode() # response의 HTTP status code를 리턴

# HTTP status code 확인 및 response 데이터 디코딩
# getcode 메서드 통해 response의  HTTP status code 확인
if(rescode==200):
    response_body = response.read()
    print(response_body.decode(&#39;utf-8&#39;)) 
else: # 네이버 오픈 API 에러 코드 목록
      print(&quot;Error Code:&quot; + rescode)</code></pre><ul>
<li>다른 카테고리 검색시 위에서 url만 바꿀것
예)  책 : book
 카페 : cafe
 쇼핑 : shop
 백과사정 : encyc
url = &quot;<a href="https://openapi.naver.com/v1/search/">https://openapi.naver.com/v1/search/</a>&lt;검색카테고리&gt;?query=&quot; + encText</li>
</ul>
</li>
</ul>
<pre><code>https://developers.naver.com/docs/serviceapi/search/book/book.md</code></pre><ul>
<li>JSON 형식의 결과 데이터는 json.loads() 메소드로 파이썬에서 활용 가능한 객체 (예: dict)로 변환하여 사용함<pre><code>import json
json_rt = response.read().decode(&#39;utf-8&#39;)
py_rt = json.loads(json_rt)</code></pre>==========================================</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - 시계열 데이터 웹 유입량 데이터 분석]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%8B%9C%EA%B3%84%EC%97%B4-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9B%B9-%EC%9C%A0%EC%9E%85%EB%9F%89-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%8B%9C%EA%B3%84%EC%97%B4-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9B%B9-%EC%9C%A0%EC%9E%85%EB%9F%89-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D</guid>
            <pubDate>Mon, 18 Mar 2024 08:20:06 GMT</pubDate>
            <description><![CDATA[<h3 id="1-prophet-이용한-1년치-웹-유입량-데이터-분석-pinkwink-블로그">1. Prophet 이용한 1년치 웹 유입량 데이터 분석 (pinkwink 블로그)</h3>
<pre><code>     import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from prophet import Prophet

    %matplotlib inline</code></pre><p>(1) 데이터 읽어오기
    * 데이터 읽어온 후 Nan 값 제거</p>
<pre><code> pinkwink_web = pd.read_csv(
        &quot;../data/05_PinkWink_Web_Traffic.csv&quot;,
        encoding=&quot;utf-8&quot;,
        thousands=&quot;,&quot;,
        names=[&quot;date&quot;, &quot;hit&quot;],
        index_col=0
    )
    pinkwink_web

    pinkwink_web = pinkwink_web[pinkwink_web[&quot;hit&quot;].notnull()]</code></pre><ul>
<li>전체 데이터 시각화<pre><code>pinkwink_web[&quot;hit&quot;].plot(figsize=(12, 4), grid=True);</code></pre></li>
</ul>
<p>(2) 경향분석 (Numpy 이용) 
    - Numpy 이용 경향성 분석 (trend)
    - 다항식 회귀(Polynomial Regression) 모델을 사용.  다항식 함수 사용하여 데이터 근사하는 회귀 모델<br>    <img src="https://velog.velcdn.com/images/jj_study/post/405100c5-b510-4141-902b-b42c1e306019/image.png" alt="">
`
        (x, y 값 형성)
        - x값은 0부터 pinkwink_web 데이터 길이까지 365개의 값
        ```
        time = np.arange(0, len(pinkwink_web))</p>
<pre><code>        - y축은 PinkWink 블로그의 일일 유입량
        ```
    traffic = pinkwink_web[&quot;hit&quot;].values</code></pre><p>(회귀함수 생성)</p>
<ul>
<li><p>TREND 파악을 위한 다항식 회귀함수 생성</p>
<ul>
<li><p>np.polyfit() : 데이터에 적합한 다항식의 계수 구함</p>
</li>
<li><p>np.poly1d() : 계수 적용한 다항식 생성</p>
</li>
<li><p>다항식은 1차, 2차, 3차, 15차 함수까지 4개 생성
``
pf1 = np.polyfit(time, traffic, 1)
f1 = np.poly1d(pf1)</p>
<p>pf2 = np.polyfit(time, traffic, 2)
f2 = np.poly1d(pf2)</p>
<p>pf3 = np.polyfit(time, traffic, 3)
f3 = np.poly1d(pf3)</p>
<p>pf15 = np.polyfit(time, traffic, 15)
f15 = np.poly1d(pf15)</p>
<pre><code></code></pre><p>(경향성과 데이터 비교)</p>
</li>
</ul>
</li>
<li><p>numpy로 만든 4종류의 trend 함수들과 실제 데이터를 그래프로 확인</p>
<ul>
<li>np.polyfit() : 데이터에 적합한 다항식의 계수 구함</li>
<li>np.poly1d() : 계수 적용한 다항식 생성</li>
<li>다항식은 1차, 2차, 3차, 15차 함수까지 4개 생성<br><img src="https://velog.velcdn.com/images/jj_study/post/3132317c-19f4-40ec-8858-c30e1be497ad/image.png" alt=""></li>
</ul>
</li>
</ul>
<p>실제 데이터에 가장 맞는 경향성을 보이는 것은f15로 보임</p>
<p>(3) 오차 검증 (RMSE: rmse average: 제곱근오차평균) 
    *-- 경향성 모델의 정확성 확인 지표 (RMSE: rmse average: 제곱근오차평균)
    *-- Numpy로 계산한 경향성과 실제 데이터의 오차가 얼마인지 확인해줄 error함수 생성</p>
<pre><code>    def error(f, x, y):
    return np.sqrt(np.mean((f(x) - y) ** 2))

    print(error(f1, time, traffic))
    print(error(f2, time, traffic))
    print(error(f3, time, traffic))
    print(error(f15, time, traffic))
    --&gt; 430.85973081109626
    --&gt; 430.6284101894695
    --&gt; 429.5328046676293
    --&gt; 330.47773079342267</code></pre><p>error() 함수로 검증한 결과도 f15가 가장 작음</p>
<p>(4) Prophet이용한 경향 분석 및 미래 데이터 예측<br>    *-- 데이터 생성 (Phrophet에 학습시킬 DataFrame 형식 - 웹 유입량 데이터 변형시킴)   </p>
<pre><code>    df = pd.DataFrame({
            &quot;ds&quot;: pinkwink_web.index,
            &quot;y&quot;: pinkwink_web[&quot;hit&quot;]
         })
    df.reset_index(inplace=True)
    del df[&quot;date&quot;]
    df[&quot;ds&quot;] = pd.to_datetime(df[&quot;ds&quot;], format=&quot;%y. %m. %d.&quot;)</code></pre><p>*-- 미래값 예측 (Phrophet으로 모델 생성 후 학습시킨 후 미래 예측값 얻어옴)</p>
<pre><code>    model = Prophet(yearly_seasonality=True, daily_seasonality=True)
    model.fit(df);

    future = model.make_future_dataframe(periods=60)
    forecast = model.predict(future)
    forecast[[&quot;ds&quot;, &quot;yhat&quot;, &quot;yhat_lower&quot;, &quot;yhat_upper&quot;]].tail()</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/368a985d-6cfb-469f-b6d0-0073748162a8/image.png" alt="">
*-- 예측값 시각화</p>
<pre><code>model.plot(forecast);</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/a9afc758-86ef-40d0-9e9f-c3396779fba0/image.png" alt=""></p>
<p>*-- 경향분석 (미래 예측 데이터 포함 경향 분석)</p>
<pre><code>model.plot_components(forecast);</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/9eada010-bfba-4cf7-992c-1b9c9befc906/image.png" alt="">
<img src="https://velog.velcdn.com/images/jj_study/post/0c3654c1-3352-4eae-8d01-86afa565a46e/image.png" alt=""></p>
<p>*-- 오차 검증 (제곱근 오차 평균)</p>
<pre><code>    np.sqrt(np.mean((forecast[&quot;trend&quot;]-df[&quot;y&quot;])**2))
    //--&gt; 536.0321309635455</code></pre><p>Prophet이 분석한 경향은 실제 데이터 분포와 상당한 오차 존재하는 편</p>
<h3 id="2-종합분석">2. 종합분석</h3>
<ul>
<li><p>실제 데이터 vs. Numpy로 계산한 trend vs. Prophet으로 예측한 trend </p>
<pre><code>  plt.figure(figsize=(14, 6))

  plt.scatter(time, traffic, s=10)
  plt.plot(fx, f1(fx), lw=4, label=&#39;Numpy Trend&#39;)
  ptrend = forecast.loc[:364, &quot;trend&quot;].values
  plt.plot(time, ptrend, lw=4, label=&#39;Prophet Trend&#39;)

  plt.grid(True, linestyle=&quot;-&quot;, color=&quot;0.75&quot;)
  plt.legend(loc=2)
  plt.show()</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/144ae0ef-6235-4bc7-a7d8-0811e634a165/image.png" alt="">
Prophet이 분석한 경향보다 Numpy로 계산한 경향이 실제 데이터 추세와 더 잘 맞아 보임</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - OIL PRICE분석]]></title>
            <link>https://velog.io/@jj_study/%EC%8B%A4%EC%8A%B5-OIL-PRICE%EB%B6%84%EC%84%9D</link>
            <guid>https://velog.io/@jj_study/%EC%8B%A4%EC%8A%B5-OIL-PRICE%EB%B6%84%EC%84%9D</guid>
            <pubDate>Mon, 18 Mar 2024 06:31:45 GMT</pubDate>
            <description><![CDATA[<p>유가 (OIL PRICE) 분석 - 셀프 주유소가 저렴한가?</p>
<ul>
<li>대한민국 주유가격 알아보는 사이트 오피넷 (OPINET)</li>
</ul>
<h3 id="1-분석-데이터-웹-스크랩핑">1. 분석 데이터 웹 스크랩핑</h3>
<ul>
<li>웹 데이터 가져오기
  (1) Selenium으로 Chrome 제어창 열기<pre><code>from selenium import webdriver
from selenium.webdriver.chrome.service import Service
</code></pre></li>
</ul>
<p>chrome_driver_path = &quot;../driver/chromedriver.exe&quot;
service = Service(executable_path = chrome_driver_path)
options = webdriver.ChromeOptions()</p>
<p>driver = webdriver.Chrome(options = options, service = service)</p>
<pre><code>     - Opiniet 에서 싼 주유소 찾기 / 지역별 페이지로 접근</code></pre><p>url = &quot;<a href="https://www.opinet.co.kr/searRgSelect.do&quot;">https://www.opinet.co.kr/searRgSelect.do&quot;</a>
driver.get(url)</p>
<pre><code>- __
    (2) id = &quot;SIDO_NM0&quot; 아이디 속성으로 접근 / 지역 / 시도/데이터 입력하기
![](https://velog.velcdn.com/images/jj_study/post/001bc723-a6e3-4751-a1df-86152d2dc0f9/image.png)
</code></pre><p> 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;)
    sido_names = [option.get_attribute(&quot;value&quot;) for option in sido_list]
    sido_names[:5] // [&#39;&#39;, &#39;서울특별시&#39;, &#39;부산광역시&#39;, &#39;대구광역시&#39;, &#39;인천광역시&#39;]
    del sido_names[0]</p>
<pre><code>sido_list_raw.send_keys(sido_names[0]) // &#39;서울&#39; 입력</code></pre><pre><code>- __
    (3) id = &quot;SIGUNGU_NM0&quot; 아이디 속성으로 접근해서 25개의 구 데이터 가져오기</code></pre><h1 id="부모-태그-select-tag">부모 태그: <select> tag</h1>
<pre><code>gu_list_raw = driver.find_element(By.ID, &quot;SIGUNGU_NM0&quot;)</code></pre><h1 id="자식-태그-option-tag">자식 태그: <option> tag</h1>
<pre><code>gu_list = gu_list_raw.find_elements(By.TAG_NAME, &quot;option&quot;)</code></pre><h1 id="태그-속성값-option-tag의-value-값">태그 속성값: <option> tag의 value= 값</h1>
<pre><code>gu_names = [option.get_attribute(&quot;value&quot;) for option in gu_list]

del gu_names[0]
gu_names[:5], len(gu_names)
// ([&#39;강남구&#39;, &#39;강동구&#39;, &#39;강북구&#39;, &#39;강서구&#39;, &#39;관악구&#39;], 25)</code></pre><pre><code>- 데이터를 EXCEL로 저장
    (1) 엑셀 저장 버튼 클릭 (메뉴 아래)
![](https://velog.velcdn.com/images/jj_study/post/02f6e3b1-4349-4f3d-b64b-5a029b2d1179/image.png)</code></pre><p>driver.find_element(By.CSS_SELECTOR, &quot;#glopopd_excel&quot;).click()</p>
<pre><code>- 
`
    (2) 25개의 구별 주유소 정보 엑셀 저장</code></pre><pre><code>import time
from tqdm import tqdm_notebook

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

    element_get_excel = driver.find_element(By.ID, &quot;glopopd_excel&quot;)
    element_get_excel.click()
    time.sleep(3)

driver.close()</code></pre><pre><code>====================================
### 2. 분석 데이터 전처리
- DataFrame 생성
  (1) 저장한 엑셀 파일을 불러와 pandas의 DataFrame으로 정리</code></pre><p>from glob import glob</p>
<pre><code># 파일 목록을 리스트로 반환
oil_stations_files = glob(&quot;./지역_*.xls&quot;)

# 25개 엑셀 파일 읽기
tmp_gu_df_raw = []
for file_name in oil_stations_files:
    tmp_gu_df = pd.read_excel(file_name, header=2)
    tmp_gu_df_raw.append(tmp_gu_df)

# DataFrame으로 모두 합치기
stations_raw = pd.concat(tmp_gu_df_raw)

# 인덱스 재정렬
stations_raw.reset_index(inplace=True)</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/168a1e34-9ba9-41f1-b3b6-298853f6c0d0/image.png)

------------------------------------------
- DataFrame 편집
    - 필요한 컬럼 데이터만 추려서 새로운 DataFrame 생성
</code></pre><p> stations = pd.DataFrame({
        &quot;상호&quot;: stations_raw[&quot;상호&quot;],
        &quot;주소&quot;: stations_raw[&quot;주소&quot;],
        &quot;가격&quot;: stations_raw[&quot;휘발유&quot;],
        &quot;셀프&quot;: stations_raw[&quot;셀프여부&quot;],
        &quot;상표&quot;: stations_raw[&quot;상표&quot;]
    })</p>
<pre><code></code></pre><pre><code>## &quot;주소&quot; 컬럼에서 구 이름 추출</code></pre><pre><code></code></pre><p> stations[&quot;구&quot;] = [each_address.split()[1] for each_address in stations[&quot;주소&quot;]]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/8b9e4d01-547c-4a6a-81e5-375940b93f66/image.png)
       ## &quot;가격&quot; 컬럼 데이터 형 변환 : object --&gt; float</code></pre><p>// 가격 정보가 있는 주유소만 사용
    stations = stations[stations[&quot;가격&quot;] != &quot;-&quot;]</p>
<pre><code>stations[&quot;가격&quot;] = stations[&quot;가격&quot;].astype(&quot;float&quot;)</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/bcc8d196-9023-47bf-90ca-5a3ec6333039/image.png)
----------------------------
### 3. 분석 데이터 시각화</code></pre><pre><code> import matplotlib.pyplot as plt
import seaborn as sns
import platform
from matplotlib import font_manager, rc

get_ipython().run_line_magic(&quot;matplotlib&quot;, &quot;inline&quot;)

path = &quot;C:/Windows/Fonts/malgun.ttf&quot;
font_name = font_manager.FontProperties(fname=path).get_name() 
rc(&quot;font&quot;, family=font_name)</code></pre><pre><code>* BOXPLOT  (seaborn)
셀프 주유소 vs. 주유소 (휘발유 가격 비교)</code></pre><pre><code> plt.figure(figsize=(10, 6))
sns.boxplot(x=&quot;셀프&quot;, y=&quot;가격&quot;, data=stations, palette=&quot;Set2&quot;)
plt.grid(True)
plt.show()    </code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/19ac63bf-0038-45f2-bc92-c07e8bf820a8/image.png)

-------------------------------------------
   셀프 주유소 vs. 주유소 (브랜드 별 비교)</code></pre><p>  plt.figure(figsize=(10, 6))
  sns.boxplot(x=&quot;상표&quot;, y=&quot;가격&quot;, hue=&quot;셀프&quot;, data=stations, palette=&quot;Set3&quot;)
  plt.grid(True)
  plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/8513872d-5777-49fa-8f39-e7a62b20a835/image.png)
-------------------------------
* folium 을 이용한 지도시각화
    - 전체 주유소의 휘발유 가격 평균으로 DataFrame 편집 (구 별로) - pivot 테이블 이용</code></pre><p>gu_price_data = pd.pivot_table(data=stations, index=&quot;구&quot;, values=&quot;가격&quot;)</p>
<pre><code>- 전체 주유소의 휘발유 가격 평균으로 DataFrame 편집 (구 별로) - pivot 테이블 이용</code></pre><pre><code> import folium
import json

geo_path = &quot;../data/seoul_municipalities_geo_simple.json&quot;
geo_str    = json.load(open(geo_path, encoding=&quot;utf-8&quot;))

oil_price_map = folium.Map(
        location=[37.5502, 126.982], zoom_start=10.5, tiles=&quot;CartoDB Voyager&quot;
)

folium.Choropleth(
    geo_data=geo_str,
    data=gu_price_data,
    columns=[gu_price_data.index, &quot;가격&quot;],
    key_on=&quot;feature.id&quot;,
    fill_color=&quot;PuRd&quot;,
    legend_name=&quot;휘발유 가격&quot;
).add_to(oil_price_map)

oil_price_map</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/620911f2-8640-42d6-af8f-4150141e3995/image.png)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - Selenium Basic]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Selenium-Basic</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Selenium-Basic</guid>
            <pubDate>Wed, 28 Feb 2024 12:57:26 GMT</pubDate>
            <description><![CDATA[<h3 id="selenium-기초">Selenium 기초</h3>
<h5 id="chrome-브라우저-도움말에서-버전-확인-122-이에-따른-driver-다운로드-후-ds_study폴더로-이동-chrome-드라이버를-다운로드-버전에-맞게-ds_study에-driver-폴더-만들어-안에-download한-드라이버-복사해-넣어둠">(chrome 브라우저 도움말에서 버전 확인 (122) 이에 따른 driver 다운로드 후 ds_study폴더로 이동 chrome 드라이버를 다운로드 (버전에 맞게) ds_study에 driver 폴더 만들어 안에 download한 드라이버 복사해 넣어둠)</h5>
<hr>
<ul>
<li>셀레니움 설치</li>
<li>윈도우 mac(intel)</li>
<li>conda install selenium</li>
<li>mac(m1)</li>
<li>pip install selenium  (!pip list로 확인가능)</li>
<li>chromedriver</li>
</ul>
<hr>
<p>!!!주의!!!
selenium의 코드가 바뀜 (인강의 내용과 달라짐 숙지) - 공식문서 확인하기 
기존:find_element_by_css_selector(&#39;tag&#39;) 에서
현재:find_element(By.CSS_SELECTOR(&#39;tag&#39;)) 로 바뀌었음</p>
<hr>
<h4 id="google에서-selenium-documentation-검색">google에서 selenium documentation 검색</h4>
<ul>
<li><p><a href="https://www.selenium.dev/documentation/">https://www.selenium.dev/documentation/</a></p>
</li>
<li><p><a href="https://selenium-python.readthedocs.io/">https://selenium-python.readthedocs.io/</a></p>
</li>
</ul>
<p>참고 : - <a href="https://www.selenium.dev/documentation/webdriver/getting_started/install_library/">https://www.selenium.dev/documentation/webdriver/getting_started/install_library/</a></p>
<hr>
<h4 id="selenium을-사용하는-이유">selenium을 사용하는 이유</h4>
<ul>
<li>Beautiful Soup만으로 해결할 수 없는것</li>
<li>자바스크립트 사용하는 웹페이지 경우</li>
<li>웹브라우저로 접근하지 않으면 안될 때</li>
</ul>
<hr>
<h4 id="selenium-기능">selenium 기능</h4>
<ul>
<li>web browser를 원격 조작하는 도구</li>
<li>자동으로 url 열고 클릭 등 가능</li>
<li>스크롤, 문자의 입력, 화면 캡처, 앞으로가기, 뒤로가기 등 (스크롤 할 수록 동적으로 스크롤이 늘어나며 정보 보여줌 : instgram, facebook등)</li>
</ul>
<hr>
<h4 id="webdriver-import">webdriver import</h4>
<ul>
<li>web browser 콘트롤 위해 selenium client사용</li>
<li>WebDriver (공통 인터페이스) + Browser Driver (각 브라우저 타입별 (Chrome, IE, FireFox 등 기타)</li>
<li>webdriver.Chrome() 은 Selenium 브라우저 제어 위한  WebDriver 생성하는 메서드</li>
<li>Chrome 브라우저와 동일한 버전 chromedriver 다운로드 받음
WebDriver의 get() 메서드 사용 특정 URL 웹페이지 열음<pre><code>from selenium import webdriver
from selenium.webdriver.chrome.service import Service
</code></pre></li>
</ul>
<h1 id="chrome-webdriver의-실행파일-경로">Chrome webDriver의 실행파일 경로</h1>
<p>chrome_driver_path = webdriver.Chrome(&#39;../driver/chromedriver.exe&#39;)</p>
<h1 id="chrome-webdriver-인스턴스-생성-및-실행-파일-경로-지정">Chrome WebDriver 인스턴스 생성 및 실행 파일 경로 지정</h1>
<p>service = Service(executable_path = chrome_driver_path driver)</p>
<p>options = webdriver.ChromeOptions()
driver = webdriver.Chrome(service = service, options = options)</p>
<pre><code>#### get() 함수로 접근하려는 웹 주소 지정
driver.get(&quot;https://www.naver.com&quot;)
#### naver가 별도의 브라우저로 나오고 Chrome이 자동화된 테스트소프트웨어에 의해 제어되고 있다 라고 나옴
#### 윈도우 창 닫기</code></pre><p>driver.quit()</p>
<pre><code>----------------------------
------------------------------------</code></pre><h3 id="브라우저-조작">브라우저 조작</h3>
<hr>
<h4 id="화면-최대-크기-설정">화면 최대 크기 설정</h4>
<h2 id="drivermaximize_window">driver.maximize_window()</h2>
<h4 id="화면-최소-크기-설정">화면 최소 크기 설정</h4>
<p>driver.minimize_window()</p>
<hr>
<h4 id="화면-크기-설정">화면 크기 설정</h4>
<h2 id="driverset_window_size600600">driver.set_window_size(600,600)</h2>
<h4 id="새로고침">새로고침</h4>
<h2 id="driverrefresh">driver.refresh()</h2>
<h4 id="뒤로가기">뒤로가기</h4>
<h2 id="driverback">driver.back()</h2>
<h4 id="앞으로-가기">앞으로 가기</h4>
<h2 id="driverforward">driver.forward() </h2>
<h4 id="새로운-탭-생성---자바스크립트-코드-사용">새로운 탭 생성 - 자바스크립트 코드 사용</h4>
<h2 id="driverexecute_scriptwindowopenhttpswwwnavercom">driver.execute_script(&#39;window.open(&quot;<a href="https://www.naver.com&quot;);&#39;">https://www.naver.com&quot;);&#39;</a>)</h2>
<h4 id="탭-이동">탭 이동</h4>
<p>len(driver.window_handles)
driver.switch_to.window(driver.window_handles[0])</p>
<hr>
<h4 id="탭-닫기">탭 닫기</h4>
<h2 id="driverclose">driver.close()</h2>
<h4 id="화면-스크롤">화면 스크롤</h4>
<h1 id="위에서-종료했으니-다시-브라우저-띄우기">위에서 종료했으니 다시 브라우저 띄우기</h1>
<h1 id="execute_script는-자바스크립트-사용하겠다는-의미">execute_script는 자바스크립트 사용하겠다는 의미</h1>
<p>driver.execute_script(&#39;return document.body.scrollHeight&#39;)</p>
<hr>
<h4 id="화면-스크롤-하단-이동">화면 스크롤 하단 이동</h4>
<h2 id="driverexecute_scriptwindowscrollto0-documentbodyscrollheight">driver.execute_script(&#39;window.scrollTo(0, document.body.scrollHeight);&#39;)</h2>
<h4 id="현재-보이는-화면-스크린샷-저장">현재 보이는 화면 스크린샷 저장</h4>
<h2 id="driversave_screenshotlast_heightpng">driver.save_screenshot(&#39;./last_height.png&#39;)</h2>
<h4 id="화면-스크롤-상단-이동">화면 스크롤 상단 이동</h4>
<h2 id="driverexecute_scriptwindowscrollto00">driver.execute_script(&#39;window.scrollTo(0,0);&#39;)</h2>
<h4 id="스크린샷">스크린샷</h4>
<p>driver.save_screenshot(&quot;./screenshot.png&quot;)</p>
<hr>
<h3 id="웹-html-요소-검색">웹 html 요소 검색</h3>
<ul>
<li>find_element() or find_elements() 사용</li>
</ul>
<p>from selenium.webdriver.common.by import By    #세로 땡땡땡 클릭 도구더보기 / 개발자도구에서 찾기
first_content = driver.find_element(By.CSS_SELECTOR, &#39;#content &gt; div.cover-masonry &gt; div &gt; ul &gt; li:nth-child(1)&#39;)
first_content.click()</p>
<hr>
<p>원하는 페이지의 ul 밑에 li를 커서 움직이며 원하는 해당 페이지의 li 부분에 우클릭 / 카피 / copy selector
&#39; &#39; 공백에 tag값 넣어줌 그러면 상세 페이지만 따로 브라우져에 띄워줌 예) #content &gt; div.cover-masonry &gt; div &gt; ul &gt; li:nth-child(1) 에서 #은 ID 의미</p>
<p>from selenium.webdriver import ActionChains</p>
<p>some_tag = driver.find_element(By.CSS_SELECTOR, &#39;#content &gt; div.cover-list &gt; div &gt; ul &gt; li:nth-child(1)&#39;)</p>
<p>action = ActionChains(driver)
action.move_to_element(some_tag).perform()</p>
<hr>
<h4 id="브라우저-완전-종료">브라우저 완전 종료</h4>
<h2 id="driverquit">driver.quit()</h2>
<h4 id="google에서-selenium-python-document-검색">google에서 selenium python document 검색</h4>
<p><a href="https://selenium-python.readthedocs.io/">https://selenium-python.readthedocs.io/</a></p>
<p>webDrive API에서 Action Chains
다양한 마우스 기능들 담당고할 selenium python document (google에서 검색)</p>
<h2 id="driverquit-1">driver.quit()</h2>
<h3 id="검색어-입력">검색어 입력</h3>
<h4 id="css_selector">CSS_SELECTOR</h4>
<ul>
<li>네이버 검색창에 검색어 입력
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome(&#39;../ds_study/driver/chromedriver.exe&#39;)
driver.get(&#39;<a href="https://www.naver.com&#39;">https://www.naver.com&#39;</a>)</li>
</ul>
<p>keyword = driver.find_element(By.CSS_SELECTOR, &#39;#query&#39;)
keyword.send_keys(&#39;파이썬&#39;)</p>
<ul>
<li>찾기 (돋보기) 버튼 클릭
search_btn = driver.find_element(By.CSS_SELECTOR, &#39;#search-btn&#39;)
search_btn.click</li>
</ul>
<hr>
<h4 id="xpath">xpath</h4>
<ul>
<li>&#39;//&#39;: 최상위</li>
<li>&#39;*&#39;: 자손 태그</li>
<li>&#39;/&#39; : 자식 태그</li>
</ul>
<hr>
<h1 id="원하는-페이지의-개발자-도구에서-찾아서-저장시-xpath로-함">원하는 페이지의 개발자 도구에서 찾아서 저장시 xpath로 함</h1>
<ul>
<li><p>최상위 - 
driver.find_element(By.XPATH, &#39;//*[@id=&quot;query&quot;]&#39;).send_keys(&#39;xpath&#39;)</p>
</li>
<li><p>자손 태그 -
driver.find_element(By.XPATH, &#39;//*[@id=&quot;search-btn&quot;]&#39;).click()
driver.quit()</p>
</li>
</ul>
<hr>
<h3 id="검색어-입력-예제">검색어 입력 (예제)</h3>
<h4 id="webdriver-import-1">webdriver import</h4>
<pre><code>from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome(&#39;../ds_study/driver/chromedriver.exe&#39;) 

driver.get(&#39;http://pinkwink.kr&#39;)

# 1. 지역 선택 고정
from selenium.webdriver import ActionChains

- 검색어 입력 문법
search_tag = driver.find_element(By.CSS_SELECTOR, &#39;.search&#39;)
action = ActionChains(driver)
action.click(search_tag)
action.perform()
-----------------------------------------------------
#### 검색어 입력 (딥러닝 입력해 봄)

driver.find_element(By.CSS_SELECTOR, &#39;#header &gt; div.search &gt; input[type=text]&#39;).send_keys(&#39;딥러닝&#39;)
--------------------------------------
#### 검색버튼 클릭 문법
driver.find_element(By.CSS_SELECTOR, &#39;#header &gt; div.search.on &gt; button&#39;).click()
------------------------------------------------------------------------
### selenium + beautifulsoup
- 현재 화면의  html코드 가져오기

from bs4 import BeautifulSoup
req = driver.page_source

# web page의 html 코드를 beautifulsoup으로 읽어와서 
soup = BeautifulSoup(req, &#39;html.parser&#39;)
---------------------------------------------------------
#### 원하는 데이터를 뽑아오도록 제어

soup.select(&#39;.post-item&#39;)
contents = soup.select(&#39;.post-item&#39;)
len(contents)
contents[2]</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - 웹데이터 분석 (시카고 맛집 데이터)]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%9B%B9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EC%8B%9C%EC%B9%B4%EA%B3%A0-%EB%A7%9B%EC%A7%91-%EB%8D%B0%EC%9D%B4%ED%84%B0</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%9B%B9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EC%8B%9C%EC%B9%B4%EA%B3%A0-%EB%A7%9B%EC%A7%91-%EB%8D%B0%EC%9D%B4%ED%84%B0</guid>
            <pubDate>Fri, 23 Feb 2024 15:19:45 GMT</pubDate>
            <description><![CDATA[<h3 id="1-시카고-50개-맛집-샌드위치-가게-이름과-메뉴-정보-모으기">1. 시카고 50개 맛집 샌드위치 가게 이름과 메뉴 정보 모으기</h3>
<ul>
<li><p>시카고 50개 맛집 샌드위치 가게에 대한 메뉴와 가게 이름</p>
<pre><code># main page
https://www.chicagomag.com/Chicago-Magazine/November-2012/Best-Sandwiches-Chicago/</code></pre><p>최종목표 총 51개 페이지에서 각 가게의 정보를 가져온다.</p>
</li>
<li><p>가게이름</p>
</li>
<li><p>대표메뉴</p>
</li>
<li><p>대표메뉴의 가격</p>
</li>
<li><p>가게주소</p>
</li>
<li><p>순위 페이지</p>
<pre><code>https://www.chicagomag.com/Chicago-Magazine/November-2012/Best-Sandwiches-Chicago/</code></pre></li>
<li><p>그 중 하나 세부 페이지 (예) Old Oak Tap BLT)</p>
<pre><code>https://www.chicagomag.com/Chicago-Magazine/November-2012/Best-Sandwiches-in-Chicago-Old-Oak-Tap-BLT/</code></pre></li>
<li><p>주소와 대표메뉴 가격 있음</p>
</li>
</ul>
<h4 id="1-구조">(1) 구조</h4>
<ul>
<li>메인 page : 시카고 50개 맛집 샌드위치 - 가게이름, 메뉴</li>
<li>세부 page : 각각 소개한 50개의 페이지 - 가게 주소, 대표 메뉴 가격</li>
<li>수집하고자 하는 정보 : 총 51개 페이지에서 각 가게의 정보 수집 - 가게이름, 대표메뉴, 대표메뉴 가격, 가게주소</li>
</ul>
<h4 id="2-시카고-맛집-데이터-수집-및-정리">(2) 시카고 맛집 데이터 수집 및 정리</h4>
<pre><code>    # pip install fake-useragent (터미널에서 인스톨)
    import pandas as pd
    import ssl
    from urllib.request import urlopen, Request
    from urllib.parse import urljoin
    from fake_useragent import UserAgent # 이것은 header request 부분 User Agent부분 임의로 만들어줌
    from bs4 import BeautifulSoup</code></pre><h4 id="3-메인-페이지">(3) 메인 페이지</h4>
<ul>
<li>시카고 매거진 기사에 대한 html 요청 및 BeautifulSoup으로 읽기<pre><code># pip install fake-useragent (터미널에서 인스톨)
</code></pre></li>
</ul>
<p>from urllib.request import Request, urlopen</p>
<h1 id="이것은-header-request부분-user-agent부분-임의로-만들어줌">이것은 header request부분 User Agent부분 임의로 만들어줌</h1>
<p>from fake_useragent import UserAgent<br>from bs4 import BeautifulSoup</p>
<p>url_base = &quot;<a href="https://www.chicagomag.com/&quot;">https://www.chicagomag.com/&quot;</a>
url_sub = &quot;chicago-magazine/november-2012/best-sandwiches-chicago/&quot;
url = url_base + url_sub</p>
<h1 id="response--urlopenurl---그냥-이렇게-하면-403-error가-나옴-이것을-구글서-서치---이것은-서버에서-내-접근을-막은-것임">response = urlopen(url)  # 그냥 이렇게 하면 403 error가 나옴. 이것을 구글서 서치   이것은 서버에서 내 접근을 막은 것임.</h1>
<h1 id="이것을-극복하려면-ctrshifti에서-network열고-첫-페이지-맨-밑에header-reqest부분에-user-agent부분-복사">이것을 극복하려면... ctr+shift+i에서 network열고 첫 페이지 맨 밑에header reqest부분에 User Agent부분 복사</h1>
<h1 id="req--requesturl-headersuser-agentmozilla50-windows-nt-100-win64-x64-applewebkit53736-khtml-like-gecko-chrome121000-safari53736-403error시-이렇게-입력해야-함">req = Request(url, headers={&quot;User-Agent&quot;:&quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36&quot;}) #403error시 이렇게 입력해야 함.</h1>
<h1 id="또는">또는</h1>
<h1 id="user-agent-붙여넣음-dictionary-형태로-키와-밸류값을-넣어줌">user agent 붙여넣음 (dictionary 형태로 키와 밸류값을 넣어줌)</h1>
<p>req = Request(url, headers={&quot;user-agent&quot;: &quot;chrome&quot;})  </p>
<h1 id="이래도-response-받아올-수-있다">이래도 response 받아올 수 있다.</h1>
<h1 id="이렇게-간단히-해서-열리면-되는데-아닌-페이지는-위와-같이-header-request부분-user-agent부분-복사해-붙여야-함">이렇게 간단히 해서 열리면 되는데 아닌 페이지는 위와 같이 header request부분 User Agent부분 복사해 붙여야 함</h1>
<p>#response = urlopen(req) 
#response
#response.status # 비로서 status 200이 나옴</p>
<h1 id="또는-이렇게-해도-됨">또는 이렇게 해도 됨</h1>
<h1 id="ua--useragent">ua = UserAgent()</h1>
<h1 id="req--requesturl-headersuser-agent-uaie">req = Request(url, headers={&quot;user-agent&quot;: ua.ie})</h1>
<p>html = urlopen(req)
soup = BeautifulSoup(html, &quot;html.parser&quot;)</p>
<h1 id="아니면-터미널에서-ds_study활성화-시켜-준-후">아니면 터미널에서 ds_study활성화 시켜 준 후</h1>
<h1 id="pip-install-fake-useragent-입력-인스톨-후--위와-같이-useragent-해도-됨">pip install fake-useragent 입력 인스톨 후  위와 같이 UserAgent 해도 됨.</h1>
<h1 id="원하는-페이지의-모든-html부분-가져올-수-있음">원하는 페이지의 모든 html부분 가져올 수 있음</h1>
<p>print(soup.prettify()) </p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/fc84b9bb-70a6-44a9-9eec-38cc725be41d/image.png)
---------------------------------------</code></pre><h1 id="찾고자-하는-부분을-ctr--shift--i-부분서-찾아내면-tag는-div--class는-sammy-를-확인-할-수-있음">찾고자 하는 부분을 ctr + shift + i 부분서 찾아내면 tag는 div  class는 sammy 를 확인 할 수 있음.</h1>
<p>soup.find_all(&quot;div&quot;, class_=&quot;sammy&quot;), len(soup.find_all(&quot;div&quot;, class_=&quot;sammy&quot;)) </p>
<h1 id="또는-1">또는</h1>
<h1 id="soupselectsammy-lensoupselectsammy">soup.select(&quot;.sammy&quot;), len(soup.select(&quot;.sammy&quot;))</h1>
<h1 id="실행결과--50">실행결과 : 50</h1>
<pre><code>- div의 sammy 클래스가 50개 임을 확인

![](https://velog.velcdn.com/images/jj_study/post/2d2ba82d-da3c-4c8e-a722-b705402a3761/image.png)

-------------------------------------------------------------------
- 랭킹, 가게이름, 대표 메뉴, url 주소 데이터 찾아보기</code></pre><h1 id="필요한-첫번째-랭크-1의-내용-담음">필요한 첫번째 랭크 1의 내용 담음</h1>
<p>tmp_one = soup.find_all(&quot;div&quot;,&quot;sammy&quot;)[0] </p>
<h1 id="select문으로도-할-수-있음">select문으로도 할 수 있음</h1>
<p>#tmp_one.select_one(&quot;.sammyRank&quot;).text
#type(tmp_one)</p>
<p>tmp_one.find(&quot;div&quot;, {&quot;class&quot;:&quot;sammyListing&quot;})</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/5fd436f5-c6b0-44f1-80db-2318d84ef2a7/image.png)

-------------------------------------------------------------------------</code></pre><p>tmp_one.find(&quot;div&quot;, {&quot;class&quot;:&quot;sammyListing&quot;}).get_text()</p>
<h1 id="또는-2">또는</h1>
<h1 id="tmp_oneselect_onesammylistingtext">tmp_one.select_one(&quot;.sammyListing&quot;).text</h1>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/3a165017-fdfa-4d66-9772-fbf21c993721/image.png)
</code></pre><p>tmp_one.find(&quot;a&quot;)[&quot;href&quot;]</p>
<h1 id="또는-3">또는</h1>
<h1 id="tmp_oneselect_oneagethref">tmp_one.select_one(&quot;a&quot;).get(&quot;href&quot;)</h1>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/6aa53bc5-bbb5-42ee-ae1e-13ca1198e89b/image.png)
</code></pre><h1 id="n-이런-표현-없애기-n-이나-rn-기준으로-없애기">\n 이런 표현 없애기 (\n 이나 \r\n 기준으로 없애기)</h1>
<p>import re
tmp_string = tmp_one.find(class_=&quot;sammyListing&quot;).get_text()
re.split(&quot;\n|\r\n&quot;, tmp_string)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/5b097f7d-6f0d-4c00-a517-a91bb99d5f7b/image.png)
---------------------------------------</code></pre><p>print(re.split((&quot;\n|\r\n&quot;), tmp_string)[0]) # 메뉴이름
print(re.split((&quot;\n|\r\n&quot;), tmp_string)[1]) # 카페이름</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/af6723bf-5c8d-4733-854e-1834444bc71a/image.png)
---------------------------------------</code></pre><p>from urllib.parse import urljoin
url_base = &quot;<a href="https://www.chicagomag.com/&quot;">https://www.chicagomag.com/&quot;</a></p>
<h1 id="필요한-내용을-담을-빈-리스트">필요한 내용을 담을 빈 리스트</h1>
<h1 id="리스트로-하나씩-컬럼을-만들고-dataframe으로--합칠-예정">리스트로 하나씩 컬럼을 만들고 Dataframe으로  합칠 예정</h1>
<p>rank = []
main_menu = []
cafe_name = []
url_add = []</p>
<p>list_soup = soup.find_all(&quot;div&quot;, &quot;sammy&quot;) # soup.select(&quot;.sammy&quot;)</p>
<p>for item in list_soup:
    rank.append(item.find(class_=&quot;sammyRank&quot;).get_text())
    tmp_string = item.find(class_=&quot;sammyListing&quot;).get_text()
    main_menu.append(re.split((&quot;\n|\r\n&quot;), tmp_string)[0])
    cafe_name.append(re.split((&quot;\n|\r\n&quot;), tmp_string)[1])
    url_add.append(urljoin(url_base, item.find(&quot;a&quot;)[&quot;href&quot;]))</p>
<p>len(rank), len(main_menu), len(cafe_name), len(url_add)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/24c03fab-aefd-4464-89ce-7d9e338589df/image.png)
</code></pre><p>rank[:5]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/f2d582bd-7847-49e8-9d21-7f7f1f850f84/image.png)

![](https://velog.velcdn.com/images/jj_study/post/41209f6f-7551-4849-9693-9a3aead303b7/image.png)</code></pre><p>main_menu[:5]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/9b5c6ede-b20a-45e7-98fd-b8c2d02d05bc/image.png)
</code></pre><p>cafe_name[:5]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/ee8b8a4d-a7ee-49c1-8633-d4c4f7a67fe5/image.png)</code></pre><p>url_add[:5]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/5dac055a-aacf-40d3-b0ee-0c0defd36a17/image.png)
</code></pre><p>import pandas as pd</p>
<p>data = {
    &quot;Rank&quot;: rank,
    &quot;Menu&quot;: main_menu,
    &quot;Cafe&quot;: cafe_name,
    &quot;URL&quot;: url_add,
}
df = pd.DataFrame(data)
df.tail(5)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/ca195241-d70b-47dc-9aba-7424883f2ad6/image.png)
--------------------------------------</code></pre><h1 id="컬럼-순서-변경">컬럼 순서 변경</h1>
<p>df = pd.DataFrame(data, columns=[&quot;Rank&quot;, &quot;Cafe&quot;,&quot;Menu&quot;,&quot;URL&quot;])
df</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/d4cf8567-4d22-4422-b64c-48bd3ea8a72b/image.png)
</code></pre><h1 id="데이터-저장">데이터 저장</h1>
<p>df.to_csv(
    &quot;../data/03. best_sandwiches_list_chicago.csv&quot;, sep=&quot;,&quot;, encoding=&quot;utf-8&quot;
)</p>
<pre><code>----------------------------------------------------------------
(4) 시카고 맛집 데이터 분석 - 하위데이터</code></pre><h1 id="requirements">Requirements</h1>
<p>import folium
import pandas as pd
import numpy as np
from urllib.request import urlopen, Request
from fake_useragent import UserAgent
from bs4 import BeautifulSoup</p>
<p>df = pd.read_csv(&quot;../data/03. best_sandwiches_list_chicago.csv&quot;)
df.tail()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/082e4eb1-f76d-4e1f-9d32-8e2c0086ee4b/image.png)
----------------------------------------</code></pre><p>df[&quot;URL&quot;][0]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/e3cf9985-4c68-4a3c-b542-830ace4b5ec5/image.png)
-----------------------------------------</code></pre><h1 id="주소부분-ctrlshifti-하면-주소-위치를-감싸는-class가-p이고-addy을-알-수-있음">주소부분 ctrl+shift+i 하면 주소 위치를 감싸는 class가 p이고 addy을 알 수 있음</h1>
<pre><code>### regular expression

price_tmp = soup_tmp.find(&quot;p&quot;,&quot;addy&quot;).text
price_tmp

import re
re.split(&quot;,&quot;, price_tmp)

price_tmp = re.split(&quot;,&quot;, price_tmp)[0]
price_tmp

tmp = re.search(&quot;\$\d+\.(\d+)?&quot;, price_tmp).group()
price_tmp[len(tmp) + 2:]

from tqdm import tqdm
![](https://velog.velcdn.com/images/jj_study/post/9b915b30-e328-4a5e-8390-8b6b1dd29c12/image.png)
    address.append(price_tmp[len(tmp)+2:])
    print(idx)

price, address

![](https://velog.velcdn.com/images/jj_study/post/9fe992d9-b162-4028-9c91-ef42862f5538/image.png)</code></pre><p>df[&quot;Price&quot;] = price
df[&quot;Rank&quot;] = rank
df[&quot;Address&quot;] = address
df = df.loc[:,[&quot;Rank&quot;,&quot;Cafe&quot;,&quot;Menu&quot;,&quot;Price&quot;,&quot;Address&quot;]]
df.set_index(&quot;Rank&quot;, inplace = True)
df</p>
<pre><code>- csv로 저장하고 읽어오기</code></pre><p>df.to_csv(&quot;../data/03. best_sandwiches_list_chicago2.csv&quot;, sep=&quot;,&quot;, encoding= &quot;UTF-8&quot;)</p>
<p>pd.read_csv(&quot;../data/03. best_sandwiches_list_chicago2.csv&quot;, index_col=0)
&#39;&#39;&#39;</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/2be87bf9-c969-4a38-9c77-e271939ffc2c/image.png)

![](https://velog.velcdn.com/images/jj_study/post/904a79e8-8608-4f6c-b120-501a3b10363c/image.png)
### 2. 시카고 맛집 데이터 지도 시각화
#### (1) setting

     import pandas as pd
    import numpy as np
    import googlemaps
    import folium
    from tqdm import tqdm

    df = pd.read_csv(&quot;../data/03. best_sandwiches_list_chicago2.csv&quot;, index_col=0)
df.tail(3)

![](https://velog.velcdn.com/images/jj_study/post/0b87f16d-061f-4507-a678-66dd04a08543/image.png)

#### (2) GoogleMaps에서 위치 정보 가져오기
- 가게 주소 정보로 위도, 경도 데이터 가져오기
- folium으로 지도 시각화

gmaps_key = &quot;나의 api_key&quot;
gmaps = googlemaps.Client(key=gmaps_key)
</code></pre><p>lat = []
lng = []</p>
<p>for idx, row in tqdm(df[:].iterrows()):
    if not row[&quot;Address&quot;] == &quot;Multiple location&quot;:
        target_name = row[&quot;Address&quot;] + &quot;, &quot; + &quot;Chicago&quot;
        #print(target_name)
        #위도와 경도값을 다 가져옴
        gmaps_output = gmaps.geocode(target_name)<br>        #딕셔너리 형태로 데이터가 있음
        #print(gmaps_output)<br>        location_output = gmaps_output[0].get(&quot;geometry&quot;)
        #지리정보에 해당하는 속성값만 가져옴
        #print(location_output)<br>        lat.append(location_output[&quot;location&quot;][&quot;lat&quot;])
        lng.append(location_output[&quot;location&quot;][&quot;lng&quot;])
        #location_target - gmaps_output[0]
    else:
        lat.append(np.nan)
        lng.append(np.nan)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/1fec993a-cc96-4ce8-80cb-57d0a8531305/image.png)
</code></pre><p>df[&quot;latt&quot;] = lat
df[&quot;lng&quot;] = lng</p>
<p>len(lat), len(lng)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/8133658b-addb-4f89-bc6d-6487afae8bc7/image.png)</code></pre><p>df.tail()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/062a1c9c-a8cd-40cc-b307-181905354965/image.png)</code></pre><pre><code>

--------------------------------------------------------------------
#### (3) folium 지도 시각화
- 지도 상 카페 위치 Marker로 찍기</code></pre><p> mapping = folium.Map(location=[41.8781136, -87.6297982], zoom_start=11)</p>
<pre><code>for idx, row in df.iterrows():
    if row[&quot;Address&quot;] != &quot;Multiple location&quot;:
        folium.Marker(
              location=[row[&quot;lat&quot;], row[&quot;lng&quot;]],
              popup=row[&quot;Cafe&quot;],
              tooltip=row[&quot;Menu&quot;],
              icon=folium.Icon(icon=&quot;coffee&quot;, prefix=&quot;fa&quot;)
        ).add_to(chicago_map)

mapping</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/5aa5a2d3-60ad-4fae-a84b-456faf524bc6/image.png)

![](https://velog.velcdn.com/images/jj_study/post/5b62fea4-534d-4d04-a0df-361d47e41217/image.png)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - 웹데이터 분석 (네이버 금융)]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%9B%B9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EB%84%A4%EC%9D%B4%EB%B2%84-%EA%B8%88%EC%9C%B5</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%9B%B9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EB%84%A4%EC%9D%B4%EB%B2%84-%EA%B8%88%EC%9C%B5</guid>
            <pubDate>Fri, 23 Feb 2024 06:56:41 GMT</pubDate>
            <description><![CDATA[<h3 id="네이버-금융">네이버 금융</h3>
<h4 id="1-웹페이지-개발자-도구">1. 웹페이지 개발자 도구</h4>
<ul>
<li>인터넷에 html을 보기 위한 도구</li>
<li>크롬 오른쪽 상단 ... &gt; 도구 더보기 &gt; 개발자 도구 또는 그냥 F12
<img src="https://velog.velcdn.com/images/jj_study/post/d099b6de-28f6-4d00-be09-df38ce8a25ac/image.png" alt=""></li>
</ul>
<p><img src="https://velog.velcdn.com/images/jj_study/post/5d87c97f-bfd1-4928-8478-c6bfaca0c7ab/image.png" alt=""></p>
<h2 id=""><img src="https://velog.velcdn.com/images/jj_study/post/1a542953-ffeb-49ec-a1f7-8c388214f7cc/image.png" alt=""></h2>
<h4 id="2-원하는-html-태그-위치-찾아가기">2. 원하는 html 태그 위치 찾아가기</h4>
<ul>
<li>html태그 위치 : <span class = "value"> 부분<pre><code>soup.find_all(&quot;span&quot;, &quot;value&quot;)[0].string
# 실행결과
&#39;1,146.00&#39;</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/d4bfc631-90a7-4688-8c7f-9c62236d9a9a/image.png" alt=""></li>
</ul>
<hr>
<h4 id="3-url접근-urllib의-request-모듈-필요">3. url접근 (urllib의 request 모듈 필요)</h4>
<pre><code># 네이버 금융
  from urllib.request import urlopen
  from bs4 import BeautifulSoup

  url = &quot;https://finance.naver.com/&quot;
  response = urlopen(url)
  response.status
  &gt;&gt; 200 - 웹페이지 정상 상태</code></pre><ul>
<li><p>4개 li 리스트 (미국/일본/유럽연합/중국)</p>
</li>
<li><p>그 내부의 a태그 가져오기</p>
</li>
<li><p>그 내부의 값 하나씩 뽑아내기</p>
<p><img src="https://velog.velcdn.com/images/jj_study/post/f19eb5da-3ca1-48cd-bb02-f08fdaf48c4a/image.png" alt="">
<img src="https://velog.velcdn.com/images/jj_study/post/f7ff4644-7914-47a3-a062-bb02ad2a76e0/image.png" alt=""></p>
</li>
</ul>
<h4 id="3-html데이터-가져오기">3. html데이터 가져오기</h4>
<pre><code># import
from urllib.request import urlopen #(웹페이지 이용이란 요청하고 응답하는 것임)
from bs4 import BeautifulSoup

url = &quot;https://finance.naver.com/marketindex/&quot;
# page = urlopen(url)
# response , res  라고도 사용 (웹페이지 이용이란 요청하고 응답하는 것임)
response = urlopen(url)
# response.status (google에서 HTTP 상태 코드 검색하면 숫자에 따른 상태의미 알수있음)
soup = BeautifulSoup(response, &quot;html.parser&quot;)
print(soup.prettify())
</code></pre><p>결과</p>
<pre><code>&lt;head&gt;
  &lt;title&gt;
   네이버 증권
  &lt;/title&gt;
  &lt;meta content=&quot;text/html; charset=utf-8&quot; http-equiv=&quot;Content-Type&quot;/&gt;
  &lt;meta content=&quot;text/javascript&quot; http-equiv=&quot;Content-Script-Type&quot;/&gt;
  &lt;meta content=&quot;text/css&quot; http-equiv=&quot;Content-Style-Type&quot;/&gt;
  &lt;meta content=&quot;네이버 증권&quot; name=&quot;apple-mobile-web-app-title&quot;/&gt;
  &lt;meta content=&quot;네이버 증권&quot; property=&quot;og:title&quot;/&gt;
  &lt;meta content=&quot;https://ssl.pstatic.net/static/m/stock/im/2016/08/og_stock-200.png&quot; property=&quot;og:image&quot;/&gt;
  &lt;meta content=&quot;https://finance.naver.com&quot; property=&quot;og:url&quot;/&gt;
  &lt;meta content=&quot;국내 해외 증시 지수, 시장지표, 뉴스, 증권사 리서치 등 제공&quot; property=&quot;og:description&quot;/&gt;
  &lt;meta content=&quot;article&quot; property=&quot;og:type&quot;/&gt;
  &lt;meta content=&quot;&quot; property=&quot;og:article:thumbnailUrl&quot;/&gt;
  &lt;meta content=&quot;네이버 증권&quot; property=&quot;og:article:author&quot;/&gt;
  &lt;meta content=&quot;http://FINANCE.NAVER.COM&quot; property=&quot;og:article:author:url&quot;/&gt;
  &lt;link href=&quot;https://ssl.pstatic.net/imgstock/static.pc/20230321170048/css/finance_header.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;/&gt;
  &lt;link href=&quot;https://ssl.pstatic.net/imgstock/static.pc/20230321170048/css/finance.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;/&gt;
  &lt;link href=&quot;https://ssl.pstatic.net/imgstock/static.pc/20230321170048/css/newstock3.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;/&gt;
  &lt;script src=&quot;https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/jindo.min.ns.1.5.3.euckr.js&quot; type=&quot;text/javascript&quot;&gt;
  &lt;/script&gt;
  &lt;script src=&quot;https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/release/common.js&quot; type=&quot;text/javascript&quot;&gt;
  &lt;/script&gt;
  &lt;script src=&quot;https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/jindoComponent/jindo.Component.1.0.3.js&quot; type=&quot;text/javascript&quot;&gt;</code></pre><h4 id="4-데이터-추출하기-태그-가져오기">4. 데이터 추출하기 (태그 가져오기)</h4>
<p>(방법1)</p>
<pre><code>soup.find_all(&quot;span&quot;,&quot;value&quot;), len(soup.find_all(&quot;span&quot;,&quot;value&quot;))

# 실행결과
([&lt;span class=&quot;value&quot;&gt;1,336.00&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;887.68&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1,435.40&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;185.03&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;149.8800&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1.0775&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1.2584&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;104.2000&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;77.59&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1618.4&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;2014.9&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;85846.55&lt;/span&gt;],
 12)</code></pre><p>(방법2)</p>
<pre><code>soup.find_all(&quot;span&quot;, class_=&quot;value&quot;), len(soup.find_all(&quot;span&quot;,&quot;value&quot;))
# 실행결과
&gt;&gt;
([&lt;span class=&quot;value&quot;&gt;1,336.00&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;887.68&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1,435.40&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;185.03&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;149.8800&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1.0775&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1.2584&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;104.2000&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;77.59&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1618.4&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;2014.9&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;85846.55&lt;/span&gt;],
 12)</code></pre><p>(방법3) : 갯수 확인까지 (+ len( ))</p>
<pre><code>soup.find_all(&quot;span&quot;, {&quot;class&quot;:&quot;value&quot;}), len(soup.find_all(&quot;span&quot;,&quot;value&quot;))

#실행결과
&gt;&gt;
([&lt;span class=&quot;value&quot;&gt;1,336.00&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;887.68&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1,435.40&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;185.03&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;149.8800&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1.0775&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1.2584&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;104.2000&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;77.59&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;1618.4&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;2014.9&lt;/span&gt;,
  &lt;span class=&quot;value&quot;&gt;85846.55&lt;/span&gt;],
 12)</code></pre><hr>
<h4 id="5-태그에서-텍스트만-추출하기">5. 태그에서 텍스트만 추출하기</h4>
<pre><code>* (방법 1)
soup.find_all(&quot;span&quot;,{&quot;lacss&quot;: &quot;value&quot;})[0] 

* (방법 2)
soup.find_all(&quot;span&quot;,{&quot;class&quot;:&quot;value&quot;})[0].text

* (방법 3)
soup.find_all(&quot;span&quot;,{&quot;class&quot;:&quot;value&quot;})[0].string

* (방법 4)
soup.find_all(&quot;span&quot;,{&quot;class&quot;:&quot;value&quot;})[0].get_text()

&gt;&gt; &#39;1,336.00&#39;</code></pre><hr>
<h4 id="6-urllib-모듈---request로-url에-접근-네이버금융--예제1-2">6. urllib 모듈 - request로 url에 접근 (네이버금융 : 예제1-2)</h4>
<ul>
<li><p>!pip install requests</p>
</li>
<li><p>find, find_all</p>
</li>
<li><p>select, select_one</p>
</li>
<li><p>find, select_one : 단일선택</p>
</li>
<li><p>select, find_all : 다중선택</p>
</li>
<li><p>requests 임포트</p>
<pre><code>import requests
# from urllib.request.Request
from bs4 import BeautifulSoup
</code></pre></li>
</ul>
<p>url = &quot;<a href="https://finance.naver.com/marketindex/&quot;">https://finance.naver.com/marketindex/&quot;</a>
response = requests.get(url)
#requests.get(), requests.post() #equest에는 get방식과 post방식이 있다.
soup = BeautifulSoup(response.text, &quot;html.parser&quot;)
print(soup.prettify())</p>
<h1 id="requestsget">requests.get()</h1>
<h1 id="requestspost">requests.post()</h1>
<p>reponse</p>
<h1 id="실행결과">실행결과</h1>
<blockquote>
<blockquote>
<p>&lt;Response [200]&gt; </p>
</blockquote>
</blockquote>
<h1 id="실행결과-1">실행결과</h1>
<blockquote>
<blockquote>
</blockquote>
<p>Output exceeds the size limit. Open the full output data in a text editor<script language="javascript" src="/template/head_js.naver?referer=info.finance.naver.com&amp;menu=marketindex&amp;submenu=market">
</script></p>
</blockquote>
<script src="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/info/jindo.min.ns.1.5.3.euckr.js" type="text/javascript">
</script>
<script src="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/jindo.1.5.3.element-text-patch.js" type="text/javascript">
</script>
<div id="container" style="padding-bottom:0px;">
 <div class="market_include">
  <div class="market_data">
   <div class="market1">
    <div class="title">
     <h2 class="h_market1">
      <span>
       환전 고시 환율
      </span>
     </h2>
    </div>
    <!-- data -->
    <div class="data">
     <ul class="data_lst" id="exchangeList">
      <li class="on">
       <a class="head usd" href="/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW" onclick="clickcr(this, 'fr1.usdt', '', '', event);">
        <h3 class="h_lst">
         <span class="blind">
          미국 USD
```
------------------------------------------------------------------
#### 7. 태그 리스트 가져오기
- li 태그의 on 클래스 
- 그 안에 있는 a태그 가져오기
- 그 안에 있는 값들을 하나씩 뽑아냄
```
soup.find_all("li","on") # li 태그의 on 클래스

<h1 id="실행결과-2">실행결과</h1>
<blockquote>
<blockquote>
</blockquote>
<p>Output exceeds the size limit. Open the full output data in a text editor[<li class="on">
 <a class="head usd" href="/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW" onclick="clickcr(this, 'fr1.usdt', '', '', event);">
 <h3 class="h_lst"><span class="blind">미국 USD</span></h3>
 <div class="head_info point_dn">
 <span class="value">1,319.00</span>
 <span class="txt_krw"><span class="blind">원</span></span>
 <span class="change"> 0.50</span>
 <span class="blind">하락</span>
 </div>
 </a>
 <a class="graph_img" href="/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW" onclick="clickcr(this, 'fr1.usdc', '', '', event);">
 <img alt="" height="153" src="https://ssl.pstatic.net/imgfinance/chart/marketindex/FX_USDKRW.png" width="295"/>
 </a>
 <div class="graph_info">
 <span class="time">2023.04.07 22:00</span>
 <span class="source">하나은행 기준</span>
 <span class="count">고시회차<span class="num">321</span>회</span>
 </div>
 </li>,
 <li class="on">
 <a class="head jpy_usd" href="/marketindex/worldExchangeDetail.naver?marketindexCd=FX_USDJPY" onclick="clickcr(this, 'fr2.jpyut', '', '', event);">
 <h3 class="h_lst"><span class="blind">달러/일본 엔</span></h3>
 <div class="head_info point_up">
 <span class="value">132.1100</span>
 <span class="txt_jpy"><span class="blind">엔</span></span>
...</p>
</blockquote>
<pre><code>------------------------------------------------------------------
#### 8. 4개 데이터 수집 (li태그)</code></pre><p>exchange_datas = []
baseurl = &quot;https://finance.naver.com&quot;</p>
<p>for item in exchangeList:
    data = {
        &quot;title&quot;: item.select_one(&quot;.h_lst&quot;).text,
        &quot;exchange&quot; : item.select_one(&quot;.value&quot;).text,
        &quot;change&quot; : item.select_one(&quot;.change&quot;).text,
        &quot;updown&quot; : item.select_one(&quot;div.head_info.point_dn&gt; .blind&quot;),
        &quot;link&quot; : baseurl + item.select_one(&quot;a&quot;).get(&quot;href&quot;)
    }
    print(data)
    exchange_datas.append(data)
exchange_datas</p>
<h1 id="실행결과-3">실행결과</h1>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/71bd62ea-5c97-4046-b920-8d085becff52/image.png)

-------------------------------------------------------------------
#### 9. 태그 리스트 가져오기 

- a 태그 가져오기 </code></pre><p>baseurl = &quot;https://finance.naver.com&quot;
baseurl +exchangeList[0].select_one(&quot;a&quot;).get(&quot;href&quot;) </p>
<h1 id="실행결과-4">실행결과</h1>
<p>&#39;https://finance.naver.com/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW&#39;</p>
<pre><code></code></pre><h1 id="엑셀파일로-저장">엑셀파일로 저장</h1>
<p>df = pd.DataFrame(exchange_datas)
df.to_excel(&quot;./naverfinance.xlsx&quot;)</p>
<pre><code>--------------------------------------------------------------------

#### 10. select로 텍스트 리스트 가져오기</code></pre><ul>
<li>select 사용법 : 클래스는 앞에 점(.) id는 앞에 샾(#)</li>
<li>blind 부분은 2곳에 쓰였으므로 구분해주기 위함</li>
<li>head_info point_dn 는 속성값 - 2개 (head_info 와 point_dn) - 띄어쓰기 주의</li>
<li>띄어쓰기는 점(.)으로 대체 가능</li>
<li>div.head_info.point_dn &gt; .blind 에서 &gt; 는 바로 밑의 하위를 뜻함 (여기서는 &#39;하락&#39;)</li>
<li><blockquote>
<p>가 없다면 첫번째로 나오는 &#39;원&#39; 을 가져옴</p>
</blockquote>
<pre><code></code></pre>title = exchangeList[0].select_one(&quot;.h_lst&quot;).text  # &#39;미국 USD&#39;
exchange = exchangeList[0].select_one(&quot;.value&quot;).text # &#39;1,319.00&#39;
change = exchangeList[0].select_one(&quot;.change&quot;).text
updown = exchangeList[0].select_one(&quot;div.head_info.point_dn &gt; .blind&quot;).text</li>
</ul>
<p>title, exchange, change, updown</p>
<h1 id="실행결과-5">실행결과</h1>
<blockquote>
<blockquote>
</blockquote>
<p>(&#39;미국 USD&#39;, &#39;1,319.00&#39;, &#39; 0.50&#39;, &#39;하락&#39;)</p>
</blockquote>
<pre><code>----------------------------------------------------------------
### BeautifulSoup 예제 2 - 위키백과 문서 정보 가져오기</code></pre><h1 id="google에서-여명의-눈동자-찾으면-위키백과-거기-url의-한글-부분이-숫자와-문자로-섞여서-표현됨">google에서 여명의 눈동자 찾으면 위키백과.. 거기 url의 한글 부분이 숫자와 문자로 섞여서 표현됨.</h1>
<h1 id="깨져있는-제목-부분을-google서-decode-치고-그-중-하나-골라서-오픈-후-위의-url-입력-후-decode한-것을-붙이면-됨">깨져있는 제목 부분을 google서 decode 치고 그 중 하나 골라서 오픈 후 위의 url 입력 후 decode한 것을 붙이면 됨.</h1>
<h1 id="여기서는-그-깨진-한글-부분을-search_words라-표현">여기서는 그 깨진 한글 부분을 {search_words}라 표현</h1>
<p>import urllib
from urllib.request import urlopen, Request
html = &quot;https://ko.wikipedia.org/wiki/{search_words}&quot;</p>
<h1 id="여명의_눈동자">여명의_눈동자</h1>
<h1 id="httpskowikipediaorgwiki여명의_눈동자">https://ko.wikipedia.org/wiki/여명의_눈동자</h1>
<p>req = Request(html.format(search_words=urllib.parse.quote(&quot;여명의_눈동자&quot;))) #글자를 url로 encoding</p>
<p>response = urlopen(req)
soup = BeautifulSoup(response, &quot;html.parser&quot;)
print(soup.prettify)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/32c4f09f-f787-4b57-a2ee-9e4acd3d8553/image.png)
----------------------------------------------------------------------</code></pre><p>n = 0</p>
<p>for each in soup.find_all(&quot;ul&quot;):
    print(&quot;=&gt;&quot; + str(n) + &quot;===========================&quot;)
    print(each.get_text())
    n += 1</p>
<pre><code>   ![](https://velog.velcdn.com/images/jj_study/post/8a6dd992-e4c4-44f3-b20f-24c89ffce40d/image.png)
--------------------------------------------------------------------</code></pre><p>soup.find_all(&quot;ul&quot;)[35].text.strip().replace(&quot;\xa0&quot;,&quot;&quot;)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/46039287-2a94-40c4-a490-1a363c68e498/image.png)

   ---------------------------------------------------------------------
#### Python List 데이터형 (대괄호로 생성)</code></pre><p>colors = [&quot;red&quot;,&quot;blue&quot;,&quot;green&quot;]
colors[0], colors[1], colors[2]</p>
<h1 id="실행결과-6">실행결과</h1>
<pre><code>(&#39;red&#39;, &#39;blue&#39;, &#39;green&#39;)</code></pre><p>b = colors
b</p>
<h1 id="실행결과-7">실행결과</h1>
<pre><code>[&#39;red&#39;, &#39;black&#39;, &#39;green&#39;]</code></pre><p>c = colors.copy()
c</p>
<h1 id="실행결과-8">실행결과</h1>
<pre><code>[&#39;red&#39;, &#39;black&#39;, &#39;green&#39;]</code></pre><p>c[1] =&quot;yellow&quot;
c</p>
<h1 id="실행결과-9">실행결과</h1>
<pre><code></code></pre><h2 id="red-yellow-green">[&#39;red&#39;, &#39;yellow&#39;, &#39;green&#39;]</h2>
<ul>
<li>List형을 반복문(for)적용</li>
</ul>
<p>for color in colors:
    print(color)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/5a0508a3-4229-45ce-84d2-1288fca1da61/image.png)
---------------------------------------------------------------------
- in 명령으로 조건문(if)에 적용
</code></pre><p>if &quot;white&quot; in colors:
    print(&quot;True&quot;)</p>
<pre><code>--------------------------------------------------------------------</code></pre><p>movies = [&quot;라라랜드&quot;,&quot;먼 훗날 우리&quot;,&quot;어벤저스&quot;,&quot;다크나이트&quot;,&quot;타이타닉&quot;]
print(movies)</p>
<pre><code>- append : list 제일 뒤에 추가
- pop : list 제일 뒤부터 자료를 하나씩 삭제</code></pre><p>movies.pop()</p>
<h1 id="실행결과-10">실행결과</h1>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/6b6241be-dd1c-4a5b-8982-ad0a8907494c/image.png)

- extend : 제일 뒤에 자료 추가
- remove : 자료를 삭제
- slicing : [n:m] n번째 부터 n-1
- insert : 원하는 위치에 자료 삽입
- list 안에 list</code></pre><p>favorite_movies.insert(5, [&quot;레오나르도 디카프리오&quot;])
favorite_movies</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/af8cd100-dfee-4fde-a271-7860c93965d6/image.png)
- isinstance(favorite_movies, list)
![](https://velog.velcdn.com/images/jj_study/post/2e2397dc-5bd3-43ba-b596-fe71f732c468/image.png)</code></pre><p>for each_item in favorite_movies:
    if isinstance(each_item, list):
        for nested_item in each_item:
            print(&quot;nested_item&quot;, nested_item)
    else:
        print(&quot;each_item&quot;, each_item)   </p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/b582dab5-fa79-46f6-934c-7308e34cce1c/image.png)
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - 웹데이터 분석 (라이브러리)]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%9B%B9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%9B%B9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</guid>
            <pubDate>Fri, 23 Feb 2024 05:45:07 GMT</pubDate>
            <description><![CDATA[<h3 id="웹데이터-분석을-위한-라이브러리">웹데이터 분석을 위한 라이브러리</h3>
<h4 id="beautiful-soup-4">Beautiful Soup 4</h4>
<ul>
<li>HTML 뿐만 아니라 XML과 같이 태그로 구조화된 언어를 파싱하고 해석 및 검색하는 파이썬 라이브러리</li>
<li>웹 스크레이핑 및 데이터 추출과 같은 작업을 쉽게 수행</li>
</ul>
<h4 id="beautiful-soup-설치">Beautiful Soup 설치</h4>
<pre><code>conda install -c anaconda beautifulsoup4
pip install beautifulsoup4
data
- 3. test_first.html</code></pre><hr>
<h4 id="1-chrome-개발자-도구">1. chrome 개발자 도구</h4>
<ul>
<li>인터넷에 html을 보기 위한 도구</li>
<li>크롬 오른쪽 상단 ... &gt; 도구 더보기 &gt; 개발자 도구 또는 그냥 F12
<img src="https://velog.velcdn.com/images/jj_study/post/d099b6de-28f6-4d00-be09-df38ce8a25ac/image.png" alt=""></li>
</ul>
<p><img src="https://velog.velcdn.com/images/jj_study/post/5d87c97f-bfd1-4928-8478-c6bfaca0c7ab/image.png" alt="">
<img src="https://velog.velcdn.com/images/jj_study/post/1a542953-ffeb-49ec-a1f7-8c388214f7cc/image.png" alt=""></p>
<ul>
<li>원하는 html태그 위치 파악
<img src="https://velog.velcdn.com/images/jj_study/post/6319e1a9-1521-4021-a352-5962f44f6def/image.png" alt=""></li>
</ul>
<h4 id="2-urllib-모듈---request">2. urllib 모듈 - request</h4>
<ul>
<li>웹주소(url)에 접근할 때 필요한 모듈<pre><code>from urllib.request import urlopen
url = &quot;https://finance.naver.com/marketindex/&quot;
page = urlopen(url)
soup = BeautifulSoup(page, &quot;html.parser&quot;)
print(soup.prettify( ))</code></pre><h5 id="requet-임포트-방법-1">requet 임포트 방법 1</h5>
</li>
<li>urlopen(url)<pre><code># 방법 1
from urllib.request import urlopen
from bs4 import BeautifulSoup
</code></pre></li>
</ul>
<p>url = &quot;<a href="https://finance.naver.com/&quot;">https://finance.naver.com/&quot;</a>
reponse = urlopen(url)
reponse.status </p>
<h1 id="200-이라는-숫자가-정상적으로-요청을-했고-정상적으로-받았다는-뜻">200 이라는 숫자가 정상적으로 요청을 했고, 정상적으로 받았다는 뜻</h1>
<h1 id="http-상태코드라고-한다">http 상태코드라고 한다</h1>
<h1 id="번호에-따라서-웹페이지의-상태를-나타낸다">번호에 따라서 웹페이지의 상태를 나타낸다</h1>
<h1 id="그-번호에-따라서-나의-잘못인지-서버오류인지-등을-알-수-있다">그 번호에 따라서 나의 잘못인지, 서버오류인지 등을 알 수 있다.</h1>
<blockquote>
<blockquote>
</blockquote>
<p>200</p>
</blockquote>
<pre><code>##### request 임포트 방법 2
- requests.get(url)</code></pre><h1 id="방법-2">방법 2</h1>
<p>import requests</p>
<h1 id="from-urllibrequestrequest">from urllib.request.Request</h1>
<h1 id="위-requests-와-기능은-똑같다고는-하는데">위 requests 와 기능은 똑같다고는 하는데,</h1>
<h1 id="from-urllibrequestrequest-는-실행하면-에러남">from urllib.request.Request 는 실행하면 에러남</h1>
<p>from bs4 import BeautifulSoup</p>
<p>url = &quot;<a href="https://finance.naver.com/marketindex/&quot;">https://finance.naver.com/marketindex/&quot;</a>
reponse = requests.get(url) </p>
<h1 id="requestsget">requests.get()</h1>
<h1 id="requestspost">requests.post()</h1>
<h1 id="두가지-방식이-있지만-설명은-안해줌">두가지 방식이 있지만 설명은 안해줌</h1>
<p>reponse</p>
<blockquote>
<blockquote>
<p>&lt;Response [200]&gt;</p>
</blockquote>
</blockquote>
<hr>
<p>reponse.text</p>
<blockquote>
<blockquote>
<p>&#39;\n&lt;script language=javascript src=&quot;/template/....</p>
</blockquote>
</blockquote>
<hr>
<pre><code>- http 상태코드가 200 - 정상
- 401 - 인증오류
- 403 - 사용자 허가 모드 오류
- 404 - 요청한 파일이 존재하지 않음
---------------------------------------------------------------------

#### 1. 예제 03) test_first.html
- 파일로 저장된 html파일 읽기
- open : 파일명과 함께 읽기(r) 쓰기(w)속성 지정
- html.parser : Beautiful Soup의 html을 읽는 엔진 중 하나
- prettify( ) : html 출력을 잘 만들어 주는 기능
![](https://velog.velcdn.com/images/jj_study/post/3e5548bb-70f5-4f37-bff2-4d5b976a489c/image.png)
----------------------------------------------------------------------
#### 2. Web page에서 HTML 데이터 가져오기
- computer에 저장된 파일 가져오기</code></pre><h1 id="import">import</h1>
<pre><code>from bs4 import BeautifulSoup
import pandas as pd
page = open(&quot;../data/03. test_first.html&quot;, &quot;r&quot;).read()
soup = BeautifulSoup(page, &quot;html.parser&quot;)
print(soup.prettify( ))</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/fc1d6936-02a0-45c9-8b68-812fb1bb14ad/image.png)

---------------------------------------------------------------</code></pre><h1 id="head-태그-확인">Head 태그 확인</h1>
<p>soup.head</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/93325239-5a2a-4ba4-88ff-e85ad20a8b78/image.png)
</code></pre><h1 id="body-태그-확인">body 태그 확인</h1>
<p>soup.body</p>
<pre><code>- Web에서 데이터 가져오기</code></pre><p>from urllib.request import urlopen
from bs4 import BeautifulSoup</p>
<p>url = &quot;<a href="https://finance.naver.com/&quot;">https://finance.naver.com/&quot;</a>
reponse = urlopen(url)</p>
<p>soup = BeautifulSoup(page, &quot;html.parser&quot;)
print(soup.prettify())</p>
<pre><code>
#### 3. 원하는 태그/속성 검색</code></pre><pre><code>soup.head  # head tag 확인
soup.body  # body tag 확인
soup.title # title tag 확인
soup.div   # div tag 확인
soup.p     # p tag 확인 (상단 하나만 나타남)</code></pre><pre><code>#### 4. p 태그 확인(find, find_all, select)
 ![](https://velog.velcdn.com/images/jj_study/post/ec09bdd5-f809-4d35-8296-bd223eef273e/image.png)
- find(  ) - 변수.find(&#39;태그&#39;)
    - 원하는 특정 태그를 검색하는 데 사용
    - 첫 번째로 일치하는 태그 하나를 찾아 반환
    - 사용하는 인자들은 다양하게 조합하여 활용   </code></pre><pre><code>soup.find(&quot;p&quot;)
# 출력결과
&lt;p class=&quot;inner-text first-item&quot; id=&quot;first&quot;&gt;
            Happy PinkWink.
            &lt;a href=&quot;http://www.pinkwink.kr&quot; id=&quot;pw-link&quot;&gt;PinkWink&lt;/a&gt;
&lt;/p&gt;</code></pre><pre><code></code></pre><h1 id="조건을-좁혀주기">조건을 좁혀주기</h1>
<p>soup.find(&quot;p&quot;, class_=&quot;inner-text first-item&quot;) </p>
<h1 id="출력결과">출력결과</h1>
<p class="inner-text first-item" id="first">
                Happy PinkWink.
                <a href="http://www.pinkwink.kr" id="pw-link">PinkWink</a>
                </p>
```
![](https://velog.velcdn.com/images/jj_study/post/78652553-7ec3-4c2d-a7ff-2d12bab96618/image.png)

<p>또는
<img src="https://velog.velcdn.com/images/jj_study/post/f1904653-e8d6-4360-8bb9-c712773afa0b/image.png" alt=""></p>
<hr>
<ul>
<li><p>find_all(&quot;p&quot;)- 변수.find_all(&#39;태그&#39;) - 여러개 태그 반환</p>
<ul>
<li>지정된 <strong>모든</strong> 태그를 검색하는 데 사용</li>
<li>조건에 맞는 모든 태그를 찾아 리스트로 반환 (soup.find_all(class=&quot;outer-text&quot;)[0] 이런 형태 가능)</li>
<li>반복문을 사용해 각 태그의 텍스트 속성 추출</li>
<li>클래스, 아이디, 속성 등을 지정하여 좀 더 구체적으로 원하는 태그를 찾을 수 있게 함</li>
<li>p태그 중 class가 &quot;outer-text&quot;인 곳 모두 출력<pre><code></code></pre></li>
</ul>
<ul>
<li>특정 태그 확인<pre><code>soup.find_all(id = &quot;pw-link&quot;)
### 실행결과
[&lt;a href=&quot;http://www.pinkwink.kr&quot; id=&quot;pw-link&quot;&gt;PinkWink&lt;/a&gt;]
</code></pre></li>
</ul>
</li>
</ul>
<p>soup.find_all(id=&quot;pw-link&quot;)[0].text</p>
<h3 id="실행결과">실행결과</h3>
<p>&#39;PinkWink&#39;</p>
<p>soup.find_all(&quot;p&quot;, class_=&quot;inner-text second-item&quot;)</p>
<h3 id="실행결과-1">실행결과</h3>
<p>[<p class="inner-text second-item">
                 Happy Data Science.
                 <a href="https://www.python.org" id="py-link">Python</a>
 </p>]</p>
<p>print(soup.find_all(&quot;p&quot;)[0].text)
print(soup.find_all(&quot;p&quot;)[1].string)
print(soup.find_all(&quot;p&quot;)[1].get_text())</p>
<h3 id="실행결과-2">실행결과</h3>
<p> Happy PinkWink.
                PinkWink</p>
<pre><code>            None

            Happy Data Science.
            Python</code></pre><pre><code>soup.find(&quot;p&quot;,{&quot;class&quot;:&quot;outer-text first-item&quot;}).text.strip()

### 실행결과</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/74eeb8c9-01c3-476c-800f-5bdc4b7e14f2/image.png" alt=""></p>
<h3 id="5-p-태그-리스트에서-텍스트-속성만-출력">5. p 태그 리스트에서 텍스트 속성만 출력</h3>
<pre><code>for each_tag in soup.find_all(&quot;p&quot;):
    print(&quot;=&quot; * 50)
    print(each_tag.text)</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/7a187af8-cab8-4079-b257-824e5dc7ff91/image.png" alt=""></p>
<pre><code> soup.find_all(&quot;li&quot;,&quot;on&quot;)(# li 태그의 on 클래스) 와 같은 방법</code></pre><pre><code>soup.find_all(&quot;p&quot;)
soup.find_all(&quot;p&quot;, class_=&quot;inner-text second-item&quot;)
soup.find_all(class_=&quot;outer-text&quot;)
soup.find_all(id=&quot;first&quot;)

soup.find_all(id=&quot;pw-link&quot;)[0].text
soup.find_all(id=&quot;pw-link&quot;)[0].string
soup.find_all(id=&quot;pw-link&quot;)[0].get_text()</code></pre><pre><code></code></pre><h3 id="6-텍스트만-추출">6. 텍스트만 추출</h3>
<ul>
<li>.text와 같은 기능 - (.string / .get_text( ))</li>
<li>해당 텍스트만 나오도록 함</li>
<li>strip( ) 은 공백 지우기, 빈칸이 있는 경우에만 넣음</li>
</ul>
<pre><code>soup.find_all(class_=&quot;outer-text&quot;)[0].text
soup.find(class_=&quot;outer-text&quot;).string
soup.find(class_=&quot;outer-text&quot;).get_text()</code></pre><ul>
<li>예시
<img src="https://velog.velcdn.com/images/jj_study/post/7267598d-0601-4140-91d4-2fa24fb9fad7/image.png" alt=""><pre><code>### strip - 공백지우기 
soup.find(&quot;p&quot;, {&quot;class&quot;: &quot;outer-text first-item&quot;}).text.strip() 
</code></pre></li>
</ul>
<p>실행결과</p>
<blockquote>
<blockquote>
<p>&#39;Data Science is Funny.&#39;</p>
</blockquote>
</blockquote>
<pre><code>- 다중조건
    - p태그 안에 class 속성값 &quot;inner-text first-item&quot;이면서 id속성값이 &quot;first인 것</code></pre><p>soup.find(&quot;p&quot;, {&quot;class&quot;:&quot;inner-text first-item&quot;, &quot;id&quot;:&quot;first&quot;}).text.strip()</p>
<pre><code></code></pre><h3 id="실행결과-3">실행결과</h3>
<blockquote>
<blockquote>
<p>&#39;Happy PinkWink.&#39;</p>
</blockquote>
</blockquote>
<ul>
<li>a 태그에서 href 속성값에 있는 값 추출
links = soup.find_all(&quot;a&quot;)
links[0].get(&quot;href&quot;), links[1][&quot;href&quot;]<pre><code></code></pre><h3 id="실행결과-4">실행결과</h3>
(&#39;<a href="http://www.pinkwink.kr&#39;">http://www.pinkwink.kr&#39;</a>, &#39;<a href="https://www.python.org&#39;">https://www.python.org&#39;</a>)</li>
</ul>
<pre><code></code></pre><h3 id="실행결과-5">실행결과</h3>
<p>PinkWink=&gt;<a href="http://www.pinkwink.kr">http://www.pinkwink.kr</a>
Python=&gt;<a href="https://www.python.org">https://www.python.org</a></p>
<pre><code>
---------------------------------------------------------------
- select_one( ) - 하나 선택
    - 하나의 요소를 선택
    - CSS Selectors나 XPath를 사용해 원하는 요소를 선택하는 데 사용
    - 지정된 CSS Selectors나 XPath에 맞는 첫 번째 요소를 선택해 단일 형태로 반환</code></pre><p>tag_name        : 태그 선택
.class          : 클래스 선택
#id             : 아이디 선택</p>
<blockquote>
<pre><code>          : 특정 요소의 자식 요소 선택</code></pre><p>(space)         : 특정 요소의 모든 하위 요소를 선택
[attribute]     : attribute 속성을 가진 요소 선택
[attribute=value] : attribute 속성 값이 특정 값인 요소 선택
selector1, selector2 : selector1 또는 selector2 요소 선택
selector1 selector2 : selector1 내부의 모든 selector2요소 선택</p>
</blockquote>
<pre><code>- select( ) - 여러 개 선택
    - 여러 요소 선택
    - 상위 하위로 이동이 좀 더 자유로움
    - CSS Selectors나 XPath를 사용해 원하는 요소 선택하는데 사용
    - 지정된 CSS Selectors나 XPath에 맞는 모든 요소를 선택해 리스트 형태로 반환
    - exchangeList = soup.select(&quot;li&quot;)
    - exchangeList = soup.select(&quot;#exchangeList &gt; li&quot;)
    - #exchangeList &gt; li : id exchangeList 바로 밑에(&gt;) li 태그를 모두 가져 옴
    - select 사용 - 클래스는 (.)을 앞에 붙임 / id는 샾(#)을 앞에 붙임


### 태그

title = exchangeList[0].select_one(&quot;.h_lst&quot;).text # &#39;미국 USD&#39;
exchange = exchangeList[0].select_one(&quot;.value&quot;).text # &#39;1,319.00&#39;
change = exchangeList[0].select_one(&quot;.change&quot;).text
updown = exchangeList[0].select_one(&quot;div.head_info.point_dn &gt; .blind&quot;).text
exchangeList[0].select_one(&quot;a&quot;).get(&quot;href&quot;)</code></pre><pre><code>### soup.p

![](https://velog.velcdn.com/images/jj_study/post/d1d30a44-b4d8-4146-9a86-0d9a3c90652e/image.png)

### 7. class 뒤에 언더바 주의
soup.find(&quot;p&quot;, class_=&quot;--&quot;) 
soup.find(&quot;p&quot;, {&quot;class&quot;:&quot;--&quot;})
위 2가지 모두 가능 (동일 반환값)

또는 
soup.find(&quot;p&quot;, {&quot;class&quot;:&quot;--&quot;, &quot;id&quot;:&quot;--&quot;})

### 8. 특정 태그 내용 추출</code></pre><pre><code>soup.find(&quot;p&quot;, {&quot;class&quot;: &quot;outer-text first-item&quot;}).text
soup.find(&quot;p&quot;, {&quot;class&quot;: &quot;outer-text first-item&quot;}).get_text()</code></pre><pre><code>
- get( )
    - 태그 내 특정 속성값을 가져옴
</code></pre><p>soup.find_all(&quot;a&quot;)[0].get(&quot;href&quot;)</p>
<pre><code>
### 9. 외부로 연결되는 링크주소 추출(href)
- a태그에서 href 속성값에 있는 값 추출
![](https://velog.velcdn.com/images/jj_study/post/abd3f27f-b5ba-472a-b50b-f86fd05bc35b/image.png)</code></pre><p>links = soup.find_all(&quot;a&quot;)</p>
<h1 id="printlinks">print(links)</h1>
<h3 id="실행결과-6">실행결과</h3>
<p>[<a href="http://www.pinkwink.kr" id="pw-link">PinkWink</a>,<a href="https://www.python.org" id="py-link">Python</a>]
&#39;&#39;&#39;</p>
<h1 id="printlinks0gethref-links1href">print(links[0].get(&quot;href&quot;), links[1][&quot;href&quot;])</h1>
<p>for each in links:
    href = each.get(&quot;href&quot;) # each[&quot;href&quot;]
    text = each.get_text()
    print(text + &quot; =&gt; &quot; + href)</p>
<pre><code>------------------------------------------------------------------</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - 서울시 범죄 현황데이터 분석 실습]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%84%9C%EC%9A%B8%EC%8B%9C-%EB%B2%94%EC%A3%84-%ED%98%84%ED%99%A9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%84%9C%EC%9A%B8%EC%8B%9C-%EB%B2%94%EC%A3%84-%ED%98%84%ED%99%A9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Fri, 23 Feb 2024 05:04:13 GMT</pubDate>
            <description><![CDATA[<h3 id="1-분석-데이터-개요-확인">1. 분석 데이터 개요 확인</h3>
<h4 id="기본-정보-확인">기본 정보 확인</h4>
<ul>
<li>google Maps API 설치 </li>
<li>모듈 설치 (conda install -c conda-forge googlemaps)</li>
<li>import googlemaps</li>
<li>gmaps_key = &quot;<strong>____</strong>&quot; (본인키 입력)</li>
<li>gmaps=googlemaps.Client(key=gmaps_key)</li>
<li>테스트 해보기 (gmaps.geocode(&quot;서울영등포경찰서&quot;, language=&quot;ko&quot;) (tmp[0].get(&quot;geometry&quot;)[&quot;location&quot;][&quot;lat&quot;]   </li>
</ul>
<pre><code> import numpy as np
 import pandas as pd

# 데이터 읽어오기  (천단위 콤마제거 thousands=&quot;,&quot;)
    crime_raw_data = pd.read_csv(
        &quot;../data/02. crime_in_Seoul.csv&quot;,
        thousands=&#39;,&#39;,
        encoding=&#39;euc-kr&#39;
    )
    crime_raw_data.head()</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/d6773031-2356-43d6-89e3-2a06b6f0c48f/image.png" alt=""></p>
<pre><code>crime_raw_data.info()

# 실행결과</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/781a0c8d-7967-44c5-ae35-3aa5bf7cbebe/image.png" alt=""></p>
<pre><code></code></pre><hr>
<h4 id="데이터-편집">데이터 편집</h4>
<p>(1) 특정 컬럼의 unique 조사</p>
<pre><code>crime_raw_data[&quot;죄종&quot;].unique()

# 실행결과
![](https://velog.velcdn.com/images/jj_study/post/5dde7f98-647c-4f52-bd73-f67b932918ed/image.png)

    &quot;죄종&quot; 컬럼에 &#39;nan&#39;값 존재</code></pre><p>(2) NaN값 제외하고 필요 데이터만 가져옴 (데이터 재편성)</p>
<pre><code>crime_raw_data = crime_raw_data[crime_raw_data[&quot;죄종&quot;].notnull()]
crime_raw_data.info()</code></pre><h5 id="실행결과">실행결과</h5>
<p><img src="https://velog.velcdn.com/images/jj_study/post/9a072933-8cc8-4b47-9975-b37c0ea2f1a0/image.png" alt=""></p>
<pre><code>crime_raw_data.head()</code></pre><p>(3) NaN값 데이터만 가져옴 (데이터 재편성)</p>
<ul>
<li>.isnull( ) : NaN만 추출<pre><code>crime_raw_data[crime_raw_data[&quot;죄종&quot;].isnull()]
</code></pre></li>
</ul>
<h1 id="실행결과-1">실행결과</h1>
<blockquote>
<blockquote>
</blockquote>
</blockquote>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/1dcce7e8-afcb-4b7c-8131-d93a7b30306d/image.png)</code></pre><p>crime_raw_data.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/c71587e9-45a5-4c6e-af80-4fca04a9c3eb/image.png)


---------------------------------------
#### Pandas pivot table
- index, columns, values, aggfunc</code></pre><p>df = pd.read_excel(&quot;../data/02. sales-funnel.xlsx&quot;)
df.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/3b061465-5908-45f9-b7ef-b0c90c308c10/image.png)

- Index 설정</code></pre><p>pd.pivot_table(df, index=&#39;Name&#39;, values=[&#39;Account&#39;,&#39;Quantity&#39;, &#39;Price&#39;])</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/05e88a83-a0b8-4950-a28a-e8617d1af8c8/image.png)
----------------------------------------
- 멀티 인덱스 설정</code></pre><p>pd.pivot_table(df, index=[&#39;Name&#39;,&#39;Rep&#39;,&#39;Manager&#39;], values=[&#39;Account&#39;,&#39;Quantity&#39;, &#39;Price&#39;])</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/25e788f3-935e-4b6e-b4e5-df655b9a7a48/image.png)

pd.pivot_table(df, index=[&#39;Manager&#39;,&#39;Rep&#39;],values=[&#39;Account&#39;,&#39;Quantity&#39;, &#39;Price&#39;] )</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/3183fa41-f777-4005-8516-e67eb7562b70/image.png" alt=""></p>
<ul>
<li>Value 설정<pre><code>df.head()</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/ab793678-1a85-42d7-b03d-c739a1397fad/image.png" alt=""></li>
</ul>
<pre><code>pd.pivot_table(df, index=[&#39;Manager&#39;,&#39;Rep&#39;], values=&#39;Price&#39;)</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/8a4ca0d7-b7c5-4e64-9a19-2be1adc47634/image.png)

- Price 컬럼  sum 연산 적용</code></pre><p>df.pivot_table(index=[&#39;Manager&#39;,&#39;Rep&#39;], values=&#39;Price&#39;, aggfunc=np.sum)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/c8979398-a6a1-441e-becd-dea61459e21a/image.png)
</code></pre><p>df.pivot_table(index=[&#39;Manager&#39;,&#39;Rep&#39;], values=&#39;Price&#39;, aggfunc=[np.sum,len])</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/ec1d1f55-b00a-419d-ab78-c93625bfa23f/image.png)

- Columns 설정</code></pre><p>df.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/61440218-f82e-4a98-9afc-4356ad5b61fd/image.png)
</code></pre><h1 id="product를-columns-으로-지정">Product를 columns 으로 지정</h1>
<p>df.pivot_table(index=[&#39;Manager&#39;,&#39;Rep&#39;], values=&#39;Price&#39;, columns=&#39;Product&#39;, aggfunc=[np.sum,len])</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/e41e15ef-052e-41cf-a9e8-062b6e4a43b4/image.png)


(4) fill_value 옵션: NaN값 설정 (예시)
- NaN값 설정 : fill_value 0으로 채워넣을 경우</code></pre><p>df.pivot_table(index=[&#39;Manager&#39;,&#39;Rep&#39;], values=&#39;Price&#39;, columns=&#39;Product&#39;, aggfunc=np.sum, fill_value=0)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/cd8fc144-0fec-4e39-a12a-0effe02bb4f9/image.png)

--------------------------------------
- 2개 이상  index, values 설정</code></pre><p>df.pivot_table(index=[&#39;Manager&#39;,&#39;Rep&#39;,&#39;Product&#39;], values=[&#39;Price&#39;,&#39;Quantity&#39;], aggfunc=np.sum, fill_value=0)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/457be0b9-d27a-45e6-9024-c85774220290/image.png)

- aggfunc 2개 이상 설정</code></pre><p>df.pivot_table(
    index = [&#39;Manager&#39;,&#39;Rep&#39;,&#39;Product&#39;],
    values=[&#39;Price&#39;,&#39;Quantity&#39;],
    aggfunc=[np.sum, np.mean],
    fill_value=0,
    margins=True) #총계(All)추가</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/f7a9f52d-75ff-4e99-8bde-135d6ade5631/image.png)

-------------------------------------------------------------------
#### 2. 분석 데이터 정리
- Pandas pivot_table()을 이용해 원하는 DataFrame 형태로 데이터 재편성
(1) DataFrame 재편성 - pivot_table() 이용</code></pre><pre><code>import pandas as pd
import numpy as np

crime_station = crime_raw_data.pivot_table(
        index=&quot;구분&quot;,
        columns=[&#39;죄종&#39;, &#39;발생검거&#39;],
        aggfunc=np.sum
)
crime_station.head()</code></pre><pre><code>- 경찰서 이름인 &quot;구분&quot; 컬럼 - Index로 설정
- “죄종”과 “발생검거” 컬럼 - columns로 지정
- 집계 함수의 Default가 &#39;평균(mean)&#39; 이므로 사건의 합이 기록되도록 aggfunc param - ‘합(sum)’ 사용



![](https://velog.velcdn.com/images/jj_study/post/0058c425-ebf8-4aa0-b295-796133296d96/image.png)
--------------------------------------
- multi index</code></pre><p>crime_station.columns  # Multiindex</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/258697f3-8893-4ea6-b6f4-0d082f216ecb/image.png)
</code></pre><p>crime_station.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/d842bd34-7647-4d6f-ba0d-587ae9a079fc/image.png)
</code></pre><h1 id="다중컬럼에서-특정-컬럼-제거-필요없는-sum-건수-컬럼-제거">다중컬럼에서 특정 컬럼 제거 (필요없는 sum, 건수 컬럼 제거)</h1>
<p>crime_station.columns = crime_station.columns.droplevel([0,1]) </p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/3d07f082-e899-4493-b5d6-3d5469999b61/image.png)

</code></pre><p>crime_station.index</p>
<pre><code></code></pre><p>Index([&#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;, &#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;, &#39;혜화&#39;],
      dtype=&#39;object&#39;, name=&#39;구분&#39;)</p>
<pre><code>- 현재 index는 경찰서 이름
- &quot;구별&quot; 범죄 현황을 알기 위함이므로 경찰서 이름을 구 이름으로 변경해야 함

![](https://velog.velcdn.com/images/jj_study/post/646f9039-aaf5-4d1a-8f07-e65d8d963475/image.png)

(2) Python 모듈 설치</code></pre><p>pip 명령
python의 공식 모듈 관리자
pip list
pip install module_name
pip uninstall module_name</p>
<h1 id="pip-list">pip list</h1>
<p>get_ipython().system(&quot;pip list&quot;) # python module설치</p>
<pre><code></code></pre><p>conda 명령
conda list
conda install module_name
conda uninstall module_name
conda install -c channel_name module_name
#지정된 배포 채널에서 모듈 설치
Window mac(intel)</p>
<pre><code>
---------------------------------------------------------------
#### 3. 분석 데이터 추가
- googlemaps를 활용해 경찰서의 이름으로 소속된 구 이름을 알아낸 후 구별로 데이터 정리

(1) 컬럼 추가
- 경찰서가 소속된 구 이름과 위도, 경도 정보를 저장할 새로운 컬럼 생성 (lat / lng)
- 새로 추가한 컬럼의 value - 전부 NaN으로 채움</code></pre><p>import googlemaps
gmaps_key = &quot;나의 키&quot;
gmaps = googlemaps.Client(key=gmaps_key)
tmp = gmaps.geocode(&quot;영등포경찰서&quot;, language = &quot;ko&quot;)
tmp[0].get(&quot;geometry&quot;)[&quot;location&quot;]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/c68e4496-d400-4f11-9aad-a08f0d1a7766/image.png)
</code></pre><h1 id="위도">위도</h1>
<p>print(tmp[0].get(&quot;geometry&quot;)[&quot;location&quot;][&quot;lat&quot;]) </p>
<h1 id="경도">경도</h1>
<p>print(tmp[0].get(&quot;geometry&quot;)[&quot;location&quot;][&quot;lng&quot;]) </p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/c910b629-fb5c-47d7-8a7c-760315e6717f/image.png)</code></pre><p>tmp[0].get(&quot;formatted_address&quot;).split()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/7acf6fd5-f3f1-4f84-8e00-519c8972ed08/image.png)

- 구별  lat lng설정</code></pre><pre><code>crime_station[&quot;구별&quot;] = np.nan
#위도
crime_station[&quot;lat&quot;] = np.nan 
#경도 새 컬럼 만들고 NaN값으로 채움
crime_station[&quot;lng&quot;] = np.nan </code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/fa6def3e-b41b-48dd-a41a-5e0973abbdb1/image.png)



(2) 새로운 데이터 추가
- 경찰서 이름으로 소속된 구이름 받기
    - 구이름과 위도 경도 정보를 저장할 준비
    - 반복문 (iterrows()) 이용 위표의 NaN 부분 모두 채움</code></pre><pre><code>import googlemaps  #iterrows()사용

gmaps = googlemaps.Client(key=&quot;google_api_key&quot;) #나의 api_key 입력

cnt = 0
for idx, row in crime_station.iterrows():
    print(idx)</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/1350c375-c6ee-4ddc-b5a9-d6e788131dc4/image.png)</code></pre><p>tmp[0].get(&quot;formatted_address&quot;).split()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/af39a6cb-5e1c-46e6-beb1-f8babf9696b9/image.png)
</code></pre><p>count = 0
for idx, rows in crime_station.iterrows():
    station_name = &#39;서울&#39; + str(idx) + &#39;경찰서&#39;
    tmp = gmaps.geocode(station_name, language = &#39;ko&#39;)
    if tmp:
        tmp[0].get(&#39;formatted_address&#39;)
        # 주소정보 얻어내기
        tmp_gu = tmp[0].get(&quot;formatted_address&quot;)
        # 위도 경도 정보 가져오기
        lat = tmp[0].get(&quot;geometry&quot;)[&quot;location&quot;][&#39;lat&#39;]
        lng = tmp[0].get(&quot;geometry&quot;)[&quot;location&quot;][&#39;lng&#39;]
        # 컬럼에 값 채우기 
        crime_station.loc[idx, &quot;lat&quot;] = lat
        crime_station.loc[idx, &quot;lng&quot;] = lng
        crime_station.loc[idx, &quot;구별&quot;] = tmp_gu.split()[2]
    print(count)
    count = count + 1</p>
<pre><code>- 데이터 확인</code></pre><p>crime_station.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/14541293-1595-4aee-84b4-b96319a7d940/image.png)
</code></pre><p>crime_station.columns</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/edcdbd53-b45e-4a8e-8087-a7c9930eca76/image.png)
</code></pre><p>crime_station.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/4584e548-07b8-413e-bac8-c893b5a401fb/image.png)
</code></pre><p>crime_station.columns.get_level_values(0)[2]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/5f2292dc-3808-42bc-a1a7-759163734357/image.png)</code></pre><p>crime_station.columns.get_level_values(1)[2]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/00dbec7a-3c9c-4dc8-9e29-6698d5939c38/image.png)


(3) Multi Column 합치기
- &quot;죄종&quot;과 &quot;발생검거&quot; 두 줄로 된 컬럼을 하나로 합침 -&gt; &quot;강도검거&quot;, 강도발생&quot;, ..
- 새로운 컬럼명 리스트를 만들고 데이터에 반영</code></pre><p>tmp = [crime_station.columns.get_level_values(0)[n]
         + crime_station.columns.get_level_values(1)[n]
         for n in range(len(crime_station.columns.get_level_values(0)))]</p>
<h1 id="실행결과-2">실행결과</h1>
<p>[&#39;강간검거&#39;, &#39;강간발생&#39;, &#39;강도검거&#39;, &#39;강도발생&#39;, &#39;살인검거&#39;, &#39;살인발생&#39;,&#39;절도검거&#39;, &#39;절도발생&#39;, &#39;폭력검거&#39;, &#39;폭력발생&#39;, &#39;구별&#39;, &#39;lat&#39;, &#39;lng&#39;]</p>
<p> crime_station.columns = tmp</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/dcabf90c-9f11-4b93-9160-e9fd67c83602/image.png)

(4) Multi index 설정 (예시)
-  인덱스를 여러개 지정 가능</code></pre><p>변수.pivot_table(index =[&quot;컬럼명&quot;,&quot;컬럼명&quot;,&quot;컬럼명&quot;]</p>
<pre><code>(5) value지정 (예시 : values=&quot;컬럼명&quot;)</code></pre><p>변수.pivot_table(index=[&quot;컬럼명&quot;, &quot;컬럼명&quot;], values=&quot;컬럼명&quot;)</p>
<pre><code>(6) aggfunc 옵션 : values에 함수 적용
- value에 함수 적용 (평균외 다른 합산/갯수 등 다른 함수 적용시 aggfunc 옵션 재지정  aggfunc=np.sum)
- 디폴트는 평균 (np.mean)
- 합계 (np.sum)
- 갯수 (len)

   (1) aggfunc 연산이 1개 인 경우</code></pre><p>df.pivot_table(index=[&quot;컬럼명&quot;, &quot;컬럼명&quot;], 
               values=&quot;컬럼명&quot;, 
               columns=&quot;컬럼명&quot;, 
               aggfunc=np.sum, 
               fill_value=0)</p>
<pre><code>   (2) aggfunc 연산이 2개 인 경우 (리스트 감싸서 작성)</code></pre><p>df.pivot_table(index=[&quot;컬럼명&quot;, &quot;컬럼명&quot;], 
               values=&quot;컬럼명&quot;, 
               aggfunc=[np.sum, len])</p>
<pre><code>-----------------------------------------------------------------------
#### 4. &quot;구별&quot; 데이터로 정리
(1) columns 옵션 분류 지정</code></pre><p> #index_col=0은 &#39;구분&#39;을  index 컬럼으로 설정하기 위함
crime_anal_station = pd.read_csv(&quot;../data/02. crime_in_Seoul_raw.csv&quot;, index_col=0, encoding=&quot;utf-8&quot;)
crime_anal_station.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/d262b78a-b039-407b-a739-514c8b7ce5c4/image.png)
</code></pre><p>crime_anal_gu = pd.pivot_table(crime_anal_station, index=&quot;구별&quot;, aggfunc=np.sum)</p>
<h1 id="컬럼-lat-삭제">컬럼 lat 삭제</h1>
<p>del crime_anal_gu[&quot;lat&quot;]
crime_anal_gu.drop(&quot;lng&quot;, axis = 1, inplace = True)
crime_anal_gu.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/bac50692-714e-4472-a041-b9378e9e55d3/image.png)

- 검거율 생성</code></pre><h1 id="검거율-생성">검거율 생성</h1>
<h1 id="하나의-칼럼을-다른-컬럼으로-나누기">하나의 칼럼을 다른 컬럼으로 나누기</h1>
<p>crime_anal_gu[&quot;강도검거&quot;] / crime_anal_gu[&quot;강도발생&quot;]</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/2af1dc57-d3ad-4724-b1b3-6ebbe415e6ec/image.png)

- 다수의 컬럼을 다른 컬럼으로 나누기 (실행 안됨)</code></pre><h1 id=""></h1>
<p>crime_anal_gu[[&quot;강도검거&quot;,&quot;살인검거&quot;]].div(crime_anal_gu[&quot;강도발생&quot;], axis=0)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/e9ea172e-e901-44c2-bd26-77c9a4e3b116/image.png)

- 다수의 컬럼을 다수의 컬럼으로 나누기</code></pre><p>num = [&quot;강간검거&quot;,&quot;강도검거&quot;,&quot;살인검거&quot;,&quot;절도검거&quot;,&quot;폭력검거&quot;]
den = [&quot;강간발생&quot;,&quot;강도발생&quot;,&quot;살인발생&quot;,&quot;절도발생&quot;,&quot;폭력발생&quot;] # den은 denominate
crime_anal_gu[num].div(crime_anal_gu[den].values)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/ccac2236-5e3a-4ca1-a319-5b6916a18426/image.png)

- 다수의 칼럼을 다수의 칼럼으로 나누어 비율계산</code></pre><p>target = [&quot;강간검거율&quot;,&quot;강도검거율&quot;,&quot;살인검거율&quot;,&quot;절도검거율&quot;,&quot;폭력검거율&quot;]
num = [&quot;강간검거&quot;,&quot;강도검거&quot;,&quot;살인검거&quot;,&quot;절도검거&quot;,&quot;폭력검거&quot;]
den = [&quot;강간발생&quot;,&quot;강도발생&quot;,&quot;살인발생&quot;,&quot;절도발생&quot;,&quot;폭력발생&quot;] # den은 denominate
crime_anal_gu[target] = crime_anal_gu[num].div(crime_anal_gu[den].values) * 100
crime_anal_gu.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/36008278-6d01-4c2d-b405-93edb365113a/image.png)

- 필요없는 컬럼 삭제</code></pre><h1 id="필요없는-칼럼-삭제">필요없는 칼럼 삭제</h1>
<p>del crime_anal_gu[&quot;강간검거&quot;]
del crime_anal_gu[&quot;강도검거&quot;]
del crime_anal_gu[&quot;살인검거&quot;]
del crime_anal_gu[&quot;절도검거&quot;]
crime_anal_gu.drop(&quot;폭력검거&quot;, axis = 1, inplace = True)
crime_anal_gu.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/dcb65356-6711-41a7-9085-eb23dc161a50/image.png)

- 100보다 큰 숫자 찾아 바꿔보기</code></pre><p>crime_anal_gu[crime_anal_gu[target] &gt; 100] = 100
crime_anal_gu.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/3c37c812-3d5b-4614-b24e-d220eded2a04/image.png)

- 칼럼 이름 바꾸기</code></pre><p>crime_anal_gu.rename(columns ={&quot;강간발생&quot;:&quot;강간&quot;, &quot;살인발생&quot;:&quot;살인&quot;,&quot;절도발생&quot;:&quot;절도&quot;,&quot;강도발생&quot;:&quot;강도&quot;,&quot;폭력발생&quot;:&quot;폭력&quot;}, inplace = True)
crime_anal_gu.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/85414c7e-c03b-412e-a39a-fd1deb0de9fd/image.png)

#### 범죄 데이터 정렬을 위한 데이터 정리
- 정규화 (최고는 1 최소는 0으로 바꿈)</code></pre><p>col = [&quot;살인&quot;,&quot;강도&quot;,&quot;강간&quot;,&quot;절도&quot;,&quot;폭력&quot;]
crime_anal_norm = crime_anal_gu[col]/crime_anal_gu[col].max()  #정규화
crime_anal_norm.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/4bd6cbb1-7862-47b1-9892-85b2a4b05c05/image.png)

- 검거율 추가</code></pre><p>col2 = [&quot;강간검거율&quot;,&quot;강도검거율&quot;,&quot;살인검거율&quot;,&quot;절도검거율&quot;,&quot;폭력검거율&quot;]
crime_anal_norm[col2] = crime_anal_gu[col2]
crime_anal_norm.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/d969a505-cdf4-4c5a-8db7-75656b87ceb9/image.png)

- 구별 CCTV자료에서 인구수와 CCTV수 추가</code></pre><p>result_CCTV = pd.read_csv(&quot;../data/01. CCTV_result.csv&quot;, index_col=&quot;구별&quot;, encoding=&quot;utf-8&quot;)
result_CCTV.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/3c223fee-9143-4655-ae9d-d3d61d6d6220/image.png)

- 새컬럼 &quot;인구수&quot; &quot;CCTV&quot; 만들되 그 값은 &quot;인구수&quot;,&quot;소계&quot;를 넣음</code></pre><p>crime_anal_norm[[&quot;인구수&quot;,&quot;CCTV&quot;]] = result_CCTV[[&quot;인구수&quot;,&quot;소계&quot;]]
crime_anal_norm.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/9f7c1a7b-64b1-49bb-ba9a-dd07837866c8/image.png)

- 정규화된 범죄발생 건수 전체의 평균을 구해서 범죄  컬럼 대표값으로 사용</code></pre><p>col = [&quot;강간&quot;,&quot;강도&quot;,&quot;살인&quot;,&quot;절도&quot;,&quot;폭력&quot;]
crime_anal_norm[&quot;범죄&quot;] = np.mean(crime_anal_norm[col], axis=1)
crime_anal_norm.head()</p>
<pre><code>- ![](https://velog.velcdn.com/images/jj_study/post/2df086c9-7d12-472f-9fb0-65f723eb0891/image.png)
----------------------------------------

- np.mean( )</code></pre><h1 id="한-예로-강남구의-살인-강도-강간-절도-폭력-정규화-한것을-평균을-내준-것임">한 예로 강남구의 살인, 강도, 강간, 절도, 폭력 정규화 한것을 평균을 내준 것임</h1>
<p>np.mean(np.array([0.357143, 1.000000, 1.000000, 0.977118, 0.73377]))</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/4720665c-9d8b-4040-baa1-9c6a72792c32/image.png)
</code></pre><p>#numpy는 axis = 1 이 행이고, axis = 0 열이다  *** 보통과 반대임 (Pandas는 그 반대임)
np.mean(np.array(
    [[0.357143, 1.000000, 1.000000, 0.977118, 0.73377],
     [0.285714, 0.358974, 0.310078, 0.477799, 0.463880]]
), axis = 1)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/4ba05c94-42e5-4815-a4b5-bdb10f76de05/image.png)

</code></pre><p>#numpy는 axis = 1 이 행이고, axis = 0 열이다  *** 보통과 반대임 (Pandas는 그 반대임)</p>
<h1 id="강남구---그밑은-강동구-2차원이상의-배열이-됨">강남구  # 그밑은 강동구 2차원이상의 배열이 됨</h1>
<p>np.mean(np.array(
    [[0.357143, 1.000000, 1.000000, 0.977118, 0.73377],
     [0.285714, 0.358974, 0.310078, 0.477799, 0.463880]]
), axis = 0)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/62be5e7b-90c0-4b5b-b617-2fda012c8e44/image.png)


- 검거율의 평균을 구해서 검거 칼럼의 대표값으로 사용</code></pre><p>col = [&quot;강간검거율&quot;,&quot;강도검거율&quot;,&quot;살인검거율&quot;,&quot;절도검거율&quot;,&quot;폭력검거율&quot;]
crime_anal_norm[&quot;검거&quot;] = np.mean(crime_anal_norm[col], axis = 1) # axis = 1은 행을 따라 연산하는 옵션
crime_anal_norm.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/deb18846-466f-404d-8d60-31633d372162/image.png)


----------------------------------------------------------------------
-------------------------------------------------------------------
#### 7. 분석 데이터 지도 시각화
(1) 시각화 준비
- 구별 5대 범죄 발행 현황을 지도에 시각화하고 경찰서별 검거율을 경찰서 위치 기준으로 원으로 표시
([시각화 관련 참고자료](https://brunch.co.kr/@catloaf/61))</code></pre><p>import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import rc
plt.rcParams[&quot;axes.unicode_minus&quot;] = False
get_ipython().run_line_magic(&quot;matplotlib&quot;,&quot;inline&quot;)
rc(&quot;font&quot;, family=&quot;Malgun Gothic&quot;)</p>
<p> crime_anal_norm = pd.read_csv(
        &quot;./result_data/06_crime_in_seoul_final.csv&quot;,  index_col=0, encoding=&quot;utf-8&quot;
    )</p>
<p>crime_anal_norm.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/9103bc29-72d8-444d-8623-8a97f326d3e7/image.png)

--------------------------------------------------------------------
- #pairplot 강도, 살인, 폭력에 대한 상관관계 확인</code></pre><p>sns.pairplot(data=crime_anal_norm, vars=[&quot;살인&quot;,&quot;강도&quot;,&quot;폭력&quot;], kind=&quot;reg&quot;, height=3) #reg는 회귀</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/94673162-2d1b-41dc-8b6a-2cc106b25995/image.png)
</code></pre><p>crime_anal_norm.head(1)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/52ad3fdf-369b-4cae-b054-9f71915d35be/image.png)

![](https://velog.velcdn.com/images/jj_study/post/b8507823-4e01-43a2-ab0d-ed5558e133e3/image.png)


- &quot;인구수&quot;,&quot;CCTV&quot;와 &quot;살인&quot;,&quot;강도&quot;의 상관관계 확인</code></pre><p>def drawGraph():
    sns.pairplot(
        data=crime_anal_norm,
        x_vars=[&quot;인구수&quot;,&quot;CCTV&quot;],
        y_vars=[&quot;살인&quot;,&quot;강도&quot;],
        kind=&quot;reg&quot;,
        height=4
    )
    plt.show()
drawGraph()</p>
<pre><code>- #&quot;인구수&quot;,&quot;CCTV&quot;와 &quot;살인검거율&quot;,&quot;폭력검거율&quot;의 상관관계 확인</code></pre><p>def drawGraph():
    sns.pairplot(
        data=crime_anal_norm,
        x_vars=[&quot;인구수&quot;,&quot;CCTV&quot;],
        y_vars=[&quot;살인검거율&quot;,&quot;폭력검거율&quot;],
        kind=&quot;reg&quot;,
        height=4
    )
    plt.show()
drawGraph()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/76a9040c-048d-4737-9bf0-26fadf8cfd9e/image.png)
</code></pre><p>crime_anal_norm.head(3)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/3fdb5f49-d1bb-45d4-8b9c-dd539995c0c9/image.png)
------------------------------------------
- 검거율 Heatmap</code></pre><p>#검거율 heatmap
#&quot;검거&quot; 칼럼을 기준으로 정렬</p>
<p>def drawGraph():
    #데이터 프레임 생성
    target_col = [&quot;강간검거율&quot;,&quot;강도검거율&quot;,&quot;살인검거율&quot;,&quot;절도검거율&quot;,&quot;폭력검거율&quot;,&quot;검거&quot;]
    crime_anal_norm_sort = crime_anal_norm.sort_values(by=&quot;검거&quot;, ascending=False) #내림차순</p>
<pre><code># 그래프 설정
plt.figure(figsize=(10,10))
sns.heatmap(
    data=crime_anal_norm_sort[target_col],
    annot=True, #데이터값 표현
    fmt =&quot;f&quot;, #float 실수
    linewidths=0.5, #박스간 간격설정
    cmap=&quot;RdPu&quot;,
)
plt.title(&quot;범죄 검거 비율(정규화된 검거의 합으로 정렬)&quot;)
plt.show()</code></pre><p>drawGraph()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/cfec0495-f93b-402d-ad22-1390b189d951/image.png)

- 범죄발생 건수 Heatmap</code></pre><p>#범죄발생 건수 heatmap
#&quot;범죄&quot; 컬럼을 기준으로 정렬</p>
<p>def drawGraph():
    # 데이터프레임 생성
    target_col = [&quot;살인&quot;,&quot;강도&quot;,&quot;강간&quot;,&quot;절도&quot;,&quot;폭력&quot;,&quot;범죄&quot;]
    crime_anal_norm_sort = crime_anal_norm.sort_values(by=&quot;범죄&quot;, ascending=False)#내림차순</p>
<pre><code>#그래프 설정
plt.figure(figsize = (10,10))
sns.heatmap(
    data = crime_anal_norm_sort[target_col],
    annot = True, #데이터값 표현
    fmt=&quot;f&quot;, #float 실수
    linewidths=0.5, #박스간 간격
    cmap=&quot;RdPu&quot;,
)
plt.title(&quot;범죄 비율(정규화된 발생건수로 정렬)&quot;)
plt.show()</code></pre><p>drawGraph()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/1d49d368-6a13-455c-ae12-17efaeb7f8ca/image.png)
--------------------------------------
- 데이터 저장</code></pre><h1 id="데이터-저장">데이터 저장</h1>
<p>crime_anal_norm.to_csv(&quot;../data/02. crime_in_Seoul_final.csv&quot;, sep=&quot;,&quot;, encoding=&quot;utf-8&quot;)</p>
<pre><code>--------------------------------------------------------------------
--------------------------------------------------------------------
### folium - python에서 지리적 데이터 시각화 위한 라이브러리로 지도 만들기</code></pre><p>!pip3 install folium
!pip install folium</p>
<h1 id="window">Window</h1>
<p>#!pip install cmake
#!pip install cython
#!pip install datadotworld[pandas]
#!pip install wheel
!pip install charset
!pip install charset-normalizer</p>
<pre><code></code></pre><p>import folium
import pandas as pd
import json
import numpy as np</p>
<p>crime_anal_norm = pd.read_csv(&quot;../data/02. crime_in_Seoul_final.csv&quot;, index_col=0, encoding=&quot;utf-8&quot;)
geo_path=&quot;../data/02. skorea_municipalities_geo_simple.json&quot;
geo_str = json.load(open(geo_path, encoding=&quot;utf-8&quot;))</p>
<pre><code></code></pre><p>crime_anal_norm.tail(2)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/144273cd-f4fd-496c-bb7e-5e4549b3761e/image.png)


- folium.Map( )
- location: tuple or list, default None
- Latitude and Longitude of Map(Northing, Easting).

----------------------------------------------------
-----------</code></pre><p>m = folium.Map(localization=[37.544564958079896, 127.05582307754338], zoom_start=18)
m</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/9747820b-e364-4248-b9e0-a30bbe9ceea2/image.png)
</code></pre><p>m.save(&quot;./folium.html&quot;)</p>
<pre><code>- tiles option
&quot;OpenStreetMap&quot;
&quot;Mapbox Bright (Limited levels of zoom for free tiels)
&quot;Mapbox Control Room&quot; (Limited levels of zoom for free tiles)
&quot;Stamen&quot; (Terrain, Toner, and Watercolor)
&quot;Cloudmade&quot; (Must pass API key)
&quot;Mapbox&quot; (Must pass API key)
&quot;CartoDB&quot; (position and dark_matter)

- 살인 발생건수 지도 시각화 - tile이 더 이상 무료가 아니라는...</code></pre><h1 id="살인발생-건수-지도-시각화---tile이-더이상-무료가-아니라는">살인발생 건수 지도 시각화 - tile이 더이상 무료가 아니라는.....</h1>
<p>my_map = folium.Map(
    location=[37.5502, 126.982],
    zoom_start=11,
    tiles=&quot;Stamen Toner&quot;
)
folium.Choropleth(
     geo_data=geo_str, #우리나라 경계선 좌표값이 담긴 데이터
     data=crime_anal_norm[&quot;살인&quot;],
     columns=[crime_anal_norm.index, crime_anal_norm[&quot;살인&quot;]],
     key_on=&quot;feature.id&quot;,
     fill_color=&quot;PuRd&quot;,
     fill_opacity=0.7,
     line_opacity=0.2,
     legend_name=&quot;정규화된 살인 발생 건수&quot;
 ).add_to(my_map)</p>
<p>my_map</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/64f68759-a65e-4e40-be97-5b5100338083/image.png)

---------------------------------------------------------------
</code></pre><p>crime_anal_norm.head(2)</p>
<pre><code></code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/c231c5ef-79d4-470e-bd9b-7657e405b114/image.png" alt=""></p>
<hr>
<ul>
<li>성범죄 건수 지도 시각화 - tile이 더이상 무료가 아니라는</li>
<li>강남 3구 중 2개 구 포함<pre><code>my_map = folium.Map(location=[37.5502, 126.982], zoom_start=11, tiles=&quot;Stamen Toner&quot;)
</code></pre></li>
</ul>
<p>my_map.choropleth(
    geo_data=geo_str, # 우리나라 경계선 좌표값이 담긴 데이터
    data=crime_anal_norm[&quot;강간&quot;],
    columns=[crime_anal_norm.index, crime_anal_norm[&quot;강간&quot;]],
    fill_color=&quot;PuRd&quot;,
    key_on=&quot;feature.id&quot;,
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name=&quot;정규화된 강간 발생 건수&quot;,
)</p>
<p>my_map</p>
<pre><code></code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/6a10725e-1c89-42ec-9904-c27fce731448/image.png" alt=""></p>
<pre><code>crime_anal_norm.head()</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/52c82e2b-26a6-4bc2-91f4-bb4f1a6c3a2f/image.png" alt=""></p>
<hr>
<pre><code>(https://velog.velcdn.com/images/jj_study/post/881ff0d1-2c24-4ae6-ba1f-fc553faeb4ff/image.png)

--------------------------------------------------------------------
- 구별 범죄 현황과 경찰서별 검거 현황
- 5대 범죄 발생 비율 시각화 - tile이 더이상 무료 아님</code></pre><p>my_map = folium.Map(
    location=[37.5502, 126.982],
    zoom_start=11,
    tiles=&quot;Stamen Toner&quot;
)
folium.Choropleth(
     geo_data=geo_str, #우리나라 경계선 좌표값이 담긴 데이터
     data=crime_anal_norm[&quot;범죄&quot;],
     columns=[crime_anal_norm.index, crime_anal_norm[&quot;범죄&quot;]],
     key_on=&quot;feature.id&quot;,
     fill_color=&quot;PuRd&quot;,
     fill_opacity=0.7,
     line_opacity=0.2,
     legend_name=&quot;정규화된 5대 범죄 발생 건수&quot;
 ).add_to(my_map)</p>
<p>my_map</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/4892be9d-f7db-4b84-9fb5-e9caed839324/image.png)
-----------------------------------------------------------------</code></pre><ul>
<li>인구 대비 범죄 발생 건수 시각화</li>
</ul>
<pre><code>tmp_criminal = crime_anal_norm[&quot;범죄&quot;] / crime_anal_norm[&quot;인구수&quot;] # 인구수 대비 범죄발생 비율 

my_map = folium.Map(location=[37.5502, 126.982], zoom_start=11, tiles=&quot;Stamen Toner&quot;)

my_map.choropleth(
    geo_data=geo_str,
    data=tmp_criminal,
    columns=[crime_anal_norm.index, tmp_criminal],
    fill_color=&quot;PuRd&quot;,
    key_on=&quot;feature.id&quot;,
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name=&quot;정규화된 범죄 발생 건수&quot;,
)

my_map</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/63487796-c2e7-46e6-b286-3ccce1a6adec/image.png" alt=""></p>
<hr>
<ul>
<li>경찰서별 검거현황과 구별 범죄발생 현황 표현<pre><code>import numpy as np
</code></pre></li>
</ul>
<p>crime_anal_station = pd.read_csv(
    &quot;../data/02. crime_in_Seoul_1st.csv&quot;, index_col=0, encoding=&quot;utf-8&quot;
)
crime_anal_station.tail(2)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/99c4557b-888d-4a4b-bef4-2b1714f77c1b/image.png)
</code></pre><p>crime_anal_station.columns</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/21b278c0-41ac-48e1-84ff-da337d98f3a0/image.png)
</code></pre><p>crime_anal_station = crime_anal_station.rename(columns={&quot;Unnamed: 0&quot;:&quot;Unnamed&quot;})
del crime_anal_station[&quot;Unnamed&quot;]</p>
<pre><code></code></pre><p>crime_anal_station.tail(2)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/f8c1382c-8c5b-4f72-a489-e68334948315/image.png)

- 정규화</code></pre><p>col = [&quot;살인검거&quot;, &quot;강도검거&quot;, &quot;강간검거&quot;, &quot;절도검거&quot;, &quot;폭력검거&quot;]</p>
<h1 id="정규화">정규화</h1>
<p>tmp = crime_anal_station[col] / crime_anal_station[col].max() </p>
<pre><code></code></pre><p>crime_anal_station[&quot;살인검거&quot;].max()  #최대값</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/6283d7b5-9e72-4d03-aa3c-69178ddf3954/image.png)
</code></pre><p>crime_anal_station[&quot;살인검거&quot;] / 13</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/bb666cbf-c3d6-4973-b261-8f12bc856d2f/image.png)
</code></pre><p>col = [&quot;살인검거&quot;, &quot;강도검거&quot;, &quot;강간검거&quot;, &quot;절도검거&quot;, &quot;폭력검거&quot;]
tmp = crime_anal_station[col] / crime_anal_station[col].max()  # 정규화
crime_anal_station[&quot;검거&quot;] = np.mean(tmp, axis=1) # 행 가로 의미  (각종 검거들의 평균을 검거로..)
crime_anal_station.tail()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/95626c44-7d10-41ff-bfbd-a3113a1b11b7/image.png)



(7) 경찰서 위치를 지도에 표시 (Marker)</code></pre><p>my_map = folium.Map(location=[37.5502, 126.982], zoom_start=11)</p>
<p>for idx, rows in crime_anal_station.iterrows():
    folium.Marker([rows[&quot;lat&quot;], rows[&quot;lng&quot;]]).add_to(my_map)</p>
<p>my_map</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/54ea5b53-a43d-4ce5-a276-1de6e5ec266e/image.png)


(7) 검거에 적절한 값을 곱해서 원의 넓이로 사용</code></pre><p>my_map = folium.Map(
    location = [37.5502, 126.962], zoom_start=11
)</p>
<p>folium.Choropleth(
    geo_data=geo_str,
    data=crime_anal_norm[&quot;범죄&quot;],
    columns=[crime_anal_norm.index, crime_anal_norm[&quot;범죄&quot;]],
    key_on=&quot;feature.id&quot;,
    fill_color=&quot;PuRd&quot;,
    fill_opacity=0.7,
    line_opacity=0.2<br>).add_to(my_map)</p>
<p>for idx, rows in crime_anal_station.iterrows():
    folium.CircleMarker(
        location=[rows[&quot;lat&quot;], rows[&quot;lng&quot;]],
        radius=rows[&quot;검거&quot;] * 50,
        popup=rows[&quot;구분&quot;] + &quot; : &quot; + &quot;%.2f&quot; % rows[&quot;검거&quot;],  #소수점 2째 짜리까지 보여주기
        color=&quot;#3186cc&quot;,
        fill=True,
        fill_color = &quot;#3186cc&quot;
    ).add_to(my_map)</p>
<p>my_map</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/0bf84a78-64b8-4a88-b107-5bdd569eddfe/image.png)


-----------------------------------------------------------------
- folium.ClickForMarker( )
- 지도 위에 마우스로 클릭했을 때 마커 생성
</code></pre><p>m = folium.Map(
    location=[37.544564958079896, 127.05582307754338],  #성수역
    zoom_start=14,
    tiles=&quot;OpenStreetMap&quot;
) # 0-18</p>
<p>m.add_child(folium.ClickForMarker(popup=&quot;ClickForMarker&quot;))</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/8218c7e2-bea7-42ff-adb5-f56939c724db/image.png)
---------------------------------------

- folium.LatLngPopup() 
- 지도 마우스로 클릭 시 위도 경도 정보 반화
</code></pre><p>m = folium.Map(
    location=[37.544564958079896, 127.05582307754338],  #성수역
    zoom_start=14,
    tiles=&quot;OpenStreetMap&quot;
) # 0-18</p>
<p>m.add_child(folium.LatLngPopup())</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/89e2ece8-f243-4234-8df4-6a515754715f/image.png)

(9) 서울시 범죄 현황 발생 장소 분석
- 오래된 데이터 지만 서울 대상에는 문제 없는 무료 json파일
- https://github.com/southkorea/southkorea-maps/blob/master/kostat/2013/json/skorea_municipalities_geo_simple.json

- 최초 받았던 발생 장소별 데이터 확인</code></pre><p>crime_loc_raw = pd.read_csv(
    &quot;../data/02. crime_in_Seoul_location.csv&quot;, thousands=&quot;,&quot;, encoding=&quot;euc-kr&quot;
)
crime_loc_raw.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/36fb7f0e-62a8-4364-b412-23ca1ed4fefb/image.png)

----------------------------------------------------------------------</code></pre><p>crime_loc_raw[&quot;범죄명&quot;].unique()</p>
<blockquote>
<blockquote>
</blockquote>
<p>array([&#39;살인&#39;, &#39;강도&#39;, &#39;강간.추행&#39;, &#39;절도&#39;, &#39;폭력&#39;], dtype=object)</p>
</blockquote>
<pre><code>------------------------------------------------------------------------</code></pre><p>crime_loc_raw[&quot;장소&quot;].unique()</p>
<blockquote>
<blockquote>
</blockquote>
<p>array([&#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;], dtype=object)```</p>
</blockquote>
<hr>
<ul>
<li>피봇테이블 생성<pre><code>crime_loc = crime_loc_raw.pivot_table(
  crime_loc_raw, index = &quot;장소&quot;, columns = &quot;범죄명&quot;, aggfunc=[np.sum]
)
crime_loc.tail(2)</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/5bce6c45-7eab-4752-b1a6-3d7b90e835ec/image.png" alt=""></li>
</ul>
<hr>
<pre><code>-sum, 발생건수 column 삭제</code></pre><p>crime_loc = crime_loc_raw.pivot_table(
    crime_loc_raw, index = &quot;장소&quot;, columns = &quot;범죄명&quot;, aggfunc=[np.sum]
)
crime_loc.columns = crime_loc.columns.droplevel([0,1]) # multi index 때문에 이렇게 해주는 것임
crime_loc.tail(2)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/9e215c0a-cf6b-45b0-b992-2725eea70319/image.png)
--------------------------------------
- 정규화</code></pre><p>col = [&quot;살인&quot;, &quot;강도&quot;, &quot;강간&quot;, &quot;절도&quot;, &quot;폭력&quot;]
crime_loc_norm = crime_loc / crime_loc.max()
crime_loc_norm.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/3bf0a19e-655c-4b10-b807-47c2c479af09/image.png)
---------------------------------------</code></pre><ul>
<li>종합 컬럼 추가
crime_loc_norm[&quot;종합&quot;]= np.mean(crime_loc_norm, axis = 1)  #numpy에서 axis=1은 행을 나타냄
crime_loc_norm.tail(2)<pre><code>![](https://velog.velcdn.com/images/jj_study/post/3696c34b-350e-42a1-93f3-a8b68476e0bb/image.png)
</code></pre></li>
</ul>
<hr>
<hr>
<h4 id="matplotlib">matplotlib</h4>
<pre><code># setting

import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import rc

rc(&quot;font&quot;, family=&quot;Malgun Gothic&quot;)  # 한글 폰트 사용
%matplotlib inline
# seaborn은 matplotlib과 함께 실행된다</code></pre><pre><code>crime_loc_norm_sort = crime_loc_norm.sort_values(&quot;종합&quot;, ascending = False) #내림차순

def drawGraph():
    plt.figure(figsize=(10,10))
    sns.heatmap(
        crime_loc_norm_sort,
        annot=True,
        fmt=&quot;f&quot;,
        linewidths=0.5, #간격 살짝 떨어지게
        cmap=&quot;RdPu&quot;)
    plt.title(&quot;범죄 발생 장소&quot;)
    plt.show()
drawGraph()</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/0233bdb9-f14a-4628-b10b-6290bc535228/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - 서울시 범죄 현황데이터 분석 (라이브러리)
]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%84%9C%EC%9A%B8%EC%8B%9C-%EB%B2%94%EC%A3%84%ED%98%84%ED%99%A9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%EC%97%90-%EC%82%AC%EC%9A%A9%EB%90%9C-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%84%9C%EC%9A%B8%EC%8B%9C-%EB%B2%94%EC%A3%84%ED%98%84%ED%99%A9%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%EC%97%90-%EC%82%AC%EC%9A%A9%EB%90%9C-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</guid>
            <pubDate>Fri, 23 Feb 2024 02:20:41 GMT</pubDate>
            <description><![CDATA[<h3 id="pandas-pivot-table">Pandas Pivot Table</h3>
<h4 id="pandas에서-pivot_table-함수는-dataframe의-데이터를-재구성하고-집계하는-데-사용되는-함수로-재구성된-dataframe을-반환">pandas에서 pivot_table() 함수는 DataFrame의 데이터를 재구성하고 집계하는 데 사용되는 함수로 재구성된 DataFrame을 반환</h4>
<pre><code>pandas.pivot_table(df_data, index=, columns=, values=, aggfunc=)</code></pre><ul>
<li>index   : 새로운 테이블의 인덱스로 사용될 열</li>
<li>columns : 새로운 테이블의 열로 사용될 열</li>
<li>values  : pivot할 값으로 재집계가 가능한 수치 값</li>
<li>aggfunc : 집계 함수로, 겹치는 값이 있는 경우 어떻게 처리할 지 지정.  디폴트 함수는 &#39;평균&#39;</li>
</ul>
<h4 id="google-maps-api">Google Maps API</h4>
<ul>
<li>googlemaps 패키지는 파이썬에서 구글 맵스 API를 사용할 수 있도록 도와주는 서드파티 라이브러리(Third Party Library)</li>
<li>구글 맵스 위치 기반 서비스, 지리적 정보 처리, 길찾기 등 다양한 기능 활용가능</li>
<li>구글맵 이용해서 구글 검색처럼 경찰서 이름 검색해서 해당 구를 알아낼 수 있음</li>
<li>Google Map API Key 필요</li>
</ul>
<hr>
<pre><code># google Maps API설치
conda install googlemaps
# 모듈 설치
conda install -c conda-forge googlemaps

import googlemaps

    # 구글 클라우드 플랫폼에서 발급받은 API 키 입력
    api_key = &#39;______&#39; (본인의 key 넣기)

    # Google Maps 클라이언트 생성
    gmaps = googlemaps.Client(key=api_key)

    # 주소를 좌표로 변환
    gmaps.geocode(&#39;서울영등포경찰서&#39;, language=&quot;ko&quot;)</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/10ff2a97-6e99-4436-bfce-908fb883cc8a/image.png" alt="">
<img src="https://velog.velcdn.com/images/jj_study/post/3739e800-3158-460a-9014-5d65cc426dfa/image.png" alt=""></p>
<pre><code>tmp = gmaps.geocode(&quot;서울영등포경찰서&quot;, language=&quot;ko&quot;)
tmp[0].get(&quot;geometry&quot;)[&quot;location&quot;][&quot;lat&quot;]
# 실행결과
&gt;&gt; 37.5260441</code></pre><hr>
<ul>
<li>구글맵 API에서 데이터 얻기</li>
<li>전체 결과 크기가 1인 리스트형이라 tmp[0]으로 접근</li>
<li>큰 리스트 안에 dictionary형</li>
<li>dictionary형에서 데이터 얻는 get명령 사용</li>
</ul>
<hr>
<ul>
<li>전체 주소엣 필요한 구 이름만 가져오기<pre><code>tmp[0].get(&quot;formatted_address&quot;).split()[2]
</code></pre></li>
</ul>
<blockquote>
<blockquote>
<p>&#39;영등포구&#39;</p>
</blockquote>
</blockquote>
<p>crime_station.head()</p>
<pre><code>----------------------------------------------------
### Seaborn
- P  데이터 시각화 라이브러리 중 하나로 통계 데이터를 시각화
- matplotlib와 함께 실행  (“tips” data, “flights” data, “iris” data, “anscombe” data, …)
- 그래프 형태 (boxplot / swarmplot / lmplot / heatmap / pairplot)
- [seaborn tutorial](https://seaborn.pydata.org/tutorial.html)
- seaborn 설치 (!conda install -y seaborn)
- seaborn import</code></pre><h2 id="setting">setting</h2>
<p>import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import rc</p>
<p>plt.rcParams[&quot;axes.unicode_minus&quot;] = False  # 마이너스 기호 사용
rc(&quot;font&quot;, family=&quot;Malgun Gothic&quot;)  # 한글 폰트 사용
get_ipython().run_line_magic(&quot;matplotlib&quot;, &quot;inline&quot;) </p>
<pre><code>----------------------------------------------------------------
#### 예제 np.linspace(0, 14, 100)
- 예제, 0부터 14 사이 100개 값 생성</code></pre><p>x = np.linspace(0, 14, 100)
x</p>
<blockquote>
<blockquote>
</blockquote>
<p>array([ 0.        ,  0.14141414,  0.28282828,  0.42424242,  0.56565657,
        0.70707071,  0.84848485,  0.98989899,  1.13131313,  1.27272727,
        1.41414141,  1.55555556,  1.6969697 ,  1.83838384,  1.97979798,
        2.12121212,  2.26262626,  2.4040404 ,  2.54545455,  2.68686869,
        2.82828283,  2.96969697,  3.11111111,  3.25252525,  3.39393939,
        3.53535354,  3.67676768,  3.81818182,  3.95959596,  4.1010101 ,
        4.24242424,  4.38383838,  4.52525253,  4.66666667,  4.80808081,
        4.94949495,  5.09090909,  5.23232323,  5.37373737,  5.51515152,
        5.65656566,  5.7979798 ,  5.93939394,  6.08080808,  6.22222222,
        6.36363636,  6.50505051,  6.64646465,  6.78787879,  6.92929293,
        7.07070707,  7.21212121,  7.35353535,  7.49494949,  7.63636364,
        7.77777778,  7.91919192,  8.06060606,  8.2020202 ,  8.34343434,
        8.48484848,  8.62626263,  8.76767677,  8.90909091,  9.05050505,
        9.19191919,  9.33333333,  9.47474747,  9.61616162,  9.75757576,
        9.8989899 , 10.04040404, 10.18181818, 10.32323232, 10.46464646,
       10.60606061, 10.74747475, 10.88888889, 11.03030303, 11.17171717,
       11.31313131, 11.45454545, 11.5959596 , 11.73737374, 11.87878788,
       12.02020202, 12.16161616, 12.3030303 , 12.44444444, 12.58585859,
       12.72727273, 12.86868687, 13.01010101, 13.15151515, 13.29292929,
       13.43434343, 13.57575758, 13.71717172, 13.85858586, 14.        ])</p>
</blockquote>
<pre><code>- 4개의 실선 데이터 생성</code></pre><p>x = np.linspace(0, 14, 100)
y1 = np.sin(x)
y2 = 2 * np.sin(x + 0.5)
y3 = 3 * np.sin(x + 1.0)
y4 = 4 * np.sin(x + 1.5)</p>
<pre><code>- plot( ) 그래프</code></pre><p>plt.figure(figsize=(10, 6))
plt.plot(x, y1, x, y2, x, y3, x, y4)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/aa477579-66cf-476c-bb5d-0a9470ffd02b/image.png)

- despine 옵션 (x축, y축과 그래프 사이 간격 벌리기)</code></pre><p>plt.figure(figsize=(10, 6))
plt.plot(x, y1, x, y2, x, y3, x, y4)
sns.despine(offset=30)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/ddf250b2-ee71-4dd4-8025-20a5b457af57/image.png)

- set_style( ) 옵션
5가지 종류 : white, dark, whitegrid, darkgrid, ticks</code></pre><p>sns.set_style(&quot;white&quot;)
plt.figure(figsize=(10, 6))
plt.plot(x, y1, x, y2, x, y3, x, y4) # 쌍으로 넣어주면 4개의 실선 데이터가 생성된다.
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/f67b527c-ab6e-4b88-b6d0-a60fb7e34ccb/image.png)
</code></pre><p>sns.set_style(&quot;dark&quot;)
plt.figure(figsize=(10, 6))
plt.plot(x, y1, x, y2, x, y3, x, y4)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/093213cf-53a6-4641-89a5-3afc4220ca59/image.png)
</code></pre><p>sns.set_style(&quot;whitegrid&quot;)
plt.figure(figsize=(10, 6))
plt.plot(x, y1, x, y2, x, y3, x, y4)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/ec8bddf4-2d9d-4b0f-acb4-bc766fc54f0a/image.png)
</code></pre><p>sns.set_style(&quot;darkgrid&quot;)
plt.figure(figsize=(10, 6))
plt.plot(x, y1, x, y2, x, y3, x, y4)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/aebc7443-2c94-4ded-b3e9-de07df07e129/image.png)
-------------------------------------
-----------------------------------------------------------------
#### 예제 tips data
- 예제, tips = sns.load_dataset(&quot;tips&quot;)
![](https://velog.velcdn.com/images/jj_study/post/69ef82ce-a05a-46f0-84c6-36f236541c18/image.png)

------------------------------------------------------------------</code></pre><h1 id="total_bill-tip---float-데이터">total_bill, tip - float 데이터</h1>
<p>sex, smoker, day, time - category 데이터
tips.info()</p>
<blockquote>
<blockquote>
</blockquote>
<p>&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;
RangeIndex: 244 entries, 0 to 243
Data columns (total 7 columns):</p>
</blockquote>
<h1 id="column------non-null-count--dtype">Column      Non-Null Count  Dtype</h1>
<hr>
<p> 0   total_bill  244 non-null    float64 
 1   tip         244 non-null    float64 
 2   sex         244 non-null    category
 3   smoker      244 non-null    category
 4   day         244 non-null    category
 5   time        244 non-null    category
 6   size        244 non-null    int64<br>dtypes: category(4), float64(2), int64(1)
memory usage: 7.4 KB</p>
<pre><code>---------------------------------------------------------------------
- boxplot( ) 그래프</code></pre><h1 id="tips-데이터-total_bill-컬럼">tips 데이터, total_bill 컬럼</h1>
<p>plt.figure(figsize=(8,6))
sns.boxplot(x=tips[&quot;total_bill&quot;]) # 방법 1</p>
<h1 id="snsboxplotxtotal_bill-datatips--방법-2">sns.boxplot(x=&quot;total_bill&quot;, data=tips) # 방법 2</h1>
<h1 id="snsboxplot-datatips-xtotal_bill--방법-3">sns.boxplot( data=tips, x=&quot;total_bill&quot;) # 방법 3</h1>
<p>plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/1999a268-7a2c-4d7c-96ee-44eae2fb2dc0/image.png)
---------------------------------------</code></pre><h1 id="x축-y축-지정">x축, y축 지정</h1>
<h1 id="요일에-따른-total-bill-boxplot">요일에 따른 total bill boxplot</h1>
<p>plt.figure(figsize=(8,6))
sns.boxplot(x=tips[&quot;day&quot;], y = tips[&quot;total_bill&quot;]) # 방법 1</p>
<h1 id="snsboxplotxday-y-total_bill-datatips--방법-2">sns.boxplot(x=&quot;day&quot;, y =&quot;total_bill&quot;, data=tips) # 방법 2</h1>
<h1 id="snsboxplotdatatips-y-total_bill-xday--방법-3">sns.boxplot(data=tips, y =&quot;total_bill&quot;, x=&quot;day&quot;) # 방법 3</h1>
<p>plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/faa91d2f-9c07-4167-9b38-37c78c79ab0a/image.png)

- hue, palette 옵션
    - hue (카테고리 데이터 표현 옵션)
    - palette (색깔 옵션 (Set 1~3))</code></pre><h1 id="hue-옵션--카테고리-데이터-표현-옵션">hue 옵션 : 카테고리 데이터 표현 옵션</h1>
<h1 id="palette-옵션--색깔-옵션-set-1--3">palette 옵션 : 색깔 옵션 (Set 1 ~ 3)</h1>
<p>plt.figure(figsize=(8,6))
sns.boxplot(x=&quot;day&quot;, y = &quot;total_bill&quot;, data=tips, hue=&quot;smoker&quot;, palette=&quot;Set2&quot;)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/3d7e1903-cbe0-41f9-a383-5c2a2ebab869/image.png)
----------------------------------------
- swarmplot 옵션</code></pre><p>plt.figure(figsize=(8,6))
sns.swarmplot(x=&quot;day&quot;, y = &quot;total_bill&quot;, data=tips)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/432697b3-1e39-4c6c-a7ad-09597bc1013d/image.png)

- color 옵션 (0 -1 사이 검은색부터 흰색 사이 값 조절(0: 검정, 1: 흰색)</code></pre><p>plt.figure(figsize=(8,6))
sns.swarmplot(x=&quot;day&quot;, y = &quot;total_bill&quot;, data=tips, color=&quot;0.5&quot;)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/5fe5dc59-d32f-4dc9-ac0a-2cdfc0014b3f/image.png)
----------------------------------------
- boxplot + swarmplot 옵션</code></pre><p>plt.figure(figsize=(8,6))
sns.boxplot(x=&quot;day&quot;, y = &quot;total_bill&quot;, data=tips)
sns.swarmplot(x=&quot;day&quot;, y = &quot;total_bill&quot;, data=tips, color=&quot;0.25&quot;)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/48998336-4300-4b1d-b2c8-1526cd2221db/image.png)

-----------------------------------------------------------------
-lmplot 옵션
    - height 옵션 (그래프 크기-figsize)</code></pre><h1 id="lmplot--total_bill과-tip-사이-관계-파악">lmplot : total_bill과 tip 사이 관계 파악</h1>
<h1 id="height-옵션--그래프-크기figsize-와-같다">height 옵션 : 그래프 크기(figsize 와 같다)</h1>
<p>sns.set_style(&quot;darkgrid&quot;)
sns.lmplot(x=&quot;total_bill&quot;, y = &quot;tip&quot;, data=tips, height=7)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/f8ee705d-bbaf-4d27-8301-fc00137c8fa7/image.png)
</code></pre><p>sns.lmplot(x=&quot;total_bill&quot;, y = &quot;tip&quot;, hue=&quot;smoker&quot;, data=tips, height=7)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/1946315d-73a2-4821-9dac-a4da743cbaf1/image.png)

------------------------------------------------------------------
-------------------------------------------------------------------
#### 예제 flights data</code></pre><p>flights = sns.load_dataset(&quot;flights&quot;)
flights.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/4575a833-a288-434d-83ce-da30923d004e/image.png)
</code></pre><p>flights.info()</p>
<blockquote>
<blockquote>
</blockquote>
<p>&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;
RangeIndex: 144 entries, 0 to 143
Data columns (total 3 columns):</p>
</blockquote>
<h1 id="column------non-null-count--dtype-1">Column      Non-Null Count  Dtype</h1>
<hr>
<p> 0   year        144 non-null    int64<br> 1   month       144 non-null    category
 2   passengers  144 non-null    int64<br>dtypes: category(1), int64(2)
memory usage: 2.9 KB</p>
<pre><code>
(1) pivot 옵션
- pivot(index=&#39;month&#39;, columns=&#39;year&#39;, values=&#39;passengers&#39;)</code></pre><p>flights = flights.pivot(index=&#39;month&#39;, columns=&#39;year&#39;, values=&#39;passengers&#39;)
flights.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/7996f649-941f-43f4-a06c-ad4a36bc0d8a/image.png)

----------------------------------------------------------------
(2) annot, fmt, cmap 옵션
- annot 옵션 : True(데이터값 표시), False(데이터 값 미표시)
- fmt 옵션 : d (정수형), f (실수형)
- cmap 옵션 : 색상명</code></pre><p>plt.figure(figsize=(10, 8))
sns.heatmap(data=flights, annot=True, fmt=&quot;d&quot;)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/521b0a07-c3bd-4c14-ba33-6d2701118df5/image.png)
---------------------------------------</code></pre><p>plt.figure(figsize=(10, 8))
sns.heatmap(data=flights, annot=True, fmt=&quot;d&quot;, cmap=&quot;YlGnBu&quot;)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/7fb6cc99-6d5b-4da0-beee-8811a5b48709/image.png)
---------------------------------------
#### 예제 iris data</code></pre><p>sns.set(style=&quot;ticks&quot;)
iris = sns.load_dataset(&quot;iris&quot;)
iris.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/dc770551-10dd-4a93-b691-11ed897250f3/image.png)</code></pre><p>iris.info()</p>
<blockquote>
<blockquote>
</blockquote>
<p>&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):</p>
</blockquote>
<h1 id="column--------non-null-count--dtype">Column        Non-Null Count  Dtype</h1>
<hr>
<p> 0   sepal_length  150 non-null    float64
 1   sepal_width   150 non-null    float64
 2   petal_length  150 non-null    float64
 3   petal_width   150 non-null    float64
 4   species       150 non-null    object 
dtypes: float64(4), object(1)
memory usage: 6.0+ KB</p>
<pre><code>----------------------------------------------------------------------
(1) pairplot 
- 값 전체 데이터에 대해 모든 경우의 수를 그래프로 나타내 줌.  다수의 컬럼 비교</code></pre><p>sns.pairplot(iris)
plt.show()</p>
<pre><code>- ticks 옵션
    - ticks : x축 y축 모양 변경</code></pre><p>sns.set_style(&quot;ticks&quot;)
sns.pairplot(iris)
plt.show()</p>
<pre><code>--------------------------------------------------------------------
- hue 옵션 (with pairplot)
    - 원하는 데이터만 pairplot으로 나타내기
    - hue option으로 다양한 색상으로 표현</code></pre><h1 id="iris의-species는-3가지-종류의-데이터가-있음을-알-수-있다">iris의 species는 3가지 종류의 데이터가 있음을 알 수 있다.</h1>
<p>iris[&quot;species&quot;].unique()</p>
<blockquote>
<blockquote>
<p>array([&#39;setosa&#39;, &#39;versicolor&#39;, &#39;virginica&#39;], dtype=object)
sns.pairplot(iris, hue=&quot;species&quot;)
plt.show()</p>
</blockquote>
</blockquote>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/dfe09853-bd62-4684-b570-dcb0e7bb1db1/image.png)
---------------------------------------
- 원하는 컬럼만 pairplot</code></pre><p>sns.pairplot(iris, 
             x_vars=[&quot;sepal_width&quot;, &quot;sepal_length&quot;], 
             y_vars=[&quot;petal_width&quot;, &quot;petal_length&quot;])
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/2c151e39-6646-483a-8c92-ef4ce0f48f10/image.png)
----------------------------------------</code></pre><p>sns.pairplot(iris, 
             x_vars=[&quot;sepal_width&quot;, &quot;sepal_length&quot;], 
             y_vars=[&quot;petal_width&quot;, &quot;petal_length&quot;],
             hue=&quot;species&quot;)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/b737f3d1-b366-4fa1-a4ad-b1cbd02ba8f1/image.png)
----------------------------------------
#### 예제 anscombe data</code></pre><p>anscombe = sns.load_dataset(&quot;anscombe&quot;)
anscombe.head()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/f84860ac-77bb-4299-898c-5ba9e9da1a2e/image.png)</code></pre><p>anscombe[&#39;dataset&#39;].unique()</p>
<h1 id="실행결과">실행결과</h1>
<blockquote>
<blockquote>
</blockquote>
<p>array([&#39;I&#39;, &#39;II&#39;, &#39;III&#39;, &#39;IV&#39;], dtype=object)</p>
</blockquote>
<pre><code>(1) ci 옵션
- ci 옵션 : 신뢰구간 선택
</code></pre><p>sns.set_style(&quot;darkgrid&quot;)
sns.lmplot(x=&quot;x&quot;, y=&quot;y&quot;, data=anscombe.query(&quot;dataset == &#39;I&#39;&quot;), ci=None, height=7)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/4dfd28df-84c3-4d32-b4b7-42f8147a9be3/image.png)

-------------------------------------------------------------------------
(2) scatter_kws 옵션
- scatter_kws 옵션 : 원크기</code></pre><p>sns.set_style(&quot;darkgrid&quot;)
sns.lmplot(x=&quot;x&quot;,
           y=&quot;y&quot;,
           data=anscombe.query(&quot;dataset == &#39;I&#39;&quot;),
           ci=None,
           scatter_kws={&quot;s&quot;:200},
           height=7)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/05101362-8407-469e-bbdc-b518ff0d5afe/image.png)

------------------------------------------------------------------------
(3) order 옵션
- order 옵션 :curve</code></pre><p>sns.set_style(&quot;darkgrid&quot;)
sns.lmplot(x=&quot;x&quot;,
           y=&quot;y&quot;,
           data=anscombe.query(&quot;dataset == &#39;II&#39;&quot;),
           order = 1,
           ci=None,
           scatter_kws={&quot;s&quot;:10},
           height=7)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/a74dbd08-9415-46ba-8a41-f0eddd2cb068/image.png)
----------------------------------------</code></pre><p>sns.set_style(&quot;darkgrid&quot;)
sns.lmplot(x=&quot;x&quot;,
           y=&quot;y&quot;,
           data=anscombe.query(&quot;dataset == &#39;II&#39;&quot;),
           order = 2,
           ci=None,
           scatter_kws={&quot;s&quot;:200},
           height=7)
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/9966a447-7e13-4024-9e6a-f07d52287bad/image.png)

------------------------------------------------------------------------
(4) robust 옵션
- order 옵션 : outlier (이상치, 특이치) 혼자 떨어져있는 데이터
- robust True : outlier 고려 안함
- robust False : outliser 고려 함</code></pre><h1 id="outlier">outlier</h1>
<p>sns.set_style(&quot;darkgrid&quot;)
sns.lmplot(
    x=&quot;x&quot;, 
    y=&quot;y&quot;, 
    data=anscombe.query(&quot;dataset == &#39;III&#39;&quot;), 
    ci=None, 
    height=7, 
    scatter_kws={&quot;s&quot;: 80}) #ci: 신뢰구간 선택
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/e5691cec-6c10-446f-964c-edc8d1955e07/image.png)

----------------------------------------------------------------------------</code></pre><h1 id="outlier이상치-특이치-옵션--혼자-동떨어져있는-데이터-다루는-방법">outlier(이상치, 특이치) 옵션 : 혼자 동떨어져있는 데이터 다루는 방법</h1>
<h1 id="robust-true--outlier-고려-안함">robust True : outlier 고려 안함</h1>
<h1 id="robust-false--outlier-고려함">robust False : outlier 고려함</h1>
<p>sns.set_style(&quot;darkgrid&quot;)
sns.lmplot(
    x=&quot;x&quot;, 
    y=&quot;y&quot;, 
    data=anscombe.query(&quot;dataset == &#39;III&#39;&quot;), 
    robust=True,
    ci=None, 
    height=7, 
    scatter_kws={&quot;s&quot;: 80}) #ci: 신뢰구간 선택
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/5e474ee6-1893-449d-8f08-bb212c940007/image.png)

--------------------------------------------------------------------
### Folium
- 지리적 데이터 시각화를 위한 라이브러리로 지도를 만들고 다양한 형태의 데이터를 지도 위에 시각적으로 나타냄
- [Folium 설명](https://python-visualization.github.io/folium/latest/)
- [Folium 예제](https://nbviewer.org/github/python-visualization/folium/tree/main/examples/)
------------------------------------------------------------
#### 설치</code></pre><p>Windows, mac(intel, m1)
!pip install folium</p>
<p>Windows
!pip install charset
!pip install charset-normalizer</p>
<pre><code>### import
import folium
import pandas as pd
import json

### Map( )
- location: tuple or list, default None Latitude and Longitude of Map (Northing, Easting).
(튜플 또는 리스트 형태)
- location = [위도, 경도]

#### zoom_start
- zoom_start : zoom 크기, 0 ~ 18</code></pre><h1 id="location--위도-경도">location = [위도, 경도]</h1>
<h1 id="zoom_start--줌-크기-0--18">zoom_start : 줌 크기, 0 ~ 18</h1>
<p>m = folium.Map(location=[37.544564958079896, 127.05582307754338], zoom_start=15)
m</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/96df95ac-069e-4811-9736-f4bdf5b4366d/image.png)

#### save(&quot;path&quot;)
- web page로 저장</code></pre><p>m.save(&quot;./folium.html_test&quot;)</p>
<pre><code>
#### tiles 옵션
- 지도 스타일 옵션
- &quot;OpenStreetMap&quot;
  &quot;Mapbox Bright&quot; (Limited levels of zoom for free   tiles)
  &quot;Mapbox Control Room&quot; (Limited levels of zoom for free tiles)
  &quot;Stamen&quot; (Terrain, Toner, and Watercolor)
  &quot;Cloudmade&quot; (Must pass API key)
  &quot;Mapbox&quot; (Must pass API key)
  &quot;CartoDB&quot; (positron and dark_matter)

---------------------------------------------------------</code></pre><p>m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], 
    zoom_start=14,
    tiles=&quot;OpenStreetMap&quot;
) # 0 ~ 18 
m</p>
<pre><code>
![](https://velog.velcdn.com/images/jj_study/post/c9867896-b522-45b2-8e2f-995f92cfbf9f/image.png)


- Folium을 사용하여 지도를 생성, Marker, CircleMarker, PolyLine, GeoJSON과 같은 다양한 기호를 사용하여 데이터를 지도에 표시
- 지도의 확대/축소, 스크롤, 팬 등과 같은 상호작용도 지원

--------------------------------------------------------------------
#### folium.Marker( ) 
- 지도에 마커 생성
- tooltip - 마우스 대면 표시
- popup - 마우스 클릭 시 표시 (None이면 위도, 경도 표시)
- target 새 창으로 열기
</code></pre><p>m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], # 성수역 
    zoom_start=14, # 0 ~ 18 
    tiles=&quot;OpenStreetMap&quot;
) </p>
<h1 id="뚝섬역">뚝섬역</h1>
<p>folium.Marker((37.54712311308356, 127.04721916917774)).add_to(m)</p>
<h1 id="성수역">성수역</h1>
<h1 id="popup--마우스로-클릭하면-표시됨-none-넣으면-위도-경도가-표시됨">popup : 마우스로 클릭하면 표시됨, None 넣으면 위도, 경도가 표시됨</h1>
<p>folium.Marker(
    location=[37.544564958079896, 127.05582307754338],
    popup=&quot;<b>Subway</b>&quot; # html 문법 적용가능
).add_to(m)</p>
<h1 id="성수역-1">성수역</h1>
<h1 id="tooltip--마우스-대면-표시됨">tooltip : 마우스 대면 표시됨</h1>
<p>folium.Marker(
    location=[37.544564958079896, 127.05582307754338],
    popup=&quot;<b>Subway</b>&quot;,
    tooltip=&quot;<i>성수역</i>&quot;
).add_to(m)</p>
<h1 id="html">html</h1>
<h1 id="target-새-창으로-열기">target= 새 창으로 열기</h1>
<p>folium.Marker(
    location=[37.54558642069953, 127.05729705810472],
    popup=&quot;&lt;a href=&#39;<a href="https://zero-base.co.kr/&#39;">https://zero-base.co.kr/&#39;</a> target=_&#39;blink&#39;&gt;제로베이스</a>&quot;,
    tooltip=&quot;<i>Zerobase</i>&quot;
).add_to(m)</p>
<p>m</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/047f596d-d5fc-4cca-b744-dde53c02d680/image.png)
![](https://velog.velcdn.com/images/jj_study/post/7897618d-bfd7-4f15-a71c-ccfb55e0f19f/image.png)
![](https://velog.velcdn.com/images/jj_study/post/7a6a3c5a-f125-4d2f-b246-7c25ee9b5a84/image.png)

#### folium.Icon( )
https://fontawesome.com/v5.15/icons?d=gallery&amp;p=2&amp;m=free
https://getbootstrap.com/docs/3.3/components/</code></pre><p>m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], # 성수역 
    zoom_start=14,
    tiles=&quot;OpenStreetMap&quot;
) # 0 ~ 18 </p>
<h1 id="icon-basic">icon basic</h1>
<p>folium.Marker(
    (37.54712311308356, 127.04721916917774), 
    icon=folium.Icon(color=&quot;black&quot;, icon=&#39;info-sign&#39;)
).add_to(m)</p>
<h1 id="icon-icon_color">icon icon_color</h1>
<p>folium.Marker(
    location=[37.544564958079896, 127.05582307754338],
    popup=&quot;<b>Subway</b>&quot;,
    tooltip=&quot;icon color&quot;,
    icon=folium.Icon(
        color=&quot;red&quot;,
        icon_color=&quot;blue&quot;,
        icon=&quot;cloud&quot;)
).add_to(m)</p>
<h1 id="icon-custom">Icon custom</h1>
<p>folium.Marker(
    location=[37.54035903907497, 127.06913328776446], # 건대입구역
    popup=&quot;건대입구역&quot;,
    tooltip=&quot;Icon custom&quot;,
    icon=folium.Icon(
        color=&quot;purple&quot;,
        icon_color=&quot;white&quot;,
        icon=&quot;glyphicon glyphicon-cloud&quot;,
        angle=50,
        prefix=&quot;glyphicon&quot;) #  glyphicon, fa 구글에 사이트 검색
).add_to(m)</p>
<p>m</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/a7158966-ed8f-44b2-9e50-6d3e24d610fb/image.png)
----------------------------------------
#### folium.ClickForMarker( )
- 지도에 마우스 클릭 시 마커 생성</code></pre><p>m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], # 성수역 
    zoom_start=14,
    tiles=&quot;OpenStreetMap&quot;
) # 0 ~ 18 </p>
<p>m.add_child(folium.ClickForMarker(popup=&quot;ClickForMarker&quot;))</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/064ea1fc-d9b2-4c18-91e5-5a251a86daa8/image.png)

---------------------------------------------------------------------
#### folium.LatLngPopup( )
- 지도를 마우스로 클릭했을 때 위도 경도 정보를 반환</code></pre><p>m = folium.Map(
    location=[37.544564958079896, 127.05582307754338], # 성수역 
    zoom_start=14,
    tiles=&quot;OpenStreetMap&quot;
) # 0 ~ 18 </p>
<p>m.add_child(folium.LatLngPopup())</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/d42da54e-8e0b-4f2e-8a20-2a7690236ea3/image.png)
----------------------------------------
#### folium.Circle( )
#### folium.CircleMarker( )
- 지도에서 둘다 원 표시</code></pre><p>m = folium.Map(
    location=[37.55068861733562, 127.04420997492151], 
    zoom_start=14,
    tiles=&quot;OpenStreetMap&quot;
) # 0 ~ 18 </p>
<h1 id="circle">Circle</h1>
<p>folium.Circle(
    location=[37.555243442409406, 127.04370422643919], # 한양대학교
    radius=100, # 반지름
    fill=True, # True : 원 안을 채움, False : 원 안을 비움
    color=&quot;#eb9e34&quot;,
    fill_color=&quot;red&quot;, 
    popup=&quot;Circle Popup&quot;,
    tooltip=&quot;Circle Tooltip&quot;
).add_to(m)</p>
<h1 id="circlemarker">CircleMarker</h1>
<p>folium.CircleMarker(
    location=[37.54347089498245, 127.04439204503049], # 한양대학교
    radius=100, 
    fill=True,
    color=&quot;#34ebc6&quot;,
    fill_color=&quot;#c634eb&quot;,
    popup=&quot;CircleMarker Popup&quot;,
    tooltip=&quot;CircleMarker Tooltip&quot;
).add_to(m)</p>
<p>m</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/6abe3481-0c1c-45f2-b1c1-da33e799df26/image.png)
----------------------------------------</code></pre><p>m = folium.Map(
    location=[37.55068861733562, 127.04420997492151], 
    zoom_start=14,
    tiles=&quot;OpenStreetMap&quot;
) # 0 ~ 18 </p>
<h1 id="원을-채우지-않으면-원-테두리에-마우스를-대거나-클릭해야-표시됨">원을 채우지 않으면 원 테두리에 마우스를 대거나, 클릭해야 표시됨</h1>
<h1 id="circle-1">Circle</h1>
<p>folium.Circle(
    location=[37.555243442409406, 127.04370422643919], # 한양대학교
    radius=100,  # 반지름
    fill= False, # True : 원 안을 채움, False : 원 안을 비움
    color=&quot;#eb9e34&quot;,
    # fill_color=&quot;red&quot;, # 이게 들어가 있으면 fill= False 이라도 원 안이 채워짐
    popup=&quot;Circle Popup&quot;,
    tooltip=&quot;Circle Tooltip&quot;
).add_to(m)</p>
<p>m</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/619312e7-7585-4cff-a8d8-1690cf5d3003/image.png)
---------------------------------------
#### folium.Choropleth - 단계구분도
</code></pre><p>import json </p>
<p>state_data = pd.read_csv(&quot;../data/02. US_Unemployment_Oct2012.csv&quot;)
state_data.tail(2)</p>
<pre><code>![](https://velog.velcdn.com/images/jj_study/post/dc563227-cb3e-49a8-9bd5-1b7ea2b4c1ea/image.png)
-------------------------------------
m = folium.Map([43, -102], zoom_start=3)

folium.Choropleth(
    geo_data=&quot;../data/02. us-states.json&quot;, # 경계선 좌표값이 담긴 데이터
    data=state_data, # Series or DataFrame 
    columns=[&quot;State&quot;, &quot;Unemployment&quot;], # DataFrame columns 
    key_on=&quot;feature.id&quot;,
    fill_color=&quot;BuPu&quot;,
    fill_opacity=0.5, # 투명도 0~1 
    line_opacity=0.2, # 투명도 0~1
    legend_name=&quot;Unemployment rate (%)&quot;    
).add_to(m)

m
![](https://velog.velcdn.com/images/jj_study/post/5007ce67-bd5e-49a6-b6d3-f9847e26e7f4/image.png)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 - 서울시CCTV현황]]></title>
            <link>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%84%9C%EC%9A%B8%EC%8B%9CCCTV%ED%98%84%ED%99%A9</link>
            <guid>https://velog.io/@jj_study/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%84%9C%EC%9A%B8%EC%8B%9CCCTV%ED%98%84%ED%99%A9</guid>
            <pubDate>Thu, 22 Feb 2024 09:30:15 GMT</pubDate>
            <description><![CDATA[<h4 id="1-분석-데이터-불러오기">1. 분석 데이터 불러오기</h4>
<ul>
<li>서울시 구별 CCTV현황 데이터 (.csv)</li>
</ul>
<pre><code>import pandas as pd
CCTV_Seoul = pd.read_csv(&quot;../data/01. Seoul_CCTV.csv&quot;)
# 한글이 깨질 경우 : encoding=&#39;utf-8&#39; </code></pre><ul>
<li>컬럼명 변경<pre><code>CCTV_Seoul.rename(columns={&quot;기관명&quot;:&quot;구별&quot;}, inplace=True)</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/ed3fd412-5dab-49d1-9b92-cb80686a190f/image.png" alt=""></li>
</ul>
<h4 id="서울시-구별-인구-현황-데이터-xls">서울시 구별 인구 현황 데이터 (.xls)</h4>
<pre><code>popul_seoul = pd.read_excel(
        &quot;../data/01. Seoul_Population.xls&quot;, header=2, usecols=&quot;B, D, G, J, N&quot; # header는 자료 읽기 시작할 행  컬럼의 &#39;합계&#39;만 가져오기
    )</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/7ed6aef9-e708-4f36-8ed4-026507098084/image.png" alt=""></p>
<ul>
<li>컬럼명 변경<pre><code>popul_seoul.rename(
      columns={
          popul_seoul.columns[0]: &quot;구별&quot;,
          popul_seoul.columns[1]: &quot;인구수&quot;,
          popul_seoul.columns[2]: &quot;한국인&quot;,
          popul_seoul.columns[3]: &quot;외국인&quot;,
          popul_seoul.columns[4]: &quot;고령자&quot;
      },
      inplace=True
  )</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/a96ca5cf-297c-4728-ad55-c6e9b31a462d/image.png" alt=""></li>
</ul>
<h4 id="2-분석-데이터-흝어보기">2. 분석 데이터 흝어보기</h4>
<h4 id="cctv-데이터">CCTV 데이터</h4>
<ul>
<li><p>가장 많은 CCTV를 보유한 구</p>
<pre><code>CCTV_Seoul.sort_values(by=&#39;소계&#39;, ascending=False).head()</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/e309cec4-f49b-4f03-96c1-d405c9e01076/image.png" alt=""></p>
</li>
<li><p>&#39;최근증가율&#39; 컬럼 추가 </p>
</li>
<li><p>이전에 보유한 CCTV 개수 대비 최근 3년(2014~2016)간 CCTV를 가장 많이 설치한 구는?</p>
</li>
</ul>
<pre><code>CCTV_Seoul[&quot;최근증가율&quot;] = (
    (CCTV_Seoul[&quot;2014년&quot;] + CCTV_Seoul[&quot;2015년&quot;] + CCTV_Seoul[&quot;2016년&quot;]) / CCTV_Seoul[&quot;2013년도 이전&quot;] * 100
)

CCTV_Seoul.sort_values(by=&#39;최근증가율&#39;, ascending=False).head()</code></pre><h4 id="인구-데이터">인구 데이터</h4>
<ul>
<li>첫 행(row[0]의 &#39;합계&#39; 데이터 삭제</li>
<li>drop 메서드로 필요없는 행 삭제<pre><code>popul_seoul.drop([0], inplace=True) popul_seoul.head()</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/af958320-245f-436d-ab36-a26ee645f6b3/image.png" alt=""></li>
</ul>
<p>외국인과 고령자 비율 컬럼 추가</p>
<ul>
<li>데이터 행 25개를 컬럼 연산으로 한번에 연산 가능<pre><code>popul_seoul[&quot;외국인비율&quot;] = popul_seoul[&quot;외국인&quot;] / popul_seoul[&quot;인구수&quot;] * 100
  popul_seoul[&quot;고령자비율&quot;] = popul_seoul[&quot;고령자&quot;] / popul_seoul[&quot;인구수&quot;] * 100
  popul_seoul.head()</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/2e84c30d-894d-4b7d-9660-425d041720d1/image.png" alt=""></li>
</ul>
<h4 id="3-분석-데이터-병합">3. 분석 데이터 병합</h4>
<p>&quot;구별&quot;로 CCTV 와 인구데이터 병합</p>
<pre><code>merge_data = pd.merge(CCTV_Seoul, popul_seoul, on=&quot;구별&quot;)</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/1122a0b4-4a25-4c87-acc4-86fdbc99658b/image.png" alt=""></p>
<p>필요없는 연도별 데이터 컬럼 삭제</p>
<pre><code>del merge_data[&quot;2013년도 이전&quot;]
    del merge_data[&quot;2014년&quot;]
    merge_data.drop([&quot;2015년&quot;, &quot;2016년&quot;], axis=1, inplace=True)</code></pre><p>Index 지정</p>
<ul>
<li>시각화 작업을 위해 인덱스를 변경</li>
<li>인덱스로 지정하려면 중복되는 값이 없어야 함</li>
<li>set_index() - 인덱스 재정의<pre><code>merge_data.set_index(&quot;구별&quot;, inplace=True)
merge_data.head()</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/7294f497-29e0-42ca-81af-66b5821f2b05/image.png" alt="">
상관관계(correlation) 파악</li>
<li>두 변량 사이에 한쪽이 증가하면 다른 쪽도 증가 또는 감소하는 경향이 있을 때, 이 두 변량 사이에는 상관관계가 있다고 함</li>
<li>단, 상관관계가 있다하여 두 변량이 인과관계인 것은 아님</li>
<li>데이터의 관계를 찾을 때, 최소한의 근거가 있어야 해당 데이터를 비교하는 의미가 있음</li>
<li>상관계수가 0.2 이상인 데이터를 비교하는 것은 의미가 있음</li>
<li>상관계수 연상을 위해서는 int나 float 자료형이어야 함<pre><code>merge_data.corr()</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/99a92eb4-201d-4732-925b-c82f2a81755f/image.png" alt=""></li>
<li>CCTV 전체 수(소계)와 가장 상관관계가 있는 데이터는 &quot;인구수&quot;(0.232555)</li>
<li>인구대비 CCTV 비율을 새로운 컬럼으로 만듬<pre><code>merge_data[&quot;CCTV비율&quot;] = merge_data[&quot;소계&quot;] / merge_data[&quot;인구수&quot;] * 100</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/acb091d6-20dd-43de-84bb-c47da4d3ba35/image.png" alt=""></li>
</ul>
<h4 id="4-분석데이터-시각화">4. 분석데이터 시각화</h4>
<p>pandas에서 plot그리기</p>
<ul>
<li>pandas DataFrame은 데이터 변수에서 바로 plot() 함수를 사용할 수 있음</li>
<li>데이터가 많을 경우 정렬한 후 그리는 것이 효과적일 때가 많음<pre><code>merge_data[&quot;인구수&quot;].plot(kind=&quot;bar&quot;, figsize=(10, 6))
  merge_data[&quot;인구수&quot;].plot(kind=&quot;barh&quot;, figsize=(10, 9))</code></pre><img src="https://velog.velcdn.com/images/jj_study/post/9395a2b7-b9ad-48ce-85f8-6ef66541a5fe/image.png" alt=""></li>
</ul>
<p>&#39;소계&#39; 및 &#39;CCTV비율&#39; 컬럼 시각화</p>
<pre><code>def drawGraph():
        merge_data[&quot;소계&quot;].sort_values().plot(
            kind=&quot;barh&quot;, grid=True, title=&quot;가장 CCTV가 많은 구&quot;, figsize=(10, 9)
        )
    drawGraph()
    def drawGraph():
        merge_data[&quot;CCTV비율&quot;].sort_values().plot(
            kind=&quot;barh&quot;, grid=True, title=&quot;인구대비 CCTV비율이 가장 높은 구&quot;, figsize=(10, 9)
        )
    drawGraph()</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/d024fbf7-af25-4589-8b28-af178821fc84/image.png" alt=""></p>
<p>데이터의 경향 시각화</p>
<ul>
<li><p>인구수와 소계 컬럼으로 산점도(scatter plot) 그리기</p>
<pre><code>def drawGraph():
      plt.figure(figsize=(14, 10))
      plt.scatter(merge_data[&quot;인구수&quot;], merge_data[&quot;소계&quot;], s=50)
      plt.xlabel(&quot;인구수&quot;)
      plt.ylabel(&quot;CCTV&quot;)
      plt.grid(True)
      plt.show()

  drawGraph()</code></pre><p><img src="https://velog.velcdn.com/images/jj_study/post/2273335d-1d3f-4d47-90d1-4e038501b9dc/image.png" alt=""></p>
</li>
<li><p>numpy 이용해 1차 직선 만들기</p>
<ul>
<li><p>numpy가 제공하는 함수를 이용해 1차 직선(y=ax+b)을       만들어 그래프로 비교</p>
</li>
<li><p>np.polyfit() : 직선을 구성하기 위한 계수
(기울기와  y절편)를 계산</p>
</li>
<li><p>np.poly1d(): polyfit으로 찾은 계수로 파이썬에서 사
용할 수 있는 함수로 만들어주는 역할</p>
<pre><code>import numpy as np

pf1 = np.polyfit(merge_data[&quot;인구수&quot;], merge_data[&quot;소계&quot;], 1)
// array([1.11155868e-03, 1.06515745e+03])

f1 = np.poly1d(pf1)
// poly1d([1.11155868e-03, 1.06515745e+03])</code></pre></li>
</ul>
</li>
<li><p>인구가 40만인 구에서 서울시의 전체 경향에 맞는 적당한 CCTV 수?</p>
<ul>
<li><p>경향선을 그리기 위한 X 데이터 생성</p>
</li>
<li><p>np.linspace(a, b, n): a부터 b까지 n개의 등간격 데이터 생성</p>
<pre><code>fx = np.linspace(100000, 700000, 100) // 100,000과 700,000 사이에 100개의 수 생성

def drawGraph():
  plt.figure(figsize=(14, 10))
  plt.scatter(merge_data[&quot;인구수&quot;], merge_data[&quot;소계&quot;], s=50)
  plt.plot(
      fx, f1(fx), ls=&quot;dashed&quot;, lw=3, color=&quot;g&quot;
  )
  plt.xlabel(&quot;인구수&quot;)
  plt.ylabel(&quot;CCTV&quot;)
  plt.grid()
  plt.show()

drawGraph()</code></pre><pre><code>![](https://velog.velcdn.com/images/jj_study/post/11127831-d91d-4d91-ac04-ac2f2a98e43f/image.png)
</code></pre></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[EDA 환경설정]]></title>
            <link>https://velog.io/@jj_study/EDA-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@jj_study/EDA-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95</guid>
            <pubDate>Thu, 22 Feb 2024 07:47:59 GMT</pubDate>
            <description><![CDATA[<h3 id="eda-exploratory-data-analysis">EDA (Exploratory Data Analysis)</h3>
<p>데이터 분석을 위해 데이터를 다양한 각도로 관찰하고 이해하는 과정</p>
<ul>
<li>데이터의 특징과 내재하는 구조적인 관계를 알아내기 위한 분석기법</li>
<li>이론적 모형을 적용하기보다 데이터를 있는 그대로 보려는데 중점을 두고 데이터 스스로 말하도록 유도하는 분석법</li>
<li>자료의 구조 및 특징 파악을 위하여 자료의 요약과 그래프 기법의 활용</li>
</ul>
<h4 id="환경설정">환경설정</h4>
<h4 id="miniconda">MiniConda</h4>
<ul>
<li>Conda는 오픈 소스의 패키지 관리 및 환경 관리 시스템으로 패키지 설치, 업데이트, 제거, 패키지 간 종속성 관리, 가상 환경 생성 등을 처리
conda &lt; Miniconda (python.exe, base modules) &lt; Anaconda</li>
<li>Anaconda의 간소화 버전</li>
<li>필요 패키지 선택적 설치</li>
<li>가상환경 생성 관리</li>
</ul>
<hr>
<h4 id="conda-가상환경-생성">Conda 가상환경 생성</h4>
<ol>
<li><p>Miniconda 설치 후 콘다 버전 확인 및 업데이트
(base) conda env list
(base) conda --version
(base) conda update conda</p>
</li>
<li><p>가상환경 생성 및 활성화
(base) conda create -n ds_study python=3.8
(base) conda activate ds_study
(ds_study) conda deactivate</p>
</li>
</ol>
<h4 id="jupyter-notebeook">Jupyter Notebeook</h4>
<ul>
<li>코드 작성 실행 대화형 환경 제공</li>
<li>matplotlib, seabor, bokeh등 시각화 도구와 연동</li>
</ul>
<ol>
<li>설치 
(ds_study) conda install jupyter
(ds_study) 패키지 설치
(ds_study) jupyter notebook</li>
</ol>
<h4 id="packages">Packages</h4>
<ul>
<li>내 가상환경(ds_study)에 필요 패키지 설치
(ds_study) conda install -y ipython
(ds_study) conda install -y pandas
(ds_study) conda install -y matplotlib
(ds_study) conda install -y seaborn
(ds_study) conda install -y scikit-learn
(ds_study) conda install -y xlrd</li>
</ul>
<ol>
<li><p>ipython (Python 인터프리터의 강화된 버전으로, 대화형으로 Python 코드를 작성하고 실행할 수 있도록 해주는 도구)</p>
</li>
<li><p>Pandas (Python에서 데이터 조작과 분석을 위한 라이브러리로, 특히 데이터프레임(DataFrame: 2D 테이블 형태 데이터구조)이라는 자료 구조를 중심으로 설계) 시리즈(1D 데이터 구조 DataFrame의 열과 행) </p>
</li>
<li><p>Matplotlib (파이썬에서 2D 그래픽을 생성하는 데 사용되는 라이브러리로 데이터 시각화에 널리 사용)- 선그래프, 막대그래프, 산점도, 히스토그램, 원그래프</p>
<ul>
<li>matplotlib 한글 설정
```<h5 id="window-환경">window 환경</h5>
</li>
</ul>
</li>
<li><p>먼저 설정할 폰트이름 찾기
from matplotlib import font_manager
f_path = &#39;C:/Windows/Fonts/malgun.ttf&#39;
font_manager.FontProperties(fname=f_path).get_name()</p>
</li>
<li><p>matplotlib의 font family로 설정하고 실행
from matplotlib import rc
rc(&quot;font&quot;, family=&#39;Malgun Gothic&#39;)</p>
</li>
</ol>
<p>import matplotlib.pyplot as plt
%matplotlib inline
plt.title(&quot;데이터사이언스&quot;)</p>
<pre><code></code></pre><ol start="3">
<li>Seaborn (통계 데이터를 시각화하는 데 사용)</li>
</ol>
<ul>
<li>히스토그램, 커널 밀도 플롯, 박스 플롯, 회귀 선과 같은 통계적인 시각화. Seaborn은 데이터프레임과 같은 Pandas 데이터 구조와 잘 통합되어 있어 데이터프레임을 바로 시각화 함수로 전달할 수 있어 데이터를 쉽게 시각화</li>
</ul>
<ol start="4">
<li>scikit-learn</li>
</ol>
<ul>
<li>파이썬에서 사용할 수 있는 머신러닝 라이브러리로 다양한 머신러닝 작업을 수행하는 데 편리하게 사용될 수 있는 도구 (분류, 회귀, 클러스터링, 차원 축소 등 다양한 머신러닝 알고리즘을 제공) </li>
<li>누락된 값의 처리, 스케일링, 범주형 데이터 처리 등 데이터를 전처리하고 준비</li>
<li>모델의 성능을 평가하고 선택하는 데 사용되는 다양한 지표와 도구를 제공</li>
<li>다른 파이썬 라이브러리들과의 상호 운용성을 제공하여 NumPy, Matplotlib 등과 통합하여 사용</li>
</ul>
<ol start="5">
<li>Xlrd</li>
</ol>
<ul>
<li>Excel 파일(.xls)을 읽기 위한 라이브러리</li>
<li>xlsx 형식 지원하지 않음. </li>
</ul>
<ol start="6">
<li>Openpyxl</li>
</ol>
<ul>
<li>Excel 파일(.xls, .xlsx)을 읽기 위한 라이브러리</li>
</ul>
<ol start="7">
<li>Pandas</li>
</ol>
<ul>
<li>엑셀 파일을 손쉽게 읽고 데이터프레임으로 변환하는데에 사용</li>
<li>엑셀 파일 형식(.xls 또는 .xlsx)을 읽어올 때 read_excel 함수를 사용하는데 이 함수가 내부적으로 xlrd나 openpyxl과 같은 엑셀 읽기 라이브러리 사용</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>