반응형

오늘은 Manim을 활용한 시각화 애니메이션 예제를 몇 가지 알아보도록 하겠습니다.

Preview

Manim 설치는 아래의 포스팅을 확인해 주세요 :)

https://wonhwa.tistory.com/36?category=1001573

 

[python/시각화] Manim을 활용한 애니메이션 시각화(1) - 설치

안녕하세요! 오늘은 Manim을 활용하여 시각하하기 위한 설치를 진행해 보도록 하겠습니다. Preview Manim이란? Manim(mathematical animation engine)은 수학을 보다 쉽게 설명하고 학생들에게 가르치기 위해 개

wonhwa.tistory.com

 

예제1: 모양이 바뀌는 도형 만들기

첫 번째 예제는 도형을 하나 생성하여(2차원) 그 도형의 모양을 바꾸는 예제입니다.

저번 설치때 만든 manim 폴더에 start.py라는 파이썬 파일을 만들어 준 후, 아래와 같이 코드를 적어줍니다.

from manimlib import *

class SquareToCircle(Scene):
    def construct(self):
        #원 만들기
        circle = Circle()
        circle.set_fill(GREEN,opacity=1.0) #색은 바꿀 수 있음 #opacity는 투명도
        square = Square()
        self.play(ShowCreation(square))
        self.wait()
        #도형모양 변경부분(네모를 동그라미로)
        self.play(ReplacementTransform(square,circle))
        self.wait()
        # 원늘리기
        self.play(circle.animate.stretch(4, 0))
        #원 회전하기
        self.play(Rotate(circle, 90 * DEGREES))
        #도형 이동
        self.play(circle.animate.shift(2 * RIGHT).scale(0.25))
        #도형 굴곡
        circle.insert_n_curves(10)
        self.play(circle.animate.apply_complex_function(lambda z: z**2))
        #텍스트 입력하기
        text = Text("""
            Hello World! ^0^
        """)
        self.play(Write(text))
        always(circle.move_to, self.mouse_point)

        #애니메이션 종료 후 창을 닫고 싶을때
        #exit()

사각형과 네모 객체를 만든 후 네모를 원으로 바꾸고,

그 원의 모양을 또 바꾸어 마지막엔 텍스트를 추가하는 예제입니다.

이렇게 코드를 작성 후 저장해 주세요.

그 후 anaconda 프롬프트 창 또는 cmd 창을 열어 주세요.

#1. manim폴더 위치로 이동
cd manim 
#2. manim 가상환경 활성화
activate manim 
#또는 anaconda prompt 에서 동작 시
conda activate manim
#3. 함수 실행 명령어 입력
manimgl start.py SquareToCircle

#팁: 동영상으로 저장 시
manimgl start.py SquareToCircle -o

#팁2: 애니메이션 종료 시
#실행되고 있는 애니메이션 창 클릭 후
#q 키를 눌러 실행 종료

위의 명령어를 입력하면 작성한 코드가 실행이 됩니다.

실행 애니메이션을 저장할 수도 있습니다.

명령어 끝에 -o를 붙이면 videos 라는 폴더 안에 동영상이 저장됩니다.

화면 종료 시에는 실행되고 있는 애니메이션 창을 한번 클릭 후 q 키를 눌러 종료합니다.

 

예제2: 텍스트 애니메이션

다음으로 알아볼 예제는 텍스트 애니메이션입니다.

Manim에서는 텍스트로 애니메이션화할 때 특정 단어만 폰트 및 색상 변경이 가능합니다.

페이드인효과도 줄 수 있습니다.

class TextExample(Scene):
    def construct(self):
        text = Text("여기에 텍스트가 있습니다.", font="BM DoHyeon", font_size=90) #폰트 변경시 font= 에 원하는 폰트 이름 입력
        difference = Text(
            """
            Manim에서는 텍스트를 애니메이션으로 시각화가 가능합니다.\n
            지금 보고 계시는 폰트는 맑은 고딕인데요\n
            폰트 색도 단어마다 변경이 가능합니다.
            """,
            font="Malgun Gothic", font_size=24,
            # 단어마다 색 변경하기(딕셔너리)
            t2c={"텍스트": BLUE, "애니메이션": BLUE, "맑은 고딕": ORANGE}
        )
        VGroup(text, difference).arrange(DOWN, buff=1)
        self.play(Write(text))
        self.play(FadeIn(difference, UP)) #페이드인 효과
        self.wait(3)
        fonts = Text(
            "또한 폰트를 단어마다 다르게 설정할 수 있습니다.",
            font="Gulim",
            t2f={"폰트": "BM DoHyeon", "단어": "Malgun Gothic"}, #특정단어에 특정폰트 설정
            t2c={"폰트": BLUE, "단어": GREEN} #특정 단어에 색상 설정
        )
        fonts.set_width(FRAME_WIDTH - 1)
        slant = Text(
            "물론 이탤릭체와 굵기도 설정 가능합니다.",
            font="Malgun Gothic",
            t2s={"이탤릭체": ITALIC}, #텍스트 효과 주기
            t2w={"굵기": BOLD},
            t2c={"이탤릭체": ORANGE, "굵기": RED}
        )
        VGroup(fonts, slant).arrange(DOWN, buff=0.8)
        self.play(FadeOut(text), FadeOut(difference, shift=DOWN))
        self.play(Write(fonts))
        self.wait()
        self.play(Write(slant))
        self.wait()

한글을 작성할 때는 한글 폰트로 사용하여야 깨짐 현상이 일어나지 않습니다.

마찬가지로 명령창에 아래와 같은 명령어를 입력해주면 실행이 됩니다.

항상 start.py파일을 저장하고 실행해야 최신 상태로 구동이 됩니다.

# 코드실행
manimgl start.py TextExample

# 영상저장
manimgl start.py TextExample -o

#영상 종료 
q

 

 

예제3: 3차원 도형 및 이미지

마지막 예제로 3차원 도형을 시각화해보겠습니다.

지구 모양의 원을 만들고 이미지를 다운받아 표면을 표현해 줍니다.

그 후 회전을 주어 지구가 회전하는 모습을 보여줍니다.

또한 지구 낮 버전 밤 버전을 번갈아서 나타낼 수 있습니다.

아래의 코드를 입력해 주세요.

class SurfaceExample(Scene):
    CONFIG = {
        "camera_class": ThreeDCamera,
    }

    def construct(self):
        surface_text = Text(" 3차원으로 도형을 나타낼 수 있습니다.",font="BM DoHyeon")
        surface_text.fix_in_frame()
        surface_text.to_edge(UP)
        self.add(surface_text)
        self.wait(0.1)
        #원모양 도형 준비
        torus1 = Torus(r1=1, r2=1)
        torus2 = Torus(r1=3, r2=1)
        sphere = Sphere(radius=3, resolution=torus1.resolution)
        # 2가지 지구 버전 이미지 준비
        day_texture = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Whole_world_-_land_and_oceans.jpg/1280px-Whole_world_-_land_and_oceans.jpg"
        night_texture = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/The_earth_at_night.jpg/1280px-The_earth_at_night.jpg"

        surfaces = [
            TexturedSurface(surface, day_texture, night_texture)
            for surface in [sphere, torus1, torus2]
        ]
        # 그리드(격자 보여주기)
        for mob in surfaces:
            mob.shift(IN)
            mob.mesh = SurfaceMesh(mob)
            mob.mesh.set_stroke(BLUE, 1, opacity=0.5)

        # Set perspective 특징설정
        frame = self.camera.frame
        frame.set_euler_angles(
            theta=-30 * DEGREES,
            phi=70 * DEGREES,
        )

        surface = surfaces[0]
        surface.save_state()
        self.play(
            FadeIn(surface),
            ShowCreation(surface.mesh, lag_ratio=0.01, run_time=3),
        )
        
        for mob in surfaces:
            mob.add(mob.mesh)
        surface.save_state()
        self.play(Rotate(surface, PI/2), run_time=2)
        for mob in surfaces[1:]:
            mob.rotate(PI/2)

        # 회전모션 추가
        frame.add_updater(lambda m, dt: m.increment_theta(-0.1 * dt))

        #밤의 지구버전 보여주기
        light_text = Text("2가지 사진을 사용하여 번갈아 가며 나타낼 수도 있습니다.",font="BM DoHyeon")
        light_text.move_to(surface_text)
        light_text.fix_in_frame()

        self.play(FadeTransform(surface_text, light_text))
        light = self.camera.light_source
        self.add(light)
        light.save_state()
        self.play(light.animate.move_to(3 * IN), run_time=5)
        self.play(light.animate.shift(10 * OUT), run_time=5)

        drag_text = Text("d나 s를 누른 상태에서 마우스를 움직여 물체를 이동시켜 보세요.",font="BM DoHyeon")
        drag_text.move_to(light_text)
        drag_text.fix_in_frame()

        self.play(FadeTransform(light_text, drag_text))
        self.wait()

이번에는 d나 s를 눌러 상호작용이 가능합니다.

d는 도형 내에서 원하는 각도로 변경할 수 있고 s는 도형 자체를 이동시킬 수 있습니다.

# 코드실행
manimgl start.py SurfaceExample

# 영상저장
manimgl start.py SurfaceExample -o

#종료
q

 

참고자료

- Manim 문서

https://3b1b.github.io/manim/getting_started/quickstart.html

 

Quick Start - manim documentation

Previous Installation

3b1b.github.io

 

전체코드
from manimlib import *

class SquareToCircle(Scene):
    def construct(self):
        #원 만들기
        circle = Circle()
        circle.set_fill(GREEN,opacity=1.0) #색은 바꿀 수 있음 #opacity는 투명도
        square = Square()
        self.play(ShowCreation(square))
        self.wait()
        #도형모양 변경부분(네모를 동그라미로)
        self.play(ReplacementTransform(square,circle))
        self.wait()
        # 원늘리기
        self.play(circle.animate.stretch(4, 0))
        #원 회전하기
        self.play(Rotate(circle, 90 * DEGREES))
        #도형 이동
        self.play(circle.animate.shift(2 * RIGHT).scale(0.25))
        #도형 굴곡
        circle.insert_n_curves(10)
        self.play(circle.animate.apply_complex_function(lambda z: z**2))
        #텍스트 입력하기
        text = Text("""
            Hello World! ^0^
        """)
        self.play(Write(text))
        always(circle.move_to, self.mouse_point)

        #애니메이션 종료 후 창을 닫고 싶을때
        #exit()


class TextExample(Scene):
    def construct(self):
        text = Text("여기에 텍스트가 있습니다.", font="BM DoHyeon", font_size=90) #폰트 변경시 font= 에 원하는 폰트 이름 입력
        difference = Text(
            """
            Manim에서는 텍스트를 애니메이션으로 시각화가 가능합니다.\n
            지금 보고 계시는 폰트는 맑은 고딕인데요\n
            폰트 색도 단어마다 변경이 가능합니다.
            """,
            font="Malgun Gothic", font_size=24,
            # 단어마다 색 변경하기(딕셔너리)
            t2c={"텍스트": BLUE, "애니메이션": BLUE, "맑은 고딕": ORANGE}
        )
        VGroup(text, difference).arrange(DOWN, buff=1)
        self.play(Write(text))
        self.play(FadeIn(difference, UP)) #페이드인 효과
        self.wait(3)
        fonts = Text(
            "또한 폰트를 단어마다 다르게 설정할 수 있습니다.",
            font="Gulim",
            t2f={"폰트": "BM DoHyeon", "단어": "Malgun Gothic"}, #특정단어에 특정폰트 설정
            t2c={"폰트": BLUE, "단어": GREEN} #특정 단어에 색상 설정
        )
        fonts.set_width(FRAME_WIDTH - 1)
        slant = Text(
            "물론 이탤릭체와 굵기도 설정 가능합니다.",
            font="Malgun Gothic",
            t2s={"이탤릭체": ITALIC}, #텍스트 효과 주기
            t2w={"굵기": BOLD},
            t2c={"이탤릭체": ORANGE, "굵기": RED}
        )
        VGroup(fonts, slant).arrange(DOWN, buff=0.8)
        self.play(FadeOut(text), FadeOut(difference, shift=DOWN))
        self.play(Write(fonts))
        self.wait()
        self.play(Write(slant))
        self.wait()

class SurfaceExample(Scene):
    CONFIG = {
        "camera_class": ThreeDCamera,
    }

    def construct(self):
        surface_text = Text(" 3차원으로 도형을 나타낼 수 있습니다.",font="BM DoHyeon")
        surface_text.fix_in_frame()
        surface_text.to_edge(UP)
        self.add(surface_text)
        self.wait(0.1)
        #원모양 도형 준비
        torus1 = Torus(r1=1, r2=1)
        torus2 = Torus(r1=3, r2=1)
        sphere = Sphere(radius=3, resolution=torus1.resolution)
        # 2가지 지구 버전 이미지 준비
        day_texture = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Whole_world_-_land_and_oceans.jpg/1280px-Whole_world_-_land_and_oceans.jpg"
        night_texture = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/The_earth_at_night.jpg/1280px-The_earth_at_night.jpg"

        surfaces = [
            TexturedSurface(surface, day_texture, night_texture)
            for surface in [sphere, torus1, torus2]
        ]
        # 그리드(격자 보여주기)
        for mob in surfaces:
            mob.shift(IN)
            mob.mesh = SurfaceMesh(mob)
            mob.mesh.set_stroke(BLUE, 1, opacity=0.5)

        # Set perspective 특징설정
        frame = self.camera.frame
        frame.set_euler_angles(
            theta=-30 * DEGREES,
            phi=70 * DEGREES,
        )

        surface = surfaces[0]
        surface.save_state()
        self.play(
            FadeIn(surface),
            ShowCreation(surface.mesh, lag_ratio=0.01, run_time=3),
        )
        
        for mob in surfaces:
            mob.add(mob.mesh)
        surface.save_state()
        self.play(Rotate(surface, PI/2), run_time=2)
        for mob in surfaces[1:]:
            mob.rotate(PI/2)

        # 회전모션 추가
        frame.add_updater(lambda m, dt: m.increment_theta(-0.1 * dt))

        #밤의 지구버전 보여주기
        light_text = Text("2가지 사진을 사용하여 번갈아 가며 나타낼 수도 있습니다.",font="BM DoHyeon")
        light_text.move_to(surface_text)
        light_text.fix_in_frame()

        self.play(FadeTransform(surface_text, light_text))
        light = self.camera.light_source
        self.add(light)
        light.save_state()
        self.play(light.animate.move_to(3 * IN), run_time=5)
        self.play(light.animate.shift(10 * OUT), run_time=5)

        drag_text = Text("d나 s를 누른 상태에서 마우스를 움직여 물체를 이동시켜 보세요.",font="BM DoHyeon")
        drag_text.move_to(light_text)
        drag_text.fix_in_frame()

        self.play(FadeTransform(light_text, drag_text))
        self.wait()

 

터미널 명령어 모음
#1. manim폴더 위치로 이동
cd manim 
#2. manim 가상환경 활성화
activate manim 
#또는 anaconda prompt 에서 동작 시
conda activate manim
#3. 함수 실행 명령어 입력
manimgl start.py SquareToCircle

#팁: 동영상으로 저장 시
manimgl start.py SquareToCircle -o

#팁2: 애니메이션 종료 시
#실행되고 있는 애니메이션 창 클릭 후
#q 키를 눌러 실행 종료

# 예제2 코드실행
manimgl start.py TextExample

# 영상저장
manimgl start.py TextExample -o

#영상 종료 
q

# 예제3 코드실행
manimgl start.py SurfaceExample

# 영상저장
manimgl start.py SurfaceExample -o

#종료
q

 

코드 파일

start.py
0.01MB

마무리

오늘은 간단한 Manim 예제 몇가지를 알아보았습니다 ㅎㅎ

마님 문서에 가면 더 다양한 예제를 확인할 수 있습니다.

Manim을 활용하여 시각화하고 싶은 애니메이션이 있다면 댓글로 알려주세요 :)

저도 활용하기 좋은 아이디어가 있으면 포스팅으로 공유하도록 하겠습니다.ㅎㅎ

반응형
반응형

안녕하세요! 오늘은 Manim을 활용하여 시각하하기 위한 설치를 진행해 보도록 하겠습니다.

Preview

Manim이란?

Manim(mathematical animation engine)은 수학을 보다 쉽게 설명하고 학생들에게 가르치기 위해 개발이 되었습니다. 수학관련 공식 및 설명등을 애니메이션으로 시각화하여 나타내는 엔진입니다. Manim은 수학 공식뿐 아니라 다른 텍스트, 도형 등도 시각화할 수 있어 소개해 드리고자 합니다 :)

 

Manim 설치

Manim을 사용하기 위해서는 미리 설치해야 되는 프로그램들이 있습니다.

Windows기준으로 설치 방법을 안내해 드리겠습니다.

1. MikTex 설치
 

Getting MiKTeX

a. Register GPG key sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys D6BC243565B2087BC3F897C9277A7293F59E4889 b. Register installation source Ubuntu 20.04 LTS (Focal Fossa): echo "deb http://miktex.org/download/ubuntu focal universe"

miktex.org

All downloads에 들어가 본인 컴퓨터에 맞는 Net Installer를 다운받아 설치해 주세요.(관리자 권한으로 실행)

저는 windows Net Installer 64-bit를 설치하였습니다.

2. FFmpeg 설치

FFmpeg 설치는 아래의 링크를 참고하여 설치해 주세요:)

https://wonhwa.tistory.com/15?category=1001573

 

[python] bar-chart-race로 시각화하기 (feat. 축구)

안녕하세요! 오늘은 bar-chart-race(직역하면 막대그래프 경주)를 이용해서 시각화 하는 방법을 알려드리려고 합니다. 예제로 EPL 영국 프리미어 축구 리그 데이터를 활용하여 bar-chart-race 시각화를

wonhwa.tistory.com

위의 게시물에서 step2. FFmpeg 설치하기를 참고하면 됩니다 ㅎㅎ

3. Sox 설치
 

SoX - Sound eXchange

Download SoX - Sound eXchange for free. SoX is the Swiss Army Knife of sound processing utilities. It can convert audio files to other popular audio file types and also apply sound effects and filters during the conversion.

sourceforge.net

파일 다운로드 후 설치를 진행해 주세요.(관리자 권한으로 실행)

위의 3번까지의 과정은 youtube에서도 확인할 수 있습니다.

아래의 영상을 참고해 주세요.

https://www.youtube.com/watch?v=ZltiKHFWmv8

4. pip3 install virtualenv(가상환경) 설치

그 후 터미널에서 위 명령어로 가상환경설정이 가능하도록 설치해줍니다.

5. pip install pycario 설치

4번과 마찬가지로 pycario도 설치해 줍니다.

6. manim 가상환경 설정

manim을 사용할 폴더를 하나 만들어 줍니다.

저는 C:Users\users 에 manim이라는 폴더를 만들어 주었습니다.

그후 cmd창을 열고,

1. cd C:\Users\user\tmanim
2. virtualenv manim
3. .\manim\Scripts\activate
4. activate manim

위의 명령어를 차례대로 입력해주면,

(manim) 파일경로 > 

이런 형태의 명령창이 나옵니다. 그럼 가상환경 설정은 끝났습니다.

7. manim 다운받기
pip install manimgl

위 명령어로 설치 후, 아래의 명령어를 추가로 설치해 manim 예시 파일을 열어보도록 합시다.

git clone https://github.com/3b1b/manim.git
cd manim
pip install -e .
manimgl example_scenes.py OpeningManimExample

 

위의 영상처럼 example이 잘 실행되면 manim 설치가 완료되었습니다 :)

참고자료

1. manim 깃헙  https://github.com/3b1b/manim

 

GitHub - 3b1b/manim: Animation engine for explanatory math videos

Animation engine for explanatory math videos. Contribute to 3b1b/manim development by creating an account on GitHub.

github.com

2. 관련 유튜브

https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw

 

3Blue1Brown

3Blue1Brown, by Grant Sanderson, is some combination of math and entertainment, depending on your disposition. The goal is for explanations to be driven by animations and for difficult problems to be made simple with changes in perspective. For more inform

www.youtube.com

https://www.youtube.com/channel/UCxiWCEdx7aY88bSEUgLOC6A

 

Theorem of Beethoven

Welcome!!! ► About me: My name is Alexander, I'm a mechanic engineering student and I live in Mexico city. ► About the content of this channel: This channel is dedicated to the musical and scientific divulgation with explanatory animations. However, th

www.youtube.com

 

TO BE CONTINUED...

다음 시간에는 Manim으로 만들 수 있는 애니메이션 몇 가지를 소개해 보도록 하겠습니다 ㅎㅎ

반응형
반응형

1편에 이어 matplotlib으로 그래프 만들기 2편 시작해 보도록 하겠습니다!

1편은 아래의 링크를 참고해주세요:)

https://wonhwa.tistory.com/30

 

[python/시각화] matplotlib으로 그래프 만들기- 히스토그램, 산점도, 박스그래프

안녕하세요! 오늘은 파이썬 matplotlib라이브러리를 이용해 다양한 종류의 그래프를 만들어 보도록 하겠습니다. 그럼 바로 시작해 보도록 하겠습니다. 데이터 준비 오늘 시각화할 데이터는 kaggle의

wonhwa.tistory.com

 

데이터준비

1편에서 사용한 csv데이터를 준비해 주세요:)

또는 아래의 링크에서 다운받아 주세요.

https://www.kaggle.com/imakash3011/customer-personality-analysis

 

Customer Personality Analysis

Analysis of company's ideal customers

www.kaggle.com

 

다변량 그래프 그리기

다변량 그래프는 변수가 여러 개 있는 그래프입니다.

이번 포스팅에는 변수를 4개를 추가하여 그래프를 그리는 방법을 알아보도록 하겠습니다.

  • x축: MntMeatProducts(육류구매량)
  • y축: MntWines(와인구매량)
  • 색구분: Edu_level(학력)
  • 사이즈구분: NumWebPurchases(웹사이트구매횟수)

이렇게 4개의 변수를 그래프로 표현해 보겠습니다.

기존 csv를 불러온 df에서 null 값이 있으면 0으로 일괄대체를 해준 후 나머지 과정을 진행합니다.

먼저 학력별로 색 구분을 하려면 str데이터인 학력을 문자에서 숫자로 변환하는 작업이 필요합니다.

이 작업을 아래의 함수를 써서 학력을 숫자로 바꾼 후,

바꾼 숫자들을 'Edu_level'이라는 학력 컬럼을 새로 만들어 입력 하겠습니다.

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager,rc

# 한글 폰트 설정
font_location = 'C:/Windows/Fonts/MALGUNSL.TTF' #맑은고딕
font_name = font_manager.FontProperties(fname=font_location).get_name()
rc('font',family=font_name)
#데이터 셋 불러오기
df = pd.read_csv('marketing_campaign.csv',sep='\t')
# null값 0으로 대체
df = df.fillna(0)

########## 다변량 그래프 그리기 ###########
#다변량 그래프(3개 이상의 변수 사용)

# 학력부분 숫자로 바꾸기
def recode_edu(education_level):
    if education_level == 'Basic':
        return 0
    elif education_level == 'Graduation':
        return 1
    elif education_level == '2nCycle':
        return 2
    elif education_level == 'Master':
        return 3
    else:
        return 4

df['Edu_level'] = df['Education'].apply(recode_edu)
print(df.head())

출력:

맨 끝 컬럼에 Edu_level이 잘 추가되었음을 확인할 수 있습니다.

그 후 다변량 그래프를 그려주도록 합니다.

c = color(색)을, s = size(사이즈)를 의미합니다.

# x축: MntMeatProducts(육류구매량)
# y축: MntWines(와인구매량)
# c(컬러): Edu_level(학력)
# s(사이즈): NumWebPurchases(웹사이트구매횟수)

#그래프틀생성
scatter_plot = plt.figure()
axes1 = scatter_plot.add_subplot(1,1,1)
#산점도 다변량 그래프 그리기
axes1.scatter(
    x=df['MntMeatProducts'],
    y=df['MntWines'],
    c=df['Edu_level'],
    s=df['NumWebPurchases']*10,
    alpha=0.5
) #alpha는 투명도 조절
axes1.set_title('다변량 그래프(학력별 다른색상, 웹사이트구매횟수는 사이즈별')
axes1.set_xlabel('육류구매량')
axes1.set_ylabel('와인구매량')
plt.show()

이렇게 4개의 변수를 그래프로 시각화하였습니다.

 

밀집도 그래프

이번에는 'NumStorePurchases'(매장구매량)컬럼을 밀집도 그래프로 나타내 보겠습니다.

밀집도 그래프는 plot.kde()를 이용하여 생성할 수 있습니다.

####밀집도 그래프#####
ax1 = plt.subplot()
ax1 = df['NumStorePurchases'].plot.kde() #매장구매량
plt.show()

 

육각형 그래프

마지막으로, 육각형 그래프를 그려보도록 하겠습니다.

plot.hexbin을 사용하여 육각 그래프를 그릴 수 있고, gridsize 파라미터로 그래프 육각형의 크기를 조절할 수 있습니다.

x축은 'Income'(수입) 컬럼으로, y축은 'MntWines'(와인구매량) 컬럼으로 하여 육각형 그래프를 만들어 보겠습니다.

####육각형 그래프#####
fig2,ax2 = plt.subplots()
ax2 = df.plot.hexbin(x='Income',y='MntWines',ax=ax2,gridsize=10) #gridsize: 육각형크기조절
plt.show()

위와 같이 벌집모양의 육각형 그래프가 만들어졌습니다.

전체 코드
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager,rc

# 한글 폰트 설정
font_location = 'C:/Windows/Fonts/MALGUNSL.TTF' #맑은고딕
font_name = font_manager.FontProperties(fname=font_location).get_name()
rc('font',family=font_name)
#데이터 셋 불러오기
df = pd.read_csv('marketing_campaign.csv',sep='\t')
# null값 0으로 대체
df = df.fillna(0)

########## 다변량 그래프 그리기 ###########
#다변량 그래프(3개 이상의 변수 사용)

# 학력부분 숫자로 바꾸기
def recode_edu(education_level):
    if education_level == 'Basic':
        return 0
    elif education_level == 'Graduation':
        return 1
    elif education_level == '2nCycle':
        return 2
    elif education_level == 'Master':
        return 3
    else:
        return 4

df['Edu_level'] = df['Education'].apply(recode_edu)
print(df.head())

# x축: MntMeatProducts(육류구매량)
# y축: MntWines(와인구매량)
# c(컬러): Edu_level(학력)
# s(사이즈): NumWebPurchases(웹사이트구매횟수)

#그래프틀생성
scatter_plot = plt.figure()
axes1 = scatter_plot.add_subplot(1,1,1)
#산점도 다변량 그래프 그리기
axes1.scatter(
    x=df['MntMeatProducts'],
    y=df['MntWines'],
    c=df['Edu_level'],
    s=df['NumWebPurchases']*10,
    alpha=0.5
) #alpha는 투명도 조절
axes1.set_title('다변량 그래프(학력별 다른색상, 웹사이트구매횟수는 사이즈별')
axes1.set_xlabel('육류구매량')
axes1.set_ylabel('와인구매량')
plt.show()


####밀집도 그래프#####
ax1 = plt.subplot()
ax1 = df['NumStorePurchases'].plot.kde() #매장구매량
plt.show()

####육각형 그래프#####
fig2,ax2 = plt.subplots()
ax2 = df.plot.hexbin(x='Income',y='MntWines',ax=ax2,gridsize=10) #gridsize: 육각형크기조절
plt.show()
코드 파일

ex)matplotlib(2).py
0.00MB

참고 자료
  • 책 Do it! 데이터 분석을 위한 판다스 입문 - 이지스퍼블리싱

 

마무리

저번 편에 이어 matplotlib으로 그릴 수 있는 다른 그래프들을 더 알아보았습니다.

데이터 분석 시 시각화가 필요한 그래프가 있으면 위의 내용들을 활용하여 분석을 진행하면

데이터 인사이트를 얻기에도 쉬우리라 생각됩니다. ヾ(^▽^*)))

 

++3D 그래프 추가버전 및 기타설정은 아래에서 확인하실 수 있습니다.

https://wonhwa1.blogspot.com/2022/11/python-matplotlib-3d.html

 

[python] matplotlib으로 그래프 만들기- 다변량그래프+3d, 밀집도그래프, 육각그래프, 패턴, 텍스트 설

Matplotlib 그래프 2 1편은 아래에서 확인하실 수 있습니다:) https://wonhwa1.blogspot.com/2022/11/python-matplotlib.html 데이터 준비 1편에서 사용한 csv데이터를 준비해 주세요. 또는 아래의...

wonhwa1.blogspot.com

 

반응형
반응형

안녕하세요!

오늘은 파이썬 matplotlib라이브러리를 이용해 다양한 종류의 그래프를 만들어 보도록 하겠습니다.

그럼 바로 시작해 보도록 하겠습니다.

 

데이터 준비

오늘 시각화할 데이터는 kaggle의 'Customer Personality Analysis' Datasets를 이용하여 그래프를 시각화 해보겠습니다.

아래의 링크에서 csv파일을 다운받아 주세요:)

https://www.kaggle.com/imakash3011/customer-personality-analysis

 

Customer Personality Analysis

Analysis of company's ideal customers

www.kaggle.com

이 데이터는 한 회사 고객들의 구매 정보 및 고객 정보등을 포함하고 있습니다.

각 열의 내용은 아래와 같습니다.

People
ID: Customer's unique identifier (고객식별id)
Year_Birth: Customer's birth year (출생년도)
Education: Customer's education level (학력)
Marital_Status: Customer's marital status (결혼상태)
Income: Customer's yearly household income (수입)
Kidhome: Number of children in customer's household (자녀 수)
Teenhome: Number of teenagers in customer's household (10대 자녀 수)
Dt_Customer: Date of customer's enrollment with the company (회원가입날짜)
Recency: Number of days since customer's last purchase (마지막구매 후 경과일자)
Complain: 1 if the customer complained in the last 2 years, 0 otherwise (지난 2년간 컴플레인 여부)
Products
MntWines: Amount spent on wine in last 2 years (지난 2년간 와인 구매량)
MntFruits: Amount spent on fruits in last 2 years (지난 2년간 과일 구매량)
MntMeatProducts: Amount spent on meat in last 2 years (지난 2년간 육류 구매량)
MntFishProducts: Amount spent on fish in last 2 years (지난 2년간 수산물 구매량)
MntSweetProducts: Amount spent on sweets in last 2 years (지난 2년간 간식류 구매량)
MntGoldProds: Amount spent on gold in last 2 years (지난 2년간 귀금속 구매량)

그 밖에도 여러 열이 있는데 나머지는 위의 링크에 들어가면 확인할 수 있습니다 :)

 

필요모듈 import 및 폰트설정

오늘의 주인공이자 그래프 생성에 필요한 matplotlib 라이브러리와

데이터 불러오는 데 필요한 pandas 라이브러리를 불러와 줍니다.

그리고 그래프에 한글을 사용하기 위해서 한글 폰트를 설정해 주어야 하기 때문에 폰트설정까지 해 보도록 하겠습니다.

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager,rc

# 한글 폰트 설정
font_location = 'C:/Windows/Fonts/MALGUNSL.TTF' #맑은고딕
font_name = font_manager.FontProperties(fname=font_location).get_name()
rc('font',family=font_name)

저는 '맑은 고딕'을 한글 폰트로 사용하겠습니다.

다른 폰트를 사용하고 싶다면 변경해 주시면 됩니다.

 

데이터셋 준비

위에서 다운받은 csv파일을 열어 줍니다.

이 csv파일은 ,가 아니라 tab으로 나누어져있어 sep = \t으로 설정하여 열어주어야 합니다.

그후 .head()를 사용하여 데이터 내용을 확인해 보도록 하겠습니다.

#데이터 셋 불러오기
df = pd.read_csv('marketing_campaign.csv',sep='\t')

print(df.head())

출력:

29개의 컬럼으로 데이터가 이루어져 있습니다.

각각 컬럼에 대한 설명은 위를 확인해 주세요.

이제 위의 데이터로 그래프를 만들어 보도록 하겠습니다.

히스토그램 그래프

히스토그램은 도수분포를 그래프화 시킨 건데 보통 변수 1개를 가지고 빈도를 구하여 그래프를 그립니다.

오늘 포스팅에는 고객의 자녀 수를 히스토그램으로 만들어 보도록 하겠습니다.

#############히스토그램##############
#그래프를 그리기 위한 기본 틀 생성
fig = plt.figure()
axes1=fig.add_subplot(1,1,1)

#히스토그램 그래프 만들기(변수1개)
axes1.hist(df['Kidhome'],bins = 8) #가정의 자녀 수 히스토그램 #bins는 x축 칸(간격)조정
#제목설정
axes1.set_title('고객 가정의 자녀 수 히스토그램')
#x축라벨링
axes1.set_xlabel('자녀 수')
#y축라벨링
axes1.set_ylabel('빈도')
plt.show()

위와 같이 히스토그램이 만들어 졌습니다.

데이터프레임으로도 히스토그램을 만들 수 있는데요 방법은 아래와 같습니다.

###다른방법으로 히스토그램
ax = plt.subplots()
ax = df['Kidhome'].plot.hist()
plt.show()

산점도 그리기

이번에는 matplotlib으로 산점도를 생성해보도록 하겠습니다.

산점도는 x,y 값을 점으로 찍어 그래프를 그리는방법인데,

여기서는 간식구매량을 x, 과일구매량을 y로 설정하여 산점도를 생성해 보겠습니다.

#산점도 그리기(변수2개)
scatter_plot = plt.figure()
axes2 = scatter_plot.add_subplot(1,1,1)

axes2.scatter(df['MntSweetProducts'],df['MntFruits'])
#제목설정
axes2.set_title('간식구매량 및 과일구매량 산점도')
#x축라벨링
axes2.set_xlabel('간식구매량')
#y축라벨링
axes2.set_ylabel('과일구매량')

#산점도 그리는 다른 방법
fig2,ax2 = plt.subplots()
ax2 = df.plot.scatter(x='MntSweetProducts',y='MntFruits',ax=ax2)
plt.show()

[산점도 그래프]

[df로 그린 산점도 그래프]

이렇게 2가지 방법으로 산점도를 그려 봤습니다.

 

박스그래프

이제 박스그래프를 그려보도록 하겠습니다.

박스그래프는 이산형 변수와 연속형 변수를 함께 사용하여 그리는데

이산형 변수는 성별의 male, female 과 같이 확실히 구분되는 값을 말하고,

연속형 변수는 구매량과 같은 연속적인 숫자가 있는 범위의 값을 말합니다.

이번에는 데이터의 Education(학력)을 이산형변수로,

Income(수입)을 연속형 변수로 하여 박스그래프를 그려 보도록 하겠습니다.

income값 중에 null인 값이 있어 null을 0으로 대체한 후 그래프를 생성하도록 합니다.

#############박스그래프##############
# box 그래프 그리기(이산형 변수와 연속형 변수를 함께 사용)
# 이산형: 학력
# 연속형: 수입
# df Null값 0으로 대체
df['Income'] = df['Income'].fillna(0)

boxplot = plt.figure()
axes3 = boxplot.add_subplot(1,1,1)
axes3.boxplot([df[df['Education'] == 'Basic']['Income'], 
               df[df['Education'] == 'Graduation']['Income'],
               df[df['Education'] == '2n Cycle']['Income'],
               df[df['Education'] == 'Master']['Income'], 
               df[df['Education'] == 'PhD']['Income']], 
               labels=['고졸','대졸','2nCycle','석사','박사'])

axes3.set_xlabel('학력')
axes3.set_ylabel('수입')
axes3.set_title('학력에 따른 수입 박스그래프')
plt.show()

여기서 Basic은 고등학교 졸업, Graduation은 학사, Master은 석사, PhD는 박사를 의미합니다.

2nCycle(second cycle)은 학사~석사 라고 하는데 석사 과정에 있는 사람을 말하는 것 같습니다.

혹시 2nCycle에대해 아는 분들은 댓글 남겨주세요 ㅎㅎ

그리고 df로도 박스 그래프를 그릴 수 있는데요 그전에 기존df의 피벗팅이 필요합니다.

아래와 같이 필요한 내용만 데이터를 뽑아 주세요.

# df피벗
#교육, 수입부분만뽑기
df_pv=df.iloc[:,0:5]
df_pv = df_pv.drop(['Year_Birth','Marital_Status'],axis=1) #열삭제시 axis=1
print(df_pv.head())

출력:

그 후 피벗을 진행해 줍니다.

#교육상태를 컬럼으로 피벗
df_pv = df_pv.pivot_table(
    index='ID',
    columns='Education',
    values='Income')
print(df_pv.head())

출력:

이제 다시 박스 그래프로 시각화 해보도록 하겠습니다.

#df로 박스그래프 만들기
fig3,ax3 = plt.subplots()
ax3 = df_pv.plot.box(ax= ax3)
plt.show()

위와 같이 그래프가 잘 만들어졌습니다. ㅎㅎ

전체 코드
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager,rc

# 한글 폰트 설정
font_location = 'C:/Windows/Fonts/MALGUNSL.TTF' #맑은고딕
font_name = font_manager.FontProperties(fname=font_location).get_name()
rc('font',family=font_name)
#데이터 셋 불러오기
df = pd.read_csv('marketing_campaign.csv',sep='\t')

print(df.head())

#############히스토그램##############
#그래프를 그리기 위한 기본 틀 생성
fig = plt.figure()
axes1=fig.add_subplot(1,1,1)

#히스토그램 그래프 만들기(변수1개)
axes1.hist(df['Kidhome'],bins = 8) #가정의 자녀 수 히스토그램 #bins는 x축 칸(간격)조정
#제목설정
axes1.set_title('고객 가정의 자녀 수 히스토그램')
#x축라벨링
axes1.set_xlabel('자녀 수')
#y축라벨링
axes1.set_ylabel('빈도')
#plt.show()

###다른방법으로 히스토그램
ax = plt.subplots()
ax = df['Kidhome'].plot.hist()
#plt.show()

#############산점도##############
#산점도 그리기(변수2개)
scatter_plot = plt.figure()
axes2 = scatter_plot.add_subplot(1,1,1)

axes2.scatter(df['MntSweetProducts'],df['MntFruits'])
#제목설정
axes2.set_title('간식구매량 및 과일구매량 산점도')
#x축라벨링
axes2.set_xlabel('간식구매량')
#y축라벨링
axes2.set_ylabel('과일구매량')


#산점도 그리는 다른 방법
fig2,ax2 = plt.subplots()
ax2 = df.plot.scatter(x='MntSweetProducts',y='MntFruits',ax=ax2)
#plt.show()

#############박스그래프##############
# box 그래프 그리기(이산형 변수와 연속형 변수를 함께 사용)
# 이산형: 학력
# 연속형: 수입
# df Null값 0으로 대체
df['Income'] = df['Income'].fillna(0)

boxplot = plt.figure()
axes3 = boxplot.add_subplot(1,1,1)
axes3.boxplot([df[df['Education'] == 'Basic']['Income'], 
               df[df['Education'] == 'Graduation']['Income'],
               df[df['Education'] == '2n Cycle']['Income'],
               df[df['Education'] == 'Master']['Income'], 
               df[df['Education'] == 'PhD']['Income']], 
               labels=['고졸','대졸','2nCycle','석사','박사'])

axes3.set_xlabel('학력')
axes3.set_ylabel('수입')
axes3.set_title('학력에 따른 수입 박스그래프')
#plt.show()

#df으로 box plot 그리기

# df피벗
#교육, 수입부분만뽑기
df_pv=df.iloc[:,0:5]
df_pv = df_pv.drop(['Year_Birth','Marital_Status'],axis=1) #열삭제시 axis=1
print(df_pv.head())

#교육상태를 컬럼으로 피벗
df_pv = df_pv.pivot_table(
    index='ID',
    columns='Education',
    values='Income')
print(df_pv.head())

fig3,ax3 = plt.subplots()
ax3 = df_pv.plot.box(ax= ax3)
plt.show()
코드파일

ex_matplotlib(1).py
0.00MB

참고자료
  • 책 Do it! 데이터 분석을 위한 판다스 입문 - 이지스퍼블리싱
마무리

오늘은 matplotlib로 그래프 그리는 방법을 알아보았는데요

다음 시간에는 matplotlib 2편으로 다른 그래프들도 그려보도록 하겠습니다!

궁금한 점은 댓글로 알려주세요:)

 

++ 파이그래프 추가한 글은 아래에서 확인하실 수 있습니다.

https://wonhwa1.blogspot.com/2022/11/python-matplotlib.html

 

[python] matplotlib으로 그래프 만들기- 히스토그램, 산점도, 박스그래프, 파이그래프

Matplotlib이란? matplotlib은 python에서 데이터 시각화를 도와주는 라이브러리입니다. 그럼 matplotlib을 이용해 다양한 종류의 그래프를 바로 그려 보도록 하겠습니다. 데이터 준비 오늘 시각화할 데이

wonhwa1.blogspot.com

 

반응형
반응형

안녕하세요!

오늘은 저번에 했던 용산구 CCTV위치 시각화에 이어서 가로등 위치를 추가하고 클러스터링 해보겠습니다.

CCTV위치 시각화 관련 포스팅은 아래를 참고해 주세요.

 

[python] folium을 이용하여 CCTV 위치 시각화하기

안녕하세요! ㅎㅎ 오늘을 folium을 이용해서 지리정보 시각화를 간단히 해 보려고 합니다. 그럼 시작하겠습니다! Preview step1. 데이터 준비하기 오늘 사용할 데이터는 서울 열린 데이터 광장의 '용

wonhwa.tistory.com

 

Preview

Preview

step1. 데이터 준비하기

용산구의 CCTV, 가로등 위치를 시각화 해야 되니까 두 개의 데이터 파일이 필요합니다.

1. 용산구 CCTV 파일

서울시 열린 데이터

 

열린데이터광장 메인

데이터분류,데이터검색,데이터활용

data.seoul.go.kr

2. 용산구 가로등 현황 파일(용산구)

전국 보안등 정보 표준데이터

 

전국보안등정보표준데이터

보안등정보(보안등위치, 설치개수 등)를 제공합니다. 공공데이터 개방 표준데이터 속성정보(표현형식/단위 등)는 [공공데이터 개방 표준]고시를 참고하시기 바랍니다.(정보공유>자료실>법령(고

www.data.go.kr

가로등 파일은 서울 검색 후 용산구로 다운 받으시면 됩니다.

 

step2. cctv와 가로등 위치데이터 추출하기

위치를 시각화하기위해 용산구 cctv, 가로등의 위, 경도 데이터를 모두 추출해 주도록 하겠습니다.

cctv는 전 게시물과 동일하므로 코드를 첨부하도록 하겠습니다.

###CCTV위치 꺼내기#### 
# CSV 파일 열기
import pandas as pd
file = r'C:\파일위치\yongsan_CCTV.csv'
file = file.replace('\\','//')
#print(file)
cctv_csv = pd.read_csv(file,encoding='cp949')
print(cctv_csv.head(5))

# 데이터프레임 NaN 값 대체
cctv_csv = cctv_csv.fillna(0.0)
print(cctv_csv.head())

# x좌표(위도),y좌표(경도) 리스트로 만들기
x = []
y = []
for i in range(len(cctv_csv['WGS x좌표'])):
    if cctv_csv['WGS x좌표'][i] == 0.0 or cctv_csv['WGS y좌표'][i] == 0.0:
        pass
    else:

        x.append(cctv_csv['WGS x좌표'][i])
        y.append(cctv_csv['WGS y좌표'][i])
print('x갯수: ',len(x))
print('y갯수: ',len(y))

이제 가로등 위치를 꺼내보도록 하겠습니다.

가로등도 cctv와 마찬가지로 데이터 확인 후 필요정보를 뽑아보도록 하겠습니다.

####가로등 파일 열기#####
# CSV 파일 열기
import pandas as pd
file = r'C:\파일위치\서울특별시_용산구_보안등정보.csv'
file = file.replace('\\','//')
#print(file)
street_csv = pd.read_csv(file,encoding='cp949')
print(street_csv.head())

출력:

여기서 필요한 정보는 위도(x) 경도(y), 그리고 나중에 위치 마킹할 때 이름을 달아주기 위해 보안등 위치명까지 뽑아 보도록 하겠습니다.

NaN이 있는 곳은 0.0으로 대체 후 , 위경도에 0.0이 있으면 그 곳은 제외하는 방식으로 값을 저장해 주도록 하겠습니다.

# 데이터프레임 NaN 값 대체
street_csv = street_csv.fillna(0.0)
print(street_csv.head())

# x좌표(위도),y좌표(경도), 이름 리스트로 만들기
x1 = []
y1 = []
name = []
for i in range(len(street_csv['위도'])):
    if street_csv['위도'][i] == 0.0 or street_csv['경도'][i] == 0.0:
        pass
    else:
        name.append(street_csv['보안등위치명'][i])
        x1.append(street_csv['위도'][i])
        y1.append(street_csv['경도'][i])
print('이름갯수: ',len(name))
print('x갯수: ',len(x1))
print('y갯수: ',len(y1))

출력:

가로등 수가 cctv 수보다 훨씬 많습니다.

 

step3. 지도를 만들고 그 위에 위치 표시하기

이제 필요한 데이터 준비는 다 되었으니 시각화해 보도록 하겠습니다.

지도를 불러오고, 그 위에 용산구 geojson파일로 구역을 눈에 들어오도록 시각화 해보겠습니다.

용산구 geojson 파일은 제가 미리 준비해 놓았으니 아래의 파일을 다운받아 사용해 주시면 됩니다:)

yongsan.zip.geojson
0.04MB

######지도 만들기#####
import folium
import folium.plugins as plug
import json

#map 만들기
map_osm = folium.Map(location=[37.538821, 126.98368841130002],zoom_start=14)
#geojson파일 오픈
file_name= r'C:\파일위치\yongsan.zip.geojson'
file_name = file_name.replace('\\','/')
with open(file_name, 'rt') as f:
    geo = json.load(f)
    f.close()
folium.GeoJson(geo, name='YongSan').add_to(map_osm)
map_osm

이렇게 용산구 지역에 표시가 되었습니다.ㅎㅎ

다음으로 cctv랑 가로등의 위치를 찍고 클러스터링 해 보도록 하겠습니다.

###가로등, cctv 위치 표시및 클러스터링### 
import folium.plugins as plug
marker_cluster = plug.MarkerCluster().add_to(map_osm)

for i in range(len(x)):

    folium.Marker([x[i],y[i]], popup='용산CCTV_%d'%i, icon=folium.Icon(color='red', icon='ok-circle')).add_to(marker_cluster)

for i in range(len(x1)):
    
    folium.Marker([x1[i],y1[i]], popup= name[i], icon=folium.Icon(color='orange', icon='star')).add_to(marker_cluster)

지도 위에 표시하는 아이콘은 모양을 설정할 수 있는데요 icon 종류는 아래의 링크를 참고해주세요.

glyphicons

 

Components · Bootstrap

Extend form controls by adding text or buttons before, after, or on both sides of any text-based . Use .input-group with an .input-group-addon or .input-group-btn to prepend or append elements to a single .form-control. Textual s only Avoid using elements

getbootstrap.com

마크 Icon 종류

만약 음표 아이콘을 쓰고 싶다면 파라미터에 icon=folium.Icon(icon=music) 이렇게 작성하면 됩니다.

다른 아이콘도 glyphicon glyphicon- 뒤에 써져 있는 아이콘이름을 입력해 주면 적용이 됩니다ㅎㅎ 

#map저장
map_osm.save('YONGSAN.html')

결과물: 

자 그럼 이렇게 완성이 됩니다 ㅎㅎ

스크롤을 위로 올리면 확대가 되면서 원이 더 많이 생기고 그중 하나를 클릭해 보면,

아까 만든 cctv,가로등 마크와 이름을 확인할 수 있습니다.

별모양은 가로등, cctv는 빨간 마크입니다.

전체 코드
####CCTV#####
# CSV 파일 열기
import pandas as pd
file = r'C:\파일위치\yongsan_CCTV.csv'
file = file.replace('\\','//')
#print(file)
cctv_csv = pd.read_csv(file,encoding='cp949')
print(cctv_csv.head(5))

# 데이터프레임 NaN 값 대체
cctv_csv = cctv_csv.fillna(0.0)
print(cctv_csv.head())

# x좌표(위도),y좌표(경도) 리스트로 만들기
x = []
y = []
for i in range(len(cctv_csv['WGS x좌표'])):
    if cctv_csv['WGS x좌표'][i] == 0.0 or cctv_csv['WGS y좌표'][i] == 0.0:
        pass
    else:

        x.append(cctv_csv['WGS x좌표'][i])
        y.append(cctv_csv['WGS y좌표'][i])
print('x갯수: ',len(x))
print('y갯수: ',len(y))

#####가로등######
# CSV 파일 열기
import pandas as pd
file = r'C:\Users\user\Desktop\web_AI\python_code\서울특별시_용산구_보안등정보.csv'
file = file.replace('\\','//')
#print(file)
street_csv = pd.read_csv(file,encoding='cp949')
print(street_csv.head())

# 데이터프레임 NaN 값 대체
street_csv = street_csv.fillna(0.0)
print(street_csv.head())

# x좌표(위도),y좌표(경도), 이름 리스트로 만들기
x1 = []
y1 = []
name = []
for i in range(len(street_csv['위도'])):
    if street_csv['위도'][i] == 0.0 or street_csv['경도'][i] == 0.0:
        pass
    else:
        name.append(street_csv['보안등위치명'][i])
        x1.append(street_csv['위도'][i])
        y1.append(street_csv['경도'][i])
print('이름갯수: ',len(name))
print('x갯수: ',len(x1))
print('y갯수: ',len(y1))

######지도생성######
import folium
import folium.plugins as plug
import json
#map 만들기
map_osm = folium.Map(location=[37.538821, 126.98368841130002],zoom_start=14)
#클러스터추가
marker_cluster = plug.MarkerCluster().add_to(map_osm)
#geojson파일 오픈
file_name= r'C:\Users\user\Downloads\yongsan.zip.geojson'
file_name = file_name.replace('\\','/')
with open(file_name, 'rt') as f:
    geo = json.load(f)
    f.close()
folium.GeoJson(geo, name='YongSan').add_to(map_osm)

for i in range(len(x)):

    folium.Marker([x[i],y[i]], popup='용산CCTV_%d'%i, icon=folium.Icon(color='red', icon='ok-circle')).add_to(marker_cluster)

for i in range(len(x1)):
    folium.Marker([x1[i],y1[i]], popup= name[i], icon=folium.Icon(color='orange', icon='star')).add_to(marker_cluster)

#map저장
map_osm.save('YONGSAN.html')
코드 파일

깃허브

 

GitHub - ElenaLim/Visualizations: This repository is for python visualizations, enjoy🤟

This repository is for python visualizations, enjoy🤟 - GitHub - ElenaLim/Visualizations: This repository is for python visualizations, enjoy🤟

github.com

 

마무리

오늘은 이렇게 geojson과 클러스터링까지 하여 시각화를 해보았습니다 ㅎㅎ

이런 위치정보를 가지고 안전한 길찾기 서비스를 해도 좋을 것 같네요.

다른 좋은 아이디어가 있으면 댓글로 공유 부탁드려요 ㅎㅎ

반응형
반응형

안녕하세요! ㅎㅎ

오늘은 folium을 이용해서 지리정보 시각화를 간단히 해 보려고 합니다.

그럼 시작하겠습니다!

Preview

step1. 데이터 준비하기

오늘 사용할 데이터는 서울 열린 데이터 광장의 '용산구 cctv 설치현황. csv'를 다운로드하여 시각화할 예정입니다.

아래의 링크를 눌러 csv파일을 다운로드 받아 주세요.

[서울 용산구 cctv] 설치현황

 

열린데이터광장 메인

데이터분류,데이터검색,데이터활용

data.seoul.go.kr

위의 내려받기(CSV)를 클릭하면 csv파일이 다운받아집니다:)

 

step 2. 위치정보 데이터 추출하기

위에서 다운로드하여준 csv를 열어 주고 내용을 확인해 보도록 하겠습니다.

항상 파일 위치를 열 때는 \를 //로 바꿔주어야 유니코드 오류가 뜨지 않고 잘 열 수 있습니다.

# CSV 파일 열기
import pandas as pd
file = r'C:\파일위치\yongsan_CCTV.csv'
file = file.replace('\\','//')
#print(file)
cctv_csv = pd.read_csv(file,encoding='cp949')
print(cctv_csv.head(5))

출력:

이렇게 용산구의 cctv가 있는 주소, x, y좌표 등등의 정보를 확인할 수 있습니다.

파일 중간중간 NAN이 있는 걸로 보아 위치 데이터에도 값이 없는 부분이 있을 수 있어

NaN이 있는 부분을 전부 0으로 바꾸어 주도록 하겠습니다.

# 데이터프레임 NaN 값 대체
cctv_csv = cctv_csv.fillna(0.0)
print(cctv_csv.head())

출력:

위처럼 NaN이 0.0으로 모두 바뀌었습니다.

이제 위치를 지도에 표시하기 위해 x좌표(위도), y좌표(경도)를 따로 준비해 주도록 하겠습니다.

여기서 0.0 값(NaN값이었던)을 가지는 행은 제외하고 좌표를 리스트로 모아보도록 하겠습니다. 

# x좌표(위도),y좌표(경도) 리스트로 만들기
x = []
y = []
for i in range(len(cctv_csv['WGS x좌표'])):
    if cctv_csv['WGS x좌표'][i] == 0.0 or cctv_csv['WGS y좌표'][i] == 0.0:
        pass
    else:

        x.append(cctv_csv['WGS x좌표'][i])
        y.append(cctv_csv['WGS y좌표'][i])
print('x갯수: ',len(x))
print('y갯수: ',len(y))

출력:

이렇게 위, 경도 각각 743개가 잘 들어가 있음을 확인할 수 있습니다.

 

step3. 지도에 위치 마커 표시하기

이제 folium을 이용해 지도를 불러오고, 불러온 지도에 CCTV 위치 정보를 표시하여 시각화해보도록 하겠습니다.

#지도 생성 및 marker 지정하기
import folium
map_osm = folium.Map(location=[x[13],y[13]],zoom_start=14)
for i in range(len(x)):
    folium.Marker([x[i],y[i]], popup='용산CCTV_%d'%i, icon=folium.Icon(color='red', icon='info-sign')).add_to(map_osm)
# 지도에서 범위 지정
folium.CircleMarker(location=[x[13],y[13]],popup='용산구 CCTV', radius=300, color="#3186cc", fill_color="#3186cc").add_to(map_osm)
#map저장
map_osm.save('yongsan_cctv.html')

출력:

위와 같이 Marker를 지정하면 아이콘 모양 및 색상을 정할 수 있습니다. pop-up은 지도에 표시되어 있는 아이콘을 클릭했을 때 나오는 설명 문구입니다. 

여기에서는 csv의 cctv입력 순서에 따라 cctv_1 cctv_2 cctv3... 등으로 이름을 지정해 주었습니다.

또 서클 마커(CircleMarker)를 사용하면 위의 파란색 원과 같이 범위를 지정할 수 있습니다.

색 또한 지정 가능하니 참고하시면 됩니다.

전체 코드
# CSV 파일 열기
import pandas as pd
file = r'파일위치\yongsan_CCTV.csv'
file = file.replace('\\','//')
#print(file)
cctv_csv = pd.read_csv(file,encoding='cp949')
print(cctv_csv.head(5))

# 데이터프레임 NaN 값 대체
cctv_csv = cctv_csv.fillna(0.0)
print(cctv_csv.head())

# x좌표(위도),y좌표(경도) 리스트로 만들기
x = []
y = []
for i in range(len(cctv_csv['WGS x좌표'])):
    if cctv_csv['WGS x좌표'][i] == 0.0 or cctv_csv['WGS y좌표'][i] == 0.0:
        pass
    else:

        x.append(cctv_csv['WGS x좌표'][i])
        y.append(cctv_csv['WGS y좌표'][i])
print('x갯수: ',len(x))
print('y갯수: ',len(y))



#지도 생성 및 marker 지정하기
import folium
map_osm = folium.Map(location=[x[13],y[13]],zoom_start=14)
for i in range(len(x)):
    folium.Marker([x[i],y[i]], popup='용산CCTV_%d'%i, icon=folium.Icon(color='red', icon='info-sign')).add_to(map_osm)
# 지도에서 범위 지정
folium.CircleMarker(location=[x[13],y[13]],popup='용산구 CCTV', radius=300, color="#3186cc", fill_color="#3186cc").add_to(map_osm)
#map저장
map_osm.save('yongsan_cctv.html')

 

코드 파일

cctv_map.py
0.00MB

참고 문서

folium 공식문서

 

Folium — Folium 0.12.1 documentation

folium builds on the data wrangling strengths of the Python ecosystem and the mapping strengths of the leaflet.js library. Manipulate your data in Python, then visualize it in on a Leaflet map via folium. Concepts folium makes it easy to visualize data tha

python-visualization.github.io

마무리

 

오늘은 파이썬으로 지도위치 시각화하는 방법을 알아보았습니다ㅎㅎ csv파일과 위치 좌표만 있으면

간편하게 시각화가 가능합니다. 질문은 댓글 달아주세요 :)

반응형
반응형

안녕하세요!

오늘은 저번에 만들었던 네이버 블로그 크롤러를 이용해서 txt 파일을 만들고

만들어진 텍스트 파일을 이용하여 워드 클라우드(WordCloud)로 시각화해보도록 하겠습니다.

 

step1. 데이터 준비
 

[python] Naver 오픈API를 이용하여 원하는 검색어로 블로그 크롤링 하기(제목+본문)

오늘은 NAVER API를 이용하여 네이버 블로그 크롤링을 해 보겠습니다 ;) NAVER OPEN API 신청하는 방법은 여기를 클릭해주세요ㅎㅎ step1. 네이버 OPEN API를 이용하여 원하는 검색어로 관련 게시물 불러오

wonhwa.tistory.com

 

위의 링크를 클릭하여 원하는 검색어 입력 후 관련 내용을 text 파일로 만들어 준비해 줍니다.

저는 '상암 맛집' 이라는 키워드로 'blog_text.txt' 파일을 만들어 보았습니다.

blog_text.txt
0.42MB

 

이제 위 파일 또는 다른 검색어로 크롤링한 파일을 파이썬으로 열어 줍니다.

파이썬으로 파일 주소를 입력할 때는 꼭 \를 //로 바꾸어 주세요!

# text 파일 읽어오기
#※※주소불러올때 \를 //로 바꾸어주기※※
blog_text = open('주소입력//blog_text.txt','rt', encoding='UTF-8').read()

# csv 파일일때
# import pandas as pd
# blog_text = pd.read_csv('csv파일.csv',encoding='utf-8')
# blog_text = blog_text['형태소분석할 컬럼명']
step2. Konlpy를 이용해 text의 형태소 분석하여 텍스트 전처리하기

텍스트 파일을 불러오고, 파일 안에 텍스트들을 konlpy를 이용해 명사, 형용사만 추출하도록 하겠습니다.

konlpy의 Okt를 이용하여 추출하도록 하겠습니다.

텍스트 한 줄 마다 형용사와 명사를 뽑아

n_adj라는 변수에 리스트를 만들어 단어를 추가해 줍니다.

from konlpy.tag import Okt
from collections import Counter

# Okt 함수를 이용해 형태소 분석
okt = Okt()
line =[]

line = okt.pos(blog_text)

n_adj =[]
# 명사 또는 형용사인 단어만 n_adj에 넣어주기
for word, tag in line:
    if tag in ['Noun','Adjective']:
        n_adj.append(word)
# 명사 또는 형용사인 단어 및 2글자 이상인 단어 선택 시
# n_adj = [word for word, tag in line if tag in ['Noun','Adjective'] and len(word) > 1]
print(n_adj)

출력:

위에를 보면 '아니었네요. ,  끝' 등과 같은 워드클라우드를 만들 때 부적절한 단어가 있습니다.

위같은 단어를 '불용어(stopwords)'라고 하는데 이 불용어들을 리스트에서 지워 주도록 하겠습니다.

#제외할 단어 추가
stop_words = "아니었네요. 있어서 끝 " #추가할 때 띄어쓰기로 추가해주기
stop_words = set(stop_words.split(' '))
# 불용어를 제외한 단어만 남기기
n_adj = [word for word in n_adj if not word in stop_words]

다음으로 같은 단어들이 2개 이상 나오는 것들을 counter를 이용하여 세어 주고,

가장 많이 나온 단어 100단어만 남기겠습니다.

#가장 많이 나온 단어 100개 저장
counts = Counter(n_adj)
tags = counts.most_common(100)

그 후 이 100단어들로 워드클라우드를 만들어 보겠습니다.

step3. 워드클라우드 만들기

저는 워드 클라우드에 모양을 넣어주고 싶어 하트 모양의 사진을 준비하여

하트 모양의 워드 클라우드를 만들어 보았습니다.

이런 하트 사진 또는 원하는 사진을 (배경이 투명해야 합니다.) 다운로드 받아 주세요.

# 이미지 추가(워드크라우드 모양 설정)
import numpy as np
from PIL import Image

mask = Image.new("RGBA",(2555,2275), (255,255,255)) #(2555,2575)는 사진 크기, (255,255,255)는 색을의미
image = Image.open('사진주소//heart.png').convert("RGBA")
x,y = image.size
mask.paste(image,(0,0,x,y),image)
mask = np.array(mask)

이렇게 이미지를 설정해주고,(제가 사용하는 이미지는 2555 x 2275 pixel 입니다.)

위의 mask를 사용하여 WordCloud를 만들어 주도록 하겠습니다.

한글을 사용하기 때문에 원하는 폰트 파일(.ttf)을 다운받아 설치하여 아래와 같이 파일 위치 및 이름을 적어줍니다.

저는 배경은(background) 검은색(black)으로, mask(모양)은 하트모양으로, 색상(colormap)은 프리즘(prism)을 이용해 

워드 클라우드를 만들어 주었습니다.

from wordcloud import WordCloud

###WordCloud(워드크라우드) 만들기###
#폰트지정
font='C://Users//user//AppData//Local//Microsoft//Windows//Fonts//BMDOHYEON.ttf'
word_cloud = WordCloud(font_path=font, background_color='black',max_font_size=400, mask=mask,colormap='prism').generate_from_frequencies(dict(tags))

# 사이즈 설정 및 화면에 출력
import matplotlib.pyplot as plt
plt.figure(figsize=(10,8))
plt.imshow(word_cloud)
plt.axis('off')
#워드클라우드 사진으로 저장
#cloud.to_file('상암맛집_wc.png')
#또는
plt.savefig('상암맛집.png', bbox_inches='tight')
plt.show()

출력:

그럼 위에 모양과 같이 하트모양의 상암맛집과 관련한 워드클라우드가 만들어졌습니다. ㅎㅎ

저는 검색어를 상암맛집으로 했기 때문에 이를 보여주기 위해 상암 맛집을 그대로 놔두었지만,

상암 맛집을 검색해서 나온 내용을 텍스트로 만들었기때문에 실제 정확한 분석을 위해서는

'상암, 맛집' 이 두 단어를 불용어로 두어 처리하고 다른 불용어를 더 추가해 다듬는다면

더 퀄리티 높은 워드클라우드가 만들어질 것 같습니다.

 

++추가로 워드클라우드의 글자 색상은 워드클라우드 파라미터인 colormap을 통해 변경할 수 있습니다.

아래 사진을 참고하여 원하는 컬러 맵 이름을 파라미터에 적어주면 적용 됩니다 :)

ex) colormap = 'autumn' 이런 식으로 작성하면 됩니다.

참고해 주세요 ^0^

컬러맵 종류

전체 코드
from konlpy.tag import Okt
from wordcloud import WordCloud
from collections import Counter

# text 파일 읽어오기
#※※주소불러올때 \를 //로 바꾸어주기※※
blog_text = open('C://주소//blog_text.txt','rt', encoding='UTF-8').read()
#print(blog_text)

# csv 파일일때
# import pandas as pd
# blog_text = pd.read_csv('csv파일.csv',encoding='utf-8')
# blog_text = blog_text['형태소분석할 컬럼명']

# Okt 함수를 이용해 형태소 분석
okt = Okt()
line =[]

line = okt.pos(blog_text)

n_adj =[]
# 명사 또는 형용사인 단어만 n_adj에 넣어주기
for word, tag in line:
    if tag in ['Noun','Adjective']:
        n_adj.append(word)
# 명사 또는 형용사인 단어 및 2글자 이상인 단어 선택 시
# n_adj = [word for word, tag in line if tag in ['Noun','Adjective'] and len(word) > 1]

#제외할 단어 추가
stop_words = "상암맛집 입니다 있어서 입니다." #추가할 때 띄어쓰기로 추가해주기
stop_words = set(stop_words.split(' '))

n_adj = [word for word in n_adj if not word in stop_words]
print(n_adj)

#print(line)
#print(n_adj)

#가장 많이 나온 단어 100개 저장
counts = Counter(n_adj)
tags = counts.most_common(100)

# 이미지 추가(워드크라우드 모양 설정)
import numpy as np
from PIL import Image

mask = Image.new("RGBA",(2555,2275), (255,255,255)) #(2555,2575)는 사진 크기, (255,255,255)는 색을의미
image = Image.open('C://Users//user//주소//heart.png').convert("RGBA")
x,y = image.size
mask.paste(image,(0,0,x,y),image)
mask = np.array(mask)

###WordCloud(워드크라우드) 만들기###
#폰트지정
font='C://폰트주소//폰트이름.ttf'
word_cloud = WordCloud(font_path=font, background_color='black',max_font_size=400, mask=mask,colormap='prism').generate_from_frequencies(dict(tags))

# 사이즈 설정 및 화면에 출력
import matplotlib.pyplot as plt
plt.figure(figsize=(10,8))
plt.imshow(word_cloud)
plt.axis('off')
#워드클라우드 사진으로 저장
#cloud.to_file('상암맛집_wc.png')
#또는
plt.savefig('상암맛집.png', bbox_inches='tight')
plt.show()

 

코드 파일

word_cloud_blog.py
0.00MB

마무리

오늘은 크롤링한 텍스트파일로 워드클라우드를 만들어 보았습니다.

항상 전처리가 시간이 많이 걸리고 전처리를 잘 해야 시각화도 잘 되어서 그 중요성을 다시 깨닫게 되네요ㅎㅎ

이번에는 블로그를 예제로 해서 워드클라우드를 만들었지만

뉴스나 연설문 등을 텍스트로 만들어 워드클라우드 해봐도 좋겠네요.

더 궁금한 것이 있다면 댓글 남겨주세요 :)

반응형
반응형

저번 게시물에 이어 OPEN API를 이용해 코로나 확진자 수를 bar_chart_race로 시각화 해 보겠습니다.

Preview

Preview

공공데이터 OPENAPI를 이용해 데이터를 가져오는 방법은 아래의 링크를 참고하여 주세요.

 

[python] 공공데이터 OPEN API의 xml 을 DataFrame으로 변환하기(feat. 코로나 확진자 수)

안녕하세요~! 오늘은 공공데이터 openAPI의 xml을 Pandas DataFrame으로 변환하여 보도록 하겠습니다. json에서 DataFrame으로의 변환은 여기를 클릭해서 확인해 주세요 :) step1. 데이터 활용신청하기 공공데

wonhwa.tistory.com

 

step1. 데이터 준비

저번 게시물을 통해 만든

전국 코로나 확진자 수(2020년도~2021년도 11월 3일까지) 데이터인 'corona_kr.csv' 파일을 불러와줍니다.

import pandas as pd
import bar_chart_race as bcr

#csv파일 불러오기(코로나 전국 확진자)
corona_csv=pd.read_csv('corona_kr.csv')
print(corona_csv.head(19))

이렇게 많은 컬럼 값에 각 값이 들어가있습니다.

각 컬럼의 의미는 아래와 같습니다.(공공데이터 포털에서 확인 가능합니다.)

각 컬럼 값 정보
SEQ : 게시글번호(국내 시도별 발생현황 고유값)
CREATE_DT:  등록일시분초
DEATH_CNT:  사망자 수
GUBUN:  시도명(한글)
GUBUN_CN:   시도명(중국어)
gubunEn: 시도명(영어)
INC_DEC: 전일대비 증감 수
ISOL_CLEAR_CNT: 격리 해제 수
QUR_RATE: 10만명당 발생률
STD_DAY: 기준일시
UPDATE_DT: 수정일시분초
DEF_CNT: 확진자 수
ISOL_ING_CNT: 격리중 환자수
OVER_FLOW_CNT: 해외유입 수
LOCAL_OCC_CNT: 지역발생 수
step2. 시각화를 위한 데이터 전처리하기

여기서 시도별 확진자 수 시각화를 하기 위해

확진자 수, 업데이트날짜, 시도명(영어) 컬럼 값만 남기고 나머지는 지워보겠습니다.

#필요한 데이터만 남기고 지우기
corona = corona_csv[['createDt','defCnt','gubunEn']] # 등록일시분초, 확진자 수, 시도명(영어)
print(corona.head(19))

출력:

여기서 날짜 - 시도명 - 확진자 순으로 컬럼 순서를 바꿔 주도록 하겠습니다.

#열 순서 바꾸기 (등록일시, 시도명, 확진자 수 순)
corona = corona[['createDt','gubunEn','defCnt']]
print(corona.head(19))

위처럼 시간 - 이름 - 확진자 수 로 순서 배치가 잘 되었음을 확인할 수 있습니다.

다음으로, 시각화할때 관련없는 검역(Lazaretto)과 총합(Total)행을 지워주도록 하겠습니다.

 gubunEn(시도 영어명)이 Lazaretto, Total 이 아닌 행만 남기는 조건을 달아 보도록 하겠습니다.

#필요없는 데이터 지우기(검역Lazaretto, 토탈Total)
condition = (corona.gubunEn != 'Lazaretto') & (corona.gubunEn !='Total')
corona = corona[condition]
print(corona.head(17))

출력:

위 사진과 같이 잘 지워졌음을 확인할 수 있습니다.

이제 열값을 도시명으로 하고 값을 확진자 수로 피벗팅 해보겠습니다.

그리고 그 후 NaN값이 있는지 확인해 보도록 하겠습니다.

# 열값을 지역(gubunEn)으로, 값을 확진자 수(defCnt)로 하여 피봇팅하기
corona_df = corona.pivot_table(values = 'defCnt', index = ['createDt'], columns='gubunEn')

#nan값 있는지 확인 True이면 null값이 있음
print(pd.isnull(corona_df))

출력:

중간중간 True가 있는 것을 보니 피벗후 데이터프레임에 NaN값이 있는 것을 확인 할 수 있습니다.

이 NaN값들을 모두 0으로 바꾸어주도록 하겠습니다.

# NaN값을 0으로 바꾸어 주기
corona_df.fillna(0,inplace=True)
print(corona_df.head())

출력:

그럼 이렇게 0.0으로 대체되었음을 확인할 수 있습니다.

이제 전처리 마지막 단계입니다.

bar_chart_race로 시각화하기 위해 다음행을 그 전 행의 누적하여 값을 나타내 주도록 하겠습니다.

# 확진자 수 누적값으로 만들어주기
corona_df.iloc[:,0:-1] = corona_df.iloc[:,0:-1].cumsum()
print(corona_df.head())

출력:

위 사진과 같이 누적값으로 변환이 되었습니다.

step3. bar_chart_race로 시각화하기
#bar_chart_race로 시각화하기
bcr.bar_chart_race(df = corona_df,
                    n_bars= 17,
                    sort='desc',
                    title='Corona in Korea',
                    filename='한국_코로나확진자.mp4')

시도명이 총 17개이므로 n_bars를 17로, 정렬(sort)은 내림차순으로 하여 큰 숫자부터 앞에 나타나도록 하였습니다.

title(제목)을 설정해주고 , 파일을 mp4로 저장하기 위해 filename을 설정해 주었습니다.

이번 데이터는 양이 많기 때문에 그래프를 생성하는데 시간이 오래 걸립니다.

이점 참고해 주세요.

또는 step2의 데이터 전처리 과정에서 시간 행을 줄이고 시각화 하시길 바랍니다.

출력:

 

2020년~2021년도 11월 3일까지 전국 코로나 확진자 수 시각화

[한글버전]

 

전체 코드
import pandas as pd
import bar_chart_race as bcr

#csv파일 불러오기(코로나 전국 확진자)
corona_csv=pd.read_csv('corona_kr.csv')

#print(corona_csv.head(19))

## 각 컬럼 값 ## (포털 문서에서 꼭 확인하세요)
"""
SEQ : 게시글번호(국내 시도별 발생현황 고유값)
CREATE_DT: 	등록일시분초
DEATH_CNT: 	사망자 수
GUBUN: 	시도명(한글)
GUBUN_CN: 	시도명(중국어)
gubunEn: 시도명(영어)
INC_DEC: 전일대비 증감 수
ISOL_CLEAR_CNT: 격리 해제 수
QUR_RATE: 10만명당 발생률
STD_DAY: 기준일시
UPDATE_DT: 수정일시분초
DEF_CNT: 확진자 수
ISOL_ING_CNT: 격리중 환자수
OVER_FLOW_CNT: 해외유입 수
LOCAL_OCC_CNT: 지역발생 수

""" 

#필요한 데이터만 남기고 지우기
corona = corona_csv[['createDt','defCnt','gubunEn']] # 등록일시분초, 확진자 수, 시도명(영어)
#print(corona.head(19))

#열 순서 바꾸기 (등록일시, 시도명, 확진자 수 순)
corona = corona[['createDt','gubunEn','defCnt']]
#print(corona.head(19))

#필요없는 데이터 지우기(검역Lazaretto, 토탈Total)
condition = (corona.gubunEn != 'Lazaretto') & (corona.gubunEn !='Total')
corona = corona[condition]
#print(corona.head(17))

# 열값을 지역(gubunEn)으로, 값을 확진자 수(defCnt)로 하여 피봇팅하기
corona_df = corona.pivot_table(values = 'defCnt', index = ['createDt'], columns='gubunEn')

#nan값 있는지 확인 True이면 null값이 있음
#print(pd.isnull(corona_df))

# NaN값을 0으로 바꾸어 주기
corona_df.fillna(0,inplace=True)
#print(corona_df.head())

# 확진자 수 누적값으로 만들어주기
corona_df.iloc[:,0:-1] = corona_df.iloc[:,0:-1].cumsum()
print(corona_df.head())

#bar_chart_race로 시각화하기
bcr.bar_chart_race(df = corona_df,
                    n_bars= 17,
                    sort='desc',
                    title='Corona in Korea',
                    filename='한국_코로나확진자.mp4')

아래는 한글 버전입니다.

###한글버전###
import pandas as pd
import bar_chart_race as bcr
from matplotlib import font_manager,rc

# 한글 폰트 설정
font_location = 'C:/Windows/Fonts/MALGUNSL.TTF' #맑은고딕
font_name = font_manager.FontProperties(fname=font_location).get_name()
rc('font',family=font_name)

#csv파일 불러오기(코로나 전국 확진자)
corona_csv=pd.read_csv('corona_kr.csv')

#필요한 데이터만 남기고 지우기
corona = corona_csv[['createDt','defCnt','gubun']] # 등록일시분초, 확진자 수, 시도명(한글)

#열 순서 바꾸기 (등록일시, 시도명, 확진자 수 순)
corona = corona[['createDt','gubun','defCnt']]

#필요없는 데이터 지우기(검역Lazaretto, 합계Total)
condition = (corona.gubun != '검역') & (corona.gubun !='합계')
corona = corona[condition]

# 열값을 지역(gubun)으로, 값을 확진자 수(defCnt)로 하여 피봇팅하기
corona_df = corona.pivot_table(values = 'defCnt', index = ['createDt'], columns='gubun')

# NaN값을 0으로 바꾸어 주기
corona_df.fillna(0,inplace=True)

# 확진자 수 누적값으로 만들어주기
corona_df.iloc[:,0:-1] = corona_df.iloc[:,0:-1].cumsum()

#bar_chart_race로 시각화하기
bcr.bar_chart_race(df = corona_df,
                    shared_fontdict={'family':font_name},
                    n_bars= 17,
                    sort='desc',
                    title='한국 코로나 누적 확진자(2019-2021)',
                    filename='한국_코로나확진자_한글.mp4')
코드 파일

corona_bar_chart_race.py
0.00MB
bar_chart_race(kor).py
0.00MB

마무리

저번 시각화에 이어 오늘은 공공데이터 OPEN API를 이용하여 수집한 데이터를 토대로 시각화를 해 보았습니다.

거의 2년치를 시각화하느라 시간이 꽤 걸렸는데요. 

공공 데이터를 이용해 다른 분야도 위 게시글을 활용하여 시각화 해보시길 바랍니다 :)

질문은 댓글로 남겨주세요 ^ㅇ^

 

++ 22.07.05 한국어 버전 추가

반응형

+ Recent posts