<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>mare-solis.log</title>
        <link>https://velog.io/</link>
        <description>콘텐츠 전문가가 되고 싶은 방구석 연구인 🧐</description>
        <lastBuildDate>Tue, 19 Jul 2022 13:48:12 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>mare-solis.log</title>
            <url>https://images.velog.io/images/mare-solis/profile/4a72b56e-8e67-43db-b25c-78c6064f0472/FAFBE424-DC9B-4D65-B4A0-7684E089D3B8.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. mare-solis.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/mare-solis" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[인공지능 예술가 달리2(DALL-E2)로 그림 그리기]]></title>
            <link>https://velog.io/@mare-solis/%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5-%EC%98%88%EC%88%A0%EA%B0%80-%EB%8B%AC%EB%A6%AC2DALLE2%EB%A1%9C-%EA%B7%B8%EB%A6%BC-%EA%B7%B8%EB%A6%AC%EA%B8%B0</link>
            <guid>https://velog.io/@mare-solis/%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5-%EC%98%88%EC%88%A0%EA%B0%80-%EB%8B%AC%EB%A6%AC2DALLE2%EB%A1%9C-%EA%B7%B8%EB%A6%BC-%EA%B7%B8%EB%A6%AC%EA%B8%B0</guid>
            <pubDate>Tue, 19 Jul 2022 13:48:12 GMT</pubDate>
            <description><![CDATA[<h1 id="1-소개">1. 소개</h1>
<p>그림 그려주는 인공지능 달리는 지난 2021년 1월 OpenAI에서 공개한 인공지능 시스템으로, 자연어로 그림을 묘사하면 그대로 그려주는 기능을 합니다. 올해는 훨씬 더 정확하고 해상도 높은 이미지를 생성하는 <a href="https://openai.com/dall-e-2/">달리2</a>를 공개했죠.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/6cd9428c-d9de-4875-b8e0-c96867aac342/image.png" alt=""></p>
<p>달리(DALL·E)라는 이름은 예술가 살바도르 달리와 디즈니 영화 월-E에서 따왔습니다. 달리2는 OpenAI의 초거대 언어 모델 GPT-3를 활용하여 이미지와 그 이미지를 설명한 텍스트의 관계를 훈련했습니다. 무려 35억개의 파라미터를 사용했는데, 이는 달리1이 사용한 120억개의 파라미터보다는 현저히 줄어든 것이라고 합니다.</p>
<p>하지만 인공지능이 발전한 만큼 윤리적인 문제도 있습니다. 가장 큰 문제는 실제 인물이 합성에 마구잡이로 이용될 수 있다는 것입니다. 이는 딥페이크가 당면한 문제점이기도 하죠. 게다가 달리는 자연어만 입력하면 이미지가 자동으로 완성되므로 누구나 쉽게 부적절한 이미지를 생성할 수 있다는 문제가 있습니다.</p>
<p>따라서 OpenAI는 GPT와 마찬가지로 달리의 소스 코드를 공개하지 않기로 결정했습니다. 그리고 올초 달리2를 공개하며 한정된 사람들만 달리2를 사용할 수 있도록 베타 테스트 대기 신청을 받았습니다. </p>
<p>그래서 저도 올 3월 대기 신청을 했었는데요. 딱 4개월만에 액세스를 받아 사용할 수 있게 되었습니다. 초대 메일은 아래처럼 옵니다. &quot;책임감있게 사용할 거라 믿는다&quot;는 문구가 눈에 띄네요.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/44d93089-5fe9-4969-9958-227e294c4d91/image.png" alt=""></p>
<p>당부의 말은 달리2 시작 페이지에서도 계속됩니다. 캡처는 못했지만, 시작 전 주의사항이 몇가지 있습니다. 생성한 이미지는 개인적으로 사용할 수 있지만 상업적으로 사용할 수 없다는 것 (NFT로 사용할 수 없음!), 그리고 다시 한번 책임감있게 사용하라는 것을 강조합니다.</p>
<ul>
<li>7월 21일부로 공식적으로 베타 테스트를 오픈하며 상업적 이용도 가능해졌습니다!</li>
</ul>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/ced58035-93de-4813-86da-ee7002168eb3/image.png" alt=""></p>
<p>이것이 바로 첫 페이지입니다. 아래에는 여러 예시 이미지들이 있습니다. 그 중 귀엽게 생긴 괴물 이미지에 커서를 두니, 어떤 텍스트를 입력했을 때 생성된 이미지인지 알 수 있습니다. &quot;보라색 방 안에 있는 흰 털 괴물 사진&quot;이었네요. 굉장히 직관적입니다.</p>
<p>이 사진을 클릭하면 동일한 텍스트로 이미지를 생성합니다. 네개의 서로 다른 이미지를 만들어주네요. 그러나 아까 봤던 이미지와는 모두 다른 것을 알 수 있습니다. 인공지능이다 보니 같은 텍스트를 입력하더라도 동일한 결과값을 얻기는 어려운 것 같습니다. 마음에 드는 이미지가 있으면 바로 저장을 해야겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/11960179-acbf-4e2d-8965-d7cc8312491a/image.png" alt=""></p>
<h1 id="2-사용-방법-예시-한계">2. 사용 방법, 예시, 한계</h1>
<p>이제 본격적으로 시험을 해보도록 하겠습니다. 핵심은 &quot;아무말이나 입력했을 때 얼마나 정확하고 예술적인 이미지를 생성하는가&quot;입니다. 첫번째로 제가 입력한 것은 &quot;oil painting of an alien sitting on a chair staring at Earth&quot;, 즉 &quot;의자에 앉아 지구를 바라보고 있는 외계인의 유화 그림&quot;입니다. 아래처럼 이미지가 생성되었습니다. 네개의 이미지가 모두 정확히 의미를 해석했지만, 구도와 색감은 제가 명시하지 않아 여러 개로 해석했네요. 외계인이 어떻게 생겼다는 것 또한 명시하지 않았는데 생김새가 모두 비슷하다는 점이 흥미롭습니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/78de150b-ed06-4fba-8d6c-bda08a79d575/image.png" alt=""></p>
<p>저는 두번째 이미지가 마음에 듭니다. 이것을 공유, 저장할 수 있는데요. 수정도 가능합니다. 마음에 안 드는 부분을 지우고 다른 텍스트를 입력하면 됩니다. 저는 지구를 지우고 은하계를 보고 있는 것으로 바꿔보겠습니다. </p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/87efdc1a-6a15-4b2e-a6f9-45b039eba8bc/image.png" alt=""></p>
<p>굉장히 만족스럽습니다!</p>
<p>다음으로는 &quot;photo of a person with a cane walking in the desert at night, stars and milky way in the sky, one tree&quot;, 즉 &quot;밤에 사막을 걷고 있는 지팡이 든 사람의 사진, 별과 은하수가 있는 하늘, 나무 하나&quot;를 입력해보겠습니다. 실제로 이 이미지는 예전에 제가 피피티를 제작하며 원했던 이미지였지만 당시 구글링으로는 딱 마음에 드는 이미지를 찾지 못했었는데요. 과연 달리가 니즈를 채워줄지 보겠습니다. </p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/062209c5-f915-4f77-b873-54337fff0ba7/image.png" alt=""></p>
<p>완전 마음에 듭니다! 제가 머리속으로 상상했던 이미지를 그대로 구현해줬습니다. 앞으로 생각해 놓은 이미지가 있는데 구글링하기 귀찮거나 존재하지 않을 때 달리를 사용할 수 있을 것 같습니다. 좀 애매하긴 하지만 저의 창작물(?)이라는 점도 뿌듯하네요.</p>
<p>유화와 사진 뿐만 아니라 어떠한 스타일로도 가능합니다. &quot;밤 바닷가의 햄버거&quot;로만 검색하면 사진 형식으로 나오지만, &quot;밤 바닷가의 햄버거, 반 고흐 스타일&quot;로 검색하면 반 고흐의 스타일을 흉내냅니다. &quot;바다 위에 있는 선인장 괴물, 3D 렌더링&quot;같이 생뚱맞은 이미지도 가능하죠. 이외에도 디지털 아트, 픽셀 아트, 일러스트레이션, 수채화 등 모두 가능합니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/39cf88e1-09cd-4425-acaa-37cb7ede11c6/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/0263fec7-9560-4e2b-878e-2d95d615490f/image.png" alt=""></p>
<p>다만, 이것저것 실험을 하다보니 한계도 발견했습니다. 첫번째로, 특정인의 사진은 제대로 생성하지 않습니다. 이건 아까 지적했던 윤리적인 문제와 결부되어 의도적으로 그렇게 만든 것 같습니다. 가령 차례대로 &quot;에베레스트 꼭대기에 있는 톰 크루즈&quot;, &quot;흰 토끼 옷을 입은 티모시 샬라메&quot;를 입력하면 결과가 나오긴 하지만 두 배우 같지는 않습니다. </p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/7db69ee1-a502-422b-b686-eecfe6a37741/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/3587c4b8-3b65-4cde-ae9a-07914c8642a5/image.png" alt=""></p>
<p>그리고 간혹 이목구비가 좀 어색한 것을 볼 수 있습니다. &quot;빗속의 두 연인, 고해상도 사진&quot;으로 특정인을 명시하지 않아도 굉장히 기괴한 사람 얼굴이 나옵니다. 동물로 입력했을 때 정확한 이목구비가 나오는 것과는 비교되는데, 이건 의도적인 것 보다는 워낙 사람의 이목구비가 다양하기 때문인 것 같습니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/47db9e92-eeda-4766-9446-fa0bb4c53337/image.png" alt=""></p>
<p>얼굴이 제대로 묘사되지 않는 것은 대상이 여성일 때 더욱 심화됩니다. &quot;빨간 드레스를 입은 소녀 사진, 왼손에는 사전, 검은 배경&quot;으로 입력하면 여성의 얼굴 없이 상반신 이미지만 생성하는 것을 볼 수 있습니다. 이는 다른 조건은 다 동일하고 소녀만 소년으로 바꿔 &quot;빨간 드레스를 입은 소년 사진, 왼손에는 사전, 검은 배경&quot;으로 입력하면 소년의 얼굴이 나오는 것과 비교됩니다. 그리고 소년이 드레스를 입고 있다고 입력했는데도 불구하고 빨간 셔츠를 입은 것으로 생성한 것도 눈여겨 볼 점입니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/f9581632-f86f-4f88-88ff-2a0abb4c773c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/861bf555-7832-4644-9cff-45d5dee9df30/image.png" alt=""></p>
<p>실제로 달리는 성별을 명시하지 않으면 남성 이미지를 생성하는 등 편향이 심합니다. 이에 대해 OpenAI는 &quot;트레이닝 데이터에서 여성의 이미지는 성적으로 이용된 경우가 상대적으로 많았고, 이를 필터링 하며 남성의 이미지가 더 많아져 결과적으로 남성의 이미지를 더 많이 생성하게 된 것&quot;이라고 설명했습니다. 반면, 특정 직업군에서는 여성의 이미지만을 생성하기도 합니다. OpenAI는 달리의 <a href="https://github.com/openai/dalle-2-preview/blob/main/system-card.md">한계점과 위험</a>을 설명하며 성별 외에도 인종, 문화, 나이 등에서 이런 편향이 일어난다고 밝혔습니다. 빅데이터의 전형적인 한계라고 볼 수 있죠. 참고로, 제가 &quot;boy&quot;라고 입력했을 때 나온 남자 아이들은 모두 백인이었습니다. </p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/1735e2ed-bf64-433a-84be-b104b0d4277c/image.png" alt=""></p>
<p>재밌게 가지고 놀다 보니 리밋에 걸렸네요. 23.5시간 동안 50개의 요청만 넣을 수 있습니다. 이 리밋에 다다르면 13시간 이후 다시 할 수 있습니다. </p>
<h1 id="3-느낀-점">3. 느낀 점</h1>
<p>달리2를 사용해보며 느낀 점이 많습니다. 우선, 이 인공지능의 발달이 예술가의 자리 마저 위협하지 않을까 생각했지만, 문구 떠올리기도 쉽지 않다는 것. 아직 상상력이 남아있을 자리는 있는 것 같습니다. 상상력은 있지만 손재주는 없던 사람들이 예술가로 거듭날 수 있지 않을까, 그런 의미에서 예술가는 오히려 더 많아지지 않을까 하는 생각도 듭니다. 물론 필요한 이미지가 있을 때 보다 실용적으로 활용할 수도 있겠고요. 하지만 여러 문제점도 발견하게 되었습니다. 이미 존재하는 여러 이미지를 통해 학습하고 새로운 이미지로 합성, 재구성한 것이다 보니 본래 이미지에 대한 저작권 문제가 있을 수 있습니다. 스타일을 그대로 흉내낼 수 있다 보니 표절 문제가 있을 수도 있죠. 사람의 이미지일 경우 문제는 더 커집니다. 새롭게 생성한 이미지이지만 우연의 일치로 실제 사람을 닮았을 경우에는 또 어떻게 해야 할지도 해결책이 없습니다. 재밌었지만 생각해 볼 거리도 안겨주는 달리2 사용 후기였습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스포티파이 API로 음악 분석하기]]></title>
            <link>https://velog.io/@mare-solis/%EC%8A%A4%ED%8F%AC%ED%8B%B0%ED%8C%8C%EC%9D%B4-API%EB%A1%9C-%EC%9D%8C%EC%95%85-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@mare-solis/%EC%8A%A4%ED%8F%AC%ED%8B%B0%ED%8C%8C%EC%9D%B4-API%EB%A1%9C-%EC%9D%8C%EC%95%85-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 03 May 2022 07:56:16 GMT</pubDate>
            <description><![CDATA[<p>여느때처럼 미디엄을 살펴보다가 스포티파이를 이용한 [재미있는 분석] (<a href="https://medium.com/dev-genius/spotify-data-analysis-with-python-a727542beaa7)%EC%9D%84">https://medium.com/dev-genius/spotify-data-analysis-with-python-a727542beaa7)을</a> 보고 고대로 따라해보기로 했습니다.</p>
<p>📌 저의 독창성이라고는 하나도 들어가지 않았습니다.</p>
<h1 id="1-준비">1. 준비</h1>
<p>우선은 스포티파이 웹사이트에서 가입을 하고 [Spotify for Developers] (<a href="https://developer.spotify.com/dashboard/login)%EC%97%90%EC%84%9C">https://developer.spotify.com/dashboard/login)에서</a> 로그인을 해줍니다. 그리고 Create an app 버튼을 클릭하면 굉장히 간단한 과정을 통해 클라이언트 아이디와 비밀번호를 발급받을 수 있습니다.</p>
<p>그럼 api 패키지를 설치해주겠습니다. </p>
<pre><code class="language-python">!pip install spotipy</code></pre>
<p>그리고 발급받은 아이디와 비밀번호를 이용해 접속해줍니다.</p>
<pre><code class="language-python">import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
client_credentials_manager = SpotifyClientCredentials(client_id=&#39;발급받은 아이디&#39;, client_secret=&#39;발급받은 비번&#39;)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)</code></pre>
<br>

<h1 id="2-데이터-가져오기">2. 데이터 가져오기</h1>
<h2 id="21-트랙-데이터">2.1. 트랙 데이터</h2>
<p>먼저 트랙 데이터부터 가져와 보겠습니다. [search] (<a href="https://developer.spotify.com/documentation/web-api/reference/#/operations/search">https://developer.spotify.com/documentation/web-api/reference/#/operations/search</a>) 함수를 사용해 2021년 트랙만 검색합니다. 트랙은 어차피 한번에 50개밖에 서치가 안되므로 limit으로 50개로 확실히 한정해주고, 중첩 루프를 사용해 0-49, 50-99, ... , 950-999씩 가져와 저장하도록 합니다. 트랙의 아티스트, 제목, 아이디, 인기 등의 정보를 각각의 리스트에 저장합니다.</p>
<pre><code class="language-python">artist_name =[]
track_name = []
track_popularity =[]
artist_id =[]
track_id =[]
for i in range(0,1000,50):
    track_results = sp.search(q=&#39;year:2021&#39;, type=&#39;track&#39;, limit=50, offset=i)
    for i, t in enumerate(track_results[&#39;tracks&#39;][&#39;items&#39;]):
        artist_name.append(t[&#39;artists&#39;][0][&#39;name&#39;])
        artist_id.append(t[&#39;artists&#39;][0][&#39;id&#39;])
        track_name.append(t[&#39;name&#39;])
        track_id.append(t[&#39;id&#39;])
        track_popularity.append(t[&#39;popularity&#39;])</code></pre>
<p>이렇게 만들어진 리스트를 데이터프레임으로 변환하겠습니다.</p>
<pre><code class="language-python">import pandas as pd
track_df = pd.DataFrame({&#39;artist_name&#39; : artist_name, &#39;track_name&#39; : track_name, &#39;track_id&#39; : track_id, &#39;track_popularity&#39; : track_popularity, &#39;artist_id&#39; : artist_id})
print(track_df.shape)
track_df.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/1d7f105c-703d-424a-8ee9-34c183a6aed2/image.png" alt=""></p>
<br>

<h2 id="22-아티스트-데이터">2.2. 아티스트 데이터</h2>
<p>앞서 가져온 트랙 데이터에는 아티스트의 이름과 아이디까지만 나와있는데요. 이제 아티스트 데이터를 받아와 각 아티스트 아이디에 추가 정보를 삽입해보겠습니다. 스포티파이의 [artist] (<a href="https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-artist">https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-artist</a>) 함수는 아티스트의 url, 팔로워수, 장르, 이미지, 이름, 타입, 인기 등의 정보를 받을 수 있습니다. 그중에서 인기, 장르, 팔로워수만 저장하겠습니다.</p>
<pre><code class="language-python">artist_popularity = []
artist_genres = []
artist_followers =[]
for a_id in track_df.artist_id:
    artist = sp.artist(a_id)
    artist_popularity.append(artist[&#39;popularity&#39;])
    artist_genres.append(artist[&#39;genres&#39;])
    artist_followers.append(artist[&#39;followers&#39;][&#39;total&#39;])</code></pre>
<p>이제 이 정보를 아까 만들었던 데이터프레임에 추가해줍니다. </p>
<pre><code class="language-python">track_df = track_df.assign(artist_popularity=artist_popularity, artist_genres=artist_genres, artist_followers=artist_followers)
track_df.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/9a2cc6e4-1098-4b08-91e9-36c6ae837690/image.png" alt=""></p>
<p>📌 이쯤되었다면 한 5분 정도 쉬어줍니다. 데이터를 한꺼번에 많이 받지 못하게 제한이 되어 있어서 아마 바로 밑의 코드를 실행하면 오류가 뜰 수 있습니다. 
<img src="https://velog.velcdn.com/images/mare-solis/post/3d7ce32a-cba0-4584-bede-4b88ecd3657a/image.png" alt=""></p>
<br>

<h2 id="23-오디오-데이터">2.3. 오디오 데이터</h2>
<p>스포티파이는 트랙에 대해 17개의 [Audio features] (<a href="https://developer.spotify.com/documentation/web-api/reference/#/operations/get-several-audio-features)%EB%A5%BC">https://developer.spotify.com/documentation/web-api/reference/#/operations/get-several-audio-features)를</a> 제공합니다. 특히 tempo, danceability, acousticness와 같이 음악의 특징을 정량적인 지표로 구분해놓고 있으므로, 이를 분석에 유용하게 사용할 수 있습니다.</p>
<pre><code class="language-python">track_features = []
for t_id in track_df[&#39;track_id&#39;]:
    af = sp.audio_features(t_id)
    track_features.append(af)
tf_df = pd.DataFrame(columns = [&#39;danceability&#39;, &#39;energy&#39;, &#39;key&#39;, &#39;loudness&#39;, &#39;mode&#39;, &#39;speechiness&#39;, &#39;acousticness&#39;, &#39;instrumentalness&#39;, &#39;liveness&#39;, &#39;valence&#39;, &#39;tempo&#39;, &#39;type&#39;, &#39;id&#39;, &#39;url&#39;, &#39;track_href&#39;, &#39;analysis_url&#39;, &#39;duration_ms&#39;, &#39;time_signature&#39;])
for item in track_features:
    for feat in item:
        tf_df = tf_df.append(feat, ignore_index=True)
tf_df.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/fbdab5da-1625-43dd-b267-232b71a631d8/image.png" alt=""></p>
<br>

<h1 id="3-전처리">3. 전처리</h1>
<p>최종적으로 만들어진 데이터프레임에서 url과 같은 필요없는 열은 제거해주겠습니다.</p>
<pre><code class="language-python">cols_to_drop2 = [&#39;key&#39;,&#39;mode&#39;,&#39;type&#39;, &#39;url&#39;,&#39;track_href&#39;,&#39;analysis_url&#39;]
tf_df = tf_df.drop(columns=cols_to_drop2)
print(track_df.info())
print(tf_df.info())</code></pre>
<p>다음에는 데이터프레임의 info를 보고 데이터 타입을 바꿔주겠습니다. </p>
<pre><code class="language-python">track_df[&#39;artist_name&#39;] = track_df[&#39;artist_name&#39;].astype(&quot;string&quot;)
track_df[&#39;track_name&#39;] = track_df[&#39;track_name&#39;].astype(&quot;string&quot;)
track_df[&#39;track_id&#39;] = track_df[&#39;track_id&#39;].astype(&quot;string&quot;)
track_df[&#39;artist_id&#39;] = track_df[&#39;artist_id&#39;].astype(&quot;string&quot;)
tf_df[&#39;duration_ms&#39;] = pd.to_numeric(tf_df[&#39;duration_ms&#39;])
tf_df[&#39;instrumentalness&#39;] = pd.to_numeric(tf_df[&#39;instrumentalness&#39;])
tf_df[&#39;time_signature&#39;] = tf_df[&#39;time_signature&#39;].astype(&quot;category&quot;)
print(track_df.info())
print(tf_df.info())</code></pre>
<br>

<h1 id="4-간단한-분석">4. 간단한 분석</h1>
<h2 id="41-가장-인기있는-2021년-트랙-top-20">4.1. 가장 인기있는 2021년 트랙 Top 20</h2>
<p>가장 간단하게 2021년 발매된 트랙 중 가장 인기있는 트랙이 무엇이었는지 보도록 하겠습니다. 트랙을 popularity를 기준으로 내림차순으로 정렬해줍니다. </p>
<pre><code class="language-python">track_df.sort_values(by=[&#39;track_popularity&#39;], ascending=False)[[&#39;track_name&#39;, &#39;artist_name&#39;]].head(20)</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/8c92032b-e877-48ed-81da-7c536b4e8602/image.png" alt=""></p>
<p>가장 인기있는 트랙은 abcdefu네요. 인스타그램과 틱톡 등 SNS에서 인기를 끈 것으로 알고 있습니다. 그런데 The Kid LAROI와 저스틴 비버의 Stay가 중복되어 나온 걸 볼 수 있습니다. 싱글로 발매되었다가 앨범에 수록되어 두개의 트랙이 있는 게 아닐까 싶네요. 그런데도 두 트랙 모두 20위 안에 들었다는 건...</p>
<p>📌 참고로, 아웃풋은 제 거나 미디엄 글의 결과와 다르게 나올 수 있습니다. 인기, 팔로워수 등은 데이터를 가져오는 현재 시점의 수치이기 때문입니다.</p>
<br>

<h2 id="42-가장-팔로워가-많은-아티스트-top-20">4.2. 가장 팔로워가 많은 아티스트 Top 20</h2>
<p>이번에는 가장 팔로워가 많은 아티스트 20위를 보도록 하겠습니다. 마찬가지로 아티스트 팔로워수를 기준으로 내림차순으로 정렬해줍니다. 이때 데이터프레임은 아티스트 관련 열만 남겨 새로 생성해주겠습니다. 중복된 아티스트는 하나만 남깁니다.</p>
<pre><code class="language-python">by_art_fol = pd.DataFrame(track_df.sort_values(by=[&#39;artist_followers&#39;], ascending=False)[[&#39;artist_followers&#39;,&#39;artist_popularity&#39;, &#39;artist_name&#39;,&#39;artist_genres&#39;]])
by_art_fol.astype(str).drop_duplicates().head(20)</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/37f0c8ce-622c-4629-94d7-87a8e5fa248f/image.png" alt=""></p>
<p>에드 시런이 9천만의 팔로워를 보유하며 가장 팔로워가 많은 것으로 나타났고, 그 뒤를 드레이크, 빌리 아일리시, 저스틴 비버가 따릅니다. BTS도 7위에 올랐네요.</p>
<br>

<h2 id="43-장르별-관계된-아티스트-수">4.3. 장르별 관계된 아티스트 수</h2>
<p>아티스트 팔로워수를 보니 artist_genres도 눈에 띕니다. 스포티파이는 트랙별로 장르를 구분하지 않고 아티스트의 장르를 구분하는데요. 한 아티스트 당 여러개의 장르가 있는데 어떤 장르에 관련된 아티스트가 많은지 숫자를 확인해보겠습니다. </p>
<pre><code class="language-python">def to_1D(series):
    return pd.Series([x for _list in series for x in _list])
to_1D(track_df[&#39;artist_genres&#39;]).value_counts().head(20)</code></pre>
<pre><code>progressive house       198
trance                  173
pop                     154
uplifting trance        139
edm                     133
progressive trance      133
pop dance               119
rap                     103
dance pop                61
hip hop                  60
contemporary country     54
trap                     53
rock                     47
mellow gold              42
art rock                 42
folk rock                41
roots rock               39
new wave pop             38
power pop                38
pub rock                 38
dtype: int64</code></pre><p>이것을 그래프로 나타내 보겠습니다.</p>
<pre><code class="language-python">import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize = (14,4))
ax.bar(to_1D(track_df[&#39;artist_genres&#39;]).value_counts().index[:10],
        to_1D(track_df[&#39;artist_genres&#39;]).value_counts().values[:10])
ax.set_ylabel(&quot;Frequency&quot;, size = 12)
ax.set_title(&quot;Top genres&quot;, size = 14)</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/6dedd526-2e79-4f77-86e6-3854c7ca7efe/image.png" alt=""></p>
<br>

<h2 id="44-각-top-10-장르에서-팔로워가-가장-많은-아티스트">4.4. 각 Top 10 장르에서 팔로워가 가장 많은 아티스트</h2>
<p>이번에는 위에서 나온 Top 10 장르 중, 각 장르에서 팔로워가 가장 많은 아티스트를 추출해보겠습니다. </p>
<pre><code class="language-python">top_10_genres = list(to_1D(track_df[&#39;artist_genres&#39;]).value_counts().index[:10])
top_artists_by_genre = []
for genre in top_10_genres:
    for index, row in by_art_fol.iterrows():
        if genre in row[&#39;artist_genres&#39;]:
            top_artists_by_genre.append({&#39;artist_name&#39;:row[&#39;artist_name&#39;], &#39;artist_genre&#39;:genre})
            break
pd.json_normalize(top_artists_by_genre)</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/0a944473-bb5d-47e4-b2a9-865d0d98362c/image.png" alt=""></p>
<br>

<h2 id="45-각-top-10-장르에서-가장-인기있는-트랙">4.5. 각 Top 10 장르에서 가장 인기있는 트랙</h2>
<p>아티스트를 확인했다면 트랙도 확인해봐야겠죠.</p>
<pre><code class="language-python">by_track_pop = pd.DataFrame(track_df.sort_values(by=[&#39;track_popularity&#39;], ascending=False)[[&#39;track_popularity&#39;,&#39;track_name&#39;, &#39;artist_name&#39;,&#39;artist_genres&#39;, &#39;track_id&#39;]])
by_track_pop.astype(str).drop_duplicates().head(10)
top_songs_by_genre = []
for genre in top_10_genres:
    for index, row in by_track_pop.iterrows():
        if genre in row[&#39;artist_genres&#39;]:
            top_songs_by_genre.append({&#39;track_name&#39;:row[&#39;track_name&#39;], &#39;track_popularity&#39;:row[&#39;track_popularity&#39;],&#39;artist_name&#39;:row[&#39;artist_name&#39;], &#39;artist_genre&#39;:genre})
            break
pd.json_normalize(top_songs_by_genre)</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/90185a66-3203-4bfe-9764-5cde0fb93468/image.png" alt=""></p>
<p>해당 장르에서 아티스트 팔로워도 가장 많으면서 가장 인기있는 트랙도 발매했던 사람은 힙합의 드레이크 뿐이네요. 많은 팔로워가 있으면서도 당해 가장 인기있는 트랙을 내기는 쉽지 않은가 봅니다.
<img src="https://velog.velcdn.com/images/mare-solis/post/96a927bc-860f-4ab1-8d63-b7f07ada05d0/image.gif" alt=""></p>
<br>

<h1 id="5-음악-분석">5. 음악 분석</h1>
<h2 id="51-특징-간-상관관계">5.1. 특징 간 상관관계</h2>
<p>이제는 좀 더 본격적으로 음악의 특성을 가지고 분석해보도록 하겠습니다. 우선 각각의 특징 간에는 어떤 상관관계가 있을까요? 히트맵으로 보도록 하겠습니다.</p>
<pre><code class="language-python">import seaborn as sn
sn.set(rc = {&#39;figure.figsize&#39;:(12,10)})
sn.heatmap(tf_df.corr(), annot=True)
plt.show()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/e1c0cefd-cc7c-40e6-88b1-3c906636a18b/image.png" alt=""></p>
<p>예상할 수 있듯이 loundness와 energy와 같이 상관관계가 높은 특징들이 있고, acousticness와 energy처럼 상관관계가 낮은 특징들도 있습니다. 이중 가장 높은 상관관계를 가진 loudness와 energy를 좀 더 살펴보겠습니다.</p>
<pre><code class="language-python">sn.set(rc = {&#39;figure.figsize&#39;:(20,20)})
sn.jointplot(data=tf_df, x=&quot;loudness&quot;, y=&quot;energy&quot;, kind=&quot;kde&quot;)</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/2fc6364c-07a0-43b9-9b76-b9701c356d0a/image.png" alt=""></p>
<br>

<h2 id="52-top-100-트랙-vs-전체-평균">5.2. Top 100 트랙 vs. 전체 평균</h2>
<p>이번에는 Top 100에 든 트랙은 과연 다른 음악들과 뭐가 달랐을지 알아보도록 하겠습니다. </p>
<p>&#39;danceability&#39;, &#39;energy&#39;, &#39;speechiness&#39;, &#39;acousticness&#39;, &#39;instrumentalness&#39;, &#39;liveness&#39;, &#39;valence&#39;의 특징을 기준으로, Top 100 트랙의 평균과 전체 평균을 스타맵을 그려 비교해보겠습니다.</p>
<pre><code class="language-python">feat_cols = [&#39;danceability&#39;, &#39;energy&#39;, &#39;speechiness&#39;, &#39;acousticness&#39;, &#39;instrumentalness&#39;, &#39;liveness&#39;, &#39;valence&#39;]
top_100_feat = pd.DataFrame(columns=feat_cols)
for i, track in by_track_pop[:100].iterrows():
    features = tf_df[tf_df[&#39;id&#39;] == track[&#39;track_id&#39;]]
    top_100_feat = top_100_feat.append(features, ignore_index=True)
top_100_feat = top_100_feat[feat_cols]

from sklearn import preprocessing
mean_vals = pd.DataFrame(columns=feat_cols)
mean_vals = mean_vals.append(top_100_feat.mean(), ignore_index=True)
mean_vals = mean_vals.append(tf_df[feat_cols].mean(), ignore_index=True)
print(mean_vals)

# 그래프 그리기

import plotly.graph_objects as go
import plotly.offline as pyo
fig = go.Figure(
    data=[
        go.Scatterpolar(r=mean_vals.iloc[0], theta=feat_cols, fill=&#39;toself&#39;, name=&#39;Top 100&#39;),
        go.Scatterpolar(r=mean_vals.iloc[1], theta=feat_cols, fill=&#39;toself&#39;, name=&#39;All&#39;),
    ],
    layout=go.Layout(
        title=go.layout.Title(text=&#39;Feature comparison&#39;),
        polar={&#39;radialaxis&#39;: {&#39;visible&#39;: True}},
        showlegend=True
    )
)

#pyo.plot(fig)
fig.show()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/ad649bb6-953f-4c33-93ec-6b3c89ac86ec/image.png" alt=""></p>
<p>이런 깔끔한 결과가 얻어집니다. Top 100은 전체 평균에 비해 danceability와 valence, acousticness가 높지만 energy, liveness, 특히 instrumentalness는 낮은 것을 볼 수 있네요. </p>
<br>

<h2 id="53-추천-받기">5.3. 추천 받기</h2>
<p>마지막으로 스포티파이 api는 추천 목록도 제공합니다. [recommendations] (<a href="https://developer.spotify.com/documentation/web-api/reference/#/operations/get-recommendations">https://developer.spotify.com/documentation/web-api/reference/#/operations/get-recommendations</a>) 함수를 이용해 아티스트와 장르, 트랙, 음악 특징 등을 입력하면 그와 비슷한 음악을 추천받을 수 있습니다. </p>
<pre><code class="language-python">rec = sp.recommendations(seed_artists=[&quot;3PhoLpVuITZKcymswpck5b&quot;], seed_genres=[&quot;pop&quot;], seed_tracks=[&quot;1r9xUipOqoNwggBpENDsvJ&quot;], limit=10)
for track in rec[&#39;tracks&#39;]:
    print(track[&#39;artists&#39;][0][&#39;name&#39;], track[&#39;name&#39;])</code></pre>
<pre><code>Twenty One Pilots Stressed Out
The Cars Just What I Needed
Maroon 5 What Lovers Do (feat. SZA)
Yusuf / Cat Stevens Wild World
Imagine Dragons Demons
BoyWithUke Two Moons
Lorde Perfect Places
Supertramp Give A Little Bit
Skillet Surviving The Game
Ed Sheeran Tenerife Sea</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[빅분기] 빅데이터 분석 기사 공부기 (필기)]]></title>
            <link>https://velog.io/@mare-solis/%EB%B9%85%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EA%B8%B0%EC%82%AC-%EA%B3%B5%EB%B6%80%EA%B8%B0</link>
            <guid>https://velog.io/@mare-solis/%EB%B9%85%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D-%EA%B8%B0%EC%82%AC-%EA%B3%B5%EB%B6%80%EA%B8%B0</guid>
            <pubDate>Sat, 23 Apr 2022 15:16:52 GMT</pubDate>
            <description><![CDATA[<p>바로 어제 빅데이터 분석 기사 필기 예비 결과가 나왔습니다! 정식 결과는 29일 나오지만, 오늘 결과를 보고 이의 접수 기간을 가진다고 하네요. </p>
<h2 id="1-빅데이터-분석-기사가-뭔데">1. 빅데이터 분석 기사가 뭔데?</h2>
<p>데이터 &#39;분석&#39; 관련 자격증은 세개가 있습니다. 첫째는 제가 준비한 빅데이터 분석 기사이고, ADsP라고 불리는 데이터분석 준전문가 자격증, 그리고 ADP라고 하는 데이터분석 전문가 자격증입니다. 이 중 빅데이터 분석 기사 자격증만 국가기술 자격증이고, ADP와 ADsP는 국가공인 민간자격증입니다. 그리고 빅데이터 분석 기사와 ADsP는 응시자격이 좀 더 유연하지만, ADP는 박사 이상의 학위나 이상의 이에 준하는 경력이 있어야 합니다. 이외에도 데이터 아키텍처 전문가, 데이터 아키텍처 준전문가, SQL 전문가, SQL 개발자 자격증도 있는데 모두 국가 공인 민간자격증입니다 (<a href="https://www.dataq.or.kr/www/sub/a_07.do">https://www.dataq.or.kr/www/sub/a_07.do</a>). </p>
<table>
<thead>
<tr>
<th>자격 이름</th>
<th>부문</th>
<th>시험 종류</th>
</tr>
</thead>
<tbody><tr>
<td>빅데이터 분석 기사</td>
<td>국가기술자격</td>
<td>필기, 실기</td>
</tr>
<tr>
<td>데이터 분석 준전문가</td>
<td>국가공인 민간자격</td>
<td>필기</td>
</tr>
<tr>
<td>데이터 분석 전문가</td>
<td>국가공인 민간자격</td>
<td>필기, 실기</td>
</tr>
</tbody></table>
<br>

<h2 id="2-나는-왜-시작했나">2. 나는 왜 시작했나?</h2>
<p>저는 사실 데이터 분석을 공부하면서도 자격증의 존재조차 모르고 있었습니다. 존재를 알게된 것은 취업 준비를 하다가 본 한 채용 공고 때문인데요. 이 자격증이 있으면 우대를 해준다는 내용이 있었습니다. 최근에는 이 자격증이 있을 때 우대를 해주는 곳이 꽤나 생겼다고 합니다. </p>
<p>사실 제 개인적인 생각으로는 전공자에게나 비전공자에게나 데이터 분석 직군 취업에 있어서는 엄청나게 매력적인 자격증은 아닌 것 같다는 생각이 듭니다. (제가 봤던 채용 공고도 데이터 분석 직군은 아니었습니다.) 데이터 분석 직군은 이미 채용할 때 지원 자격을 통계, 컴퓨터, 데이터 과학 등의 전공으로 제한한 경우가 많기 때문에 비전공자는 자격증이 있더라도 어차피 지원을 못 하고, 전공자의 경우 전공이 전문 지식을 자격증 이상으로 증명해주니까요. 자격증 공부가 코딩 테스트에 도움이 되는 것도 아니고...😨</p>
<p>하지만 저는 취업을 위해서 자격증을 준비했다기 보다는 1) 시간은 많은데 할 건 없어서 이거라도 해야겠다는 마음이 컸고, 2) 그동안 데이터 분석을 한다고 하긴 했지만 기본기가 많이 부족했기 때문에 겸사겸사 공부한다는 생각으로 시작했습니다. </p>
<h2 id="3-공부-과정">3. 공부 과정</h2>
<blockquote>
<p>기간: 한달 (하루 2-3시간)
교재: 이기적</p>
</blockquote>
<p>저는 그 공고를 보고 바로 준비를 시작해서 약 한달 간 공부를 했습니다. 교재는 이기적 하나로 했고, 인강을 듣거나 스터디를 하진 않았습니다. 하지만 통계에서 이해가 안 되는 부분이 있을 때는 유튜브 선생님들의 도움을 받았습니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/3f14aaff-d72a-4abc-a795-940b2d560e9f/image.png" alt=""></p>
<p>공부를 하다 보니 정말 도움이 많이 되었습니다. 물론 시험 범위가 깊지는 않아서 최신 분석 기법까지 배운다거나 할 순 없습니다. 하지만 큰 틀에서 어떤 흐름으로 공부를 해야 하는지 알 수 있었고, 특히 제가 약했던 통계 분석의 기초를 공부할 수 있었습니다.</p>
<h2 id="4-시험-응시와-반성">4. 시험 응시와 반성</h2>
<p>제가 본 시험은 4회였는데요. 아직 체계가 제대로 갖춰지지 않았다는 얘기를 많이 듣긴 했습니다만, 시험을 쳐보니 범위조차 확실히 정해지지 않았다는 생각이 들었습니다. 문제집에서 나오지 않은 내용도 나왔고, 오히려 ADsP 문제집에 나왔던 내용이 여러개 나왔습니다.</p>
<p>이건 문제집을 여러개 풀지 않았던 제 잘못이었던 것 같습니다. 다른 문제집의 경우 기출문제 복원이 잘 되어 있는 것도 있고, 내용이 엄청 방대한 것도 있다고 하니 적어도 두개 정도는 봐야 안전할 것 같습니다. </p>
<p>어쨌든 시험을 보면서는 정말 망했다고 생각하고 봤습니다. 문제가 어렵지는 않았습니다. 하지만 제가 제대로 이해하지 않고 넘어간 것들이 그대로 되돌아오더군요🥲 당연한 얘기겠지만 공부를 착실히 했다면 쉽게 풀 수 있는 문제였던 것 같습니다.
<img src="https://velog.velcdn.com/images/mare-solis/post/75f88fc3-a63f-4902-bf79-504c76703c2e/image.JPG" alt=""></p>
<p>그런데 홈페이지 공지를 보니 이번에도 역시 문제 오류 두개가 발견되었다고 합니다. 이런 오류가 시험의 신뢰도에 큰 영향을 미치는데 말이죠. 어쨌든 저는 이 두 문제가 전체 정답 처리되며 간신히 합격할 수 있었기 때문에 불평할 처지는 아닙니다.</p>
<p>필기를 합격하고 보니, 실기를 준비하며 보완해야 할 점이 보입니다. 우선 문제집을 좀 여러개 사서 봐야겠습니다. 그리고 실기에는 좀 더 시간을 많이 투자해서 제대로 공부를 해보고 싶네요!</p>
<p>++ 후기는 작성하지 못했지만 실기도 합격했습니다! 문제집에 있는 연습 문제만 좀 열심히 풀어보고 체화하면 실기는 어렵지 않게 패스할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[네트워크 분석] 할리우드 배우들의 네트워크를 알아보자]]></title>
            <link>https://velog.io/@mare-solis/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EB%B6%84%EC%84%9D-%ED%95%A0%EB%A6%AC%EC%9A%B0%EB%93%9C-%EB%B0%B0%EC%9A%B0%EB%93%A4%EC%9D%98-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@mare-solis/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EB%B6%84%EC%84%9D-%ED%95%A0%EB%A6%AC%EC%9A%B0%EB%93%9C-%EB%B0%B0%EC%9A%B0%EB%93%A4%EC%9D%98-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Sat, 09 Apr 2022 16:09:46 GMT</pubDate>
            <description><![CDATA[<p>네트워크 분석은 빅데이터 분석의 기본 테크닉 중 하나로, 연결망을 통해 데이터의 관계를 파악하고 중심이 되는 데이터를 찾아내는 기법입니다. 가장 기본적으로 사람들 간의 네트워크를 분석할 수도 있으나, 단어, 웹사이트, 국가 등 관계를 보려고 하는 분석이라면 무궁무진하게 활용할 수 있습니다. </p>
<p>그중에서도 오늘은 imdb 영화 관련 데이터를 통해 같은 작품에 출연한 배우들의 네트워크를 만들어보고, 서로 다 연결이 되어 있는지, 누가 가장 인싸일지 보도록 하겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/1ca67cef-6805-4d98-90a9-5be73070e412/IMG_5884.GIF" alt=""></p>
<hr>
<h2 id="1-패키지-설치">1. 패키지 설치</h2>
<p>우선 필요한 패키지를 먼저 설치해주겠습니다. 기본적인 패키지는 있다고 가정하고, 새로 사용하는 패키지 두개를 설치하겠습니다.networkx는 네트워크 분석 패키지이고, pyvis는 동적 시각화 패키지입니다. </p>
<pre><code class="language-python">! pip install networkx
! pip install pyvis</code></pre>
<h2 id="2-데이터-준비">2. 데이터 준비</h2>
<h3 id="21-데이터-다운로드">2.1. 데이터 다운로드</h3>
<p>imdb에서는 데이터셋을 제공하고 있습니다. 압축파일을 다운로드 받을 수 있으며, 압축을 풀면 tsv 파일이 있습니다. imdb(<a href="https://www.imdb.com/interfaces/)%EC%97%90">https://www.imdb.com/interfaces/)에</a> 있는 설명을 보고 필요한 데이터를 다운로드 받으면 되는데, 이번 분석에서는 &quot;title.akas.tsv.gz&quot;를 제외하고는 모두 다운로드 받습니다.</p>
<p>다운로드 받은 후에는 데이터프레임으로 로드해줍니다.</p>
<pre><code class="language-python">import pandas as pd

# 인물정보

name_info = pd.read_csv(&#39;/Users/imare-solis/Downloads/name.basics.tsv&#39;, sep=&#39;\t&#39;)
name_info.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/7fddcaa7-d332-422d-aca9-50f97299eea8/image.png" alt=""></p>
<pre><code class="language-python"># 작품 별 제작진/출연진
# 출연진은 상위 10명까지만 나옴

principal = pd.read_csv(&#39;/Users/imare-solis/Downloads/title.principals.tsv&#39;, sep=&#39;\t&#39;)
principal.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/2c367790-e890-4a15-bfac-792f82ee7201/image.png" alt=""></p>
<pre><code class="language-python"># 작품 기본 정보

title_info  = pd.read_csv(&#39;/Users/imare-solis/Downloads/title.basics.tsv&#39;, sep=&#39;\t&#39;)
title_info.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/95f1cf68-4291-4f29-80f8-786534bf51f2/image.png" alt=""></p>
<pre><code class="language-python"># 별점

rating  = pd.read_csv(&#39;/Users/imare-solis/Downloads/title.ratings.tsv&#39;, sep=&#39;\t&#39;)
rating.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/0111bbc3-5074-48c8-a71f-4bea6fcfd201/image.png" alt=""></p>
<h3 id="22-데이터-병합">2.2. 데이터 병합</h3>
<p>데이터가 로드되었다면 필요한 데이터셋을 구성하기 위해 데이터를 병합합니다. 우리는 타이틀에 관한 정보와 별점, 그 타이틀에 등장한 주연 배우, 그 주연 배우에 관한 정보가 필요하므로, 네 개의 데이터셋으로 하나의 통합된 데이터셋을 만들겠습니다.</p>
<pre><code class="language-python">title_crew = principal.merge(name_info, how=&#39;inner&#39;, on=&#39;nconst&#39;)
actors = title_crew.loc[(title_crew[&#39;category&#39;] == &#39;actor&#39;) | (title_crew[&#39;category&#39;] == &#39;actress&#39;)]
actors = actors.merge(title_info, how=&#39;inner&#39;, on=&#39;tconst&#39;)
actors = actors.merge(rating, how=&#39;inner&#39;, on=&#39;tconst&#39;)
actors.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/b2742838-b649-44ec-bd7f-a2a0bef68729/image.png" alt=""></p>
<h3 id="23-데이터-확인">2.3. 데이터 확인</h3>
<p>나중에 처음부터 돌릴 때 위의 과정을 생략할 수 있도록 데이터를 csv 파일로 따로 저장해주고 csv 파일로 다시 로드해줍니다. 데이터가 커서 저장하고 로드하는데 시간이 좀 걸리네요.</p>
<pre><code class="language-python">actors.to_csv(&#39;actors.csv&#39;)
actors = pd.read_csv(&#39;actors.csv&#39;)
actors.info()</code></pre>
<p>데이터 정보를 보니 몇가지 변환 사항이 보입니다. 필요없는 칼럼을 삭제하고, 데이터 타입을 변환해줍니다.</p>
<pre><code class="language-python">import numpy as np

actors = actors.drop(columns=&#39;Unnamed: 0&#39;)
actors[&#39;startYear_y&#39;] = actors[&#39;startYear_y&#39;].replace(&#39;\\N&#39;, np.nan)
actors[&#39;startYear_y&#39;] = actors[&#39;startYear_y&#39;].astype(float)
actors.info()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/aa224c52-9f53-4bd9-9ae4-d4740127b148/image.png" alt=""></p>
<h3 id="24-데이터-전처리">2.4. 데이터 전처리</h3>
<p>네트워크 분석에 맞도록 데이터를 선정해야 합니다. 먼저 현재의 데이터는 너무 크니까 2021년 데이터만 사용하도록 하겠습니다. 콘텐츠의 형태는 영화와 tv 시리즈로만으로 제한하고, 별점 평가 수가 2000건이 넘는 콘텐츠만 보겠습니다.</p>
<pre><code class="language-python">
actors_2021 = actors.loc[(actors[&#39;startYear_y&#39;] == 2021) 
                         &amp; ((actors[&#39;titleType_y&#39;] == &#39;movie&#39;) 
                         | (actors[&#39;titleType_y&#39;] == &#39;tvSeries&#39;))
                         &amp; (actors[&#39;numVotes&#39;] &gt; 2000)].dropna()</code></pre>
<p>이 과정이 끝나면 배우 이름을 제외하고 다른 데이터는 필요가 없으므로, 타이틀 아이디(tconst)와 배우 이름(primaryName)만 있는 데이터프레임을 사용하겠습니다. 그래도 데이터가 너무 많으므로 2021년에 출연작이 하나인 배우는 삭제하겠습니다.</p>
<pre><code class="language-python">actors_2021 = actors_2021.loc[:, actors_2021.columns.intersection([&#39;tconst&#39;,&#39;primaryName&#39;])]
actors_2021[&#39;primaryName&#39;] = actors_2021[&#39;primaryName&#39;].str.replace(&#39;,&#39;, &#39;&#39;)
actors_2021[&#39;counts&#39;] = actors_2021.groupby([&#39;primaryName&#39;]).transform(&#39;count&#39;)</code></pre>
<h2 id="3-네트워크-분석">3. 네트워크 분석</h2>
<h3 id="31-네트워크-분석-데이터셋">3.1. 네트워크 분석 데이터셋</h3>
<p>다음에는 네트워크 분석을 위해 데이터 형태를 변행해줘야 합니다. 현재는 한 타이틀에 여러 출연자가 있을 경우 여러 개의 레코드가 만들어져 있습니다. 이것을 groupby로 타이틀 하나 당 출연진의 리스트가 만들어지도록 하겠습니다. 그러면 중복된 타이틀이 없겠죠!</p>
<pre><code class="language-python">actors_2021_join = actors_2021.groupby([&#39;tconst&#39;])[&#39;primaryName&#39;].apply(list).reset_index()
actors_2021_join</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/b854318b-61f1-4e06-af67-005242c7b6e4/image.png" alt=""></p>
<p>다음에는 네트워크 분석에 사용될 수 있도록 변형해줘야 합니다. 네트워크 분석에 사용되는 데이터프레임에는 &#39;source&#39;, &#39;target&#39;, &#39;weight&#39;가 있어야 합니다. &#39;source&#39;가 되는 배우, &#39;target&#39;이 되는 배우, 그리고 그 조합이 얼마나 발생했는지에 따른 &#39;weight&#39;으로 구성됩니다. 원래 &#39;source&#39;와 &#39;target&#39;에는 방향성의 의미가 있지만 이번과 같은 분석에서는 방향성이 필요하지 않습니다. &#39;source&#39;와 &#39;target&#39;은 하나씩밖에 지정되지 않으므로, 저희는 같은 작품에 출연한 배우들에서 2인으로 구성된 모든 조합을 구해야 합니다. </p>
<pre><code class="language-python">from itertools import combinations

actors_2021_join[&#39;primaryName&#39;] = actors_2021_join[&#39;primaryName&#39;].apply(lambda l: list(combinations(l, 2)))
actors_2021_join = actors_2021_join.explode(&#39;primaryName&#39;).dropna()
actors_2021_join.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/15889620-a56c-481c-86a1-ab8ecc86bf16/image.png" alt=""></p>
<pre><code class="language-python">nt = pd.DataFrame(actors_2021_join[&#39;primaryName&#39;].to_list(), columns=[&#39;source&#39;,&#39;target&#39;])
nt</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/dd09148e-4be3-4071-977b-117251cfd132/image.png" alt=""></p>
<h3 id="32-네트워크-분석-실행">3.2. 네트워크 분석 실행</h3>
<p>데이터 준비가 모두 끝났으면 네트워크 분석을 실행해보겠습니다. 위에서 만든 데이터셋을 networkx에서 그래프로 바꿔줍니다.</p>
<pre><code class="language-python">import networkx as nx

nt[&#39;weight&#39;] = nt.groupby([&#39;source&#39;, &#39;target&#39;])[&#39;source&#39;].transform(&#39;size&#39;)
nt = nt.dropna()

G = nx.from_pandas_edgelist(nt, &#39;source&#39;, &#39;target&#39;,
                            create_using=nx.DiGraph(), edge_attr=&#39;weight&#39;)

nt</code></pre>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/0b4001ba-c4b9-4250-9d31-f1e6860fc130/image.png" alt=""></p>
<p>이제 최종! 네트워크 시각화를 해주고 파일로 저장합니다. 시각화 결과는 주피터 노트북 상에도 나오고 파일로도 저장됩니다. </p>
<pre><code class="language-python">from pyvis.network import Network

net = Network(notebook=True)
net.from_nx(G)
net.show_buttons(filter_=[&#39;nodes&#39;])
net.show(&#39;example3.html&#39;)</code></pre>
<h2 id="4-결과-해석">4. 결과 해석</h2>
<p>마치 밤하늘 같은 아름다운 모양이 나왔습니다 🤣 </p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/5e7b19ff-e1a1-4a39-87d7-6a96d956be72/image.png" alt=""></p>
<p>좀 더 자세히 들여다 보자면, 지엽적으로 별처럼 떠있는 모양들은 주로 같은 TV 드라마에 출연한 배우들입니다. </p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/b22fb11e-6f39-46c4-8a80-fa96a4cf8ba1/image.png" alt=""></p>
<p>또 국가 별로 네트워크가 형성되는 것도 볼 수 있습니다. 아래는 한국 배우들의 네트워크네요. 따로 분리가 되어있는 것으로 보아, 2021년에 한국 작품을 했으면서 해외 배우와 같은 작품을 한 한국 배우는 없나 봅니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/047be8f0-3773-4e75-8e06-b082fe0c4be1/image.png" alt=""></p>
<p>가장 중앙을 보면, 할리우드의 거대한 네트워크를 확인할 수 있습니다. 할리우드 배우들은 다른 영화 배우들과 활발히 연결되는 한편, 몇몇 인물을 중심으로 TV 배우들과도 연결이 되어 있는 것을 볼 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/c7a343ff-f0b3-4a1f-a2bd-38595a06b10c/image.png" alt=""></p>
<p>관계망의 중심이 되는 영향력 있는 인물들을 파악해보도록 하겠습니다. 다작을 하는 조연배우들의 활약이 두드러지네요. </p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/63296d6b-6cc2-4db7-a26c-c2d44ff5a830/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/dac49616-9bb0-40a5-a80b-cacf6be9f7ba/image.png" alt=""></p>
<p>주연 배우들 중에서는 &lt;듄&gt;, &lt;아담스 패일리&gt; 등에 출연한 오스카 아이작, &lt;이터널스&gt;, &lt;킬러의 보디가드&gt;에 출연한 샐마 헤이약, &lt;프리 가이&gt;, &lt;킬러의 보디가드&gt;, &lt;레드 노티스&gt;에 출연한 라이언 레이놀즈가 네트워크 형성에 중요한 역할을 하고 있습니다. </p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/a8f70b11-9ab8-4790-8f91-93b90dd72901/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/eee9aa0b-7028-423a-b5bb-8dfb6c3301a9/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/122db362-e603-4ae1-ab42-ae9e4105c359/image.png" alt=""></p>
<p>오늘 분석은 여기까지입니다. 특정 노드들의 색깔을 다르게 지정할 수 있으면 훨씬 이해하기 쉬운 시각화가 될 것 같은데 방법을 알 수 있으면 좋겠네요 😅 참고로 아래 시각화는 데이터 필터링을 거의 하지 않고 한번 해본 건데요. 데이터가 크면 클수록 오히려 더 직관적으로 이해하기 쉬울 수도 있다는 점 참고할 수 있을 것 같습니다. 
<img src="https://velog.velcdn.com/images/mare-solis/post/776964b9-9c33-4284-a9e3-cc57440860b3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[트위터 스크래핑 라이브러리 twint 사용법]]></title>
            <link>https://velog.io/@mare-solis/%ED%8A%B8%EC%9C%84%ED%84%B0-%EC%8A%A4%ED%81%AC%EB%9E%98%ED%95%91-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-twint-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@mare-solis/%ED%8A%B8%EC%9C%84%ED%84%B0-%EC%8A%A4%ED%81%AC%EB%9E%98%ED%95%91-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-twint-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Thu, 31 Mar 2022 11:41:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/mare-solis/post/abdce6cd-902a-4c49-a7a6-a2fcb46295ac/image.png" alt="">트위터를 스크래핑 하는 다양한 방법 중 가장 적법한 방법은 트위터 API를 사용하는 것입니다. 하지만 트위터 API에는 여러 한계가 존재합니다. </p>
<p>첫번째는 기간입니다. 트위터 API에서는 최근 7일 간의 데이터 밖에 스크래핑하지 못합니다. 두번째는 rate limit입니다. 15분마다 18000개의 트윗을 받도록 제한하고 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/mare-solis/post/a7575dd8-6cf8-4f48-b371-90b438b4a7ce/image.gif" alt=""></p>
<p>따라서 트위터를 제한 없이 스크래핑 하기 위해 다양한 라이브러리가 등장했습니다. 대표적으로 twint, getOldtweets3, snscrape 등이 있죠. 따라서 트위터는 이런 라이브러리의 활용을 막기 위해 코드를 계속 변경하고, 라이브러리는 또 버그를 수정하는 적대적 관계가 형성되었습니다. </p>
<p>하지만 getOldtweets3은 2020년 9월 이후로 제대로 작동하지 않고, snscrape도 최근 발생한 이슈가 해결되지 않고 있습니다. 따라서 selenium으로 직접 스크래퍼를 만들지 않는 이상, 현재로서는 twint가 유일한 선택지입니다. </p>
<p>물론 twint 역시 완벽하다고 할 수 없으며 불안정한 상태이므로, 이 점은 유의하고 진행해야 합니다.</p>
<hr>
<h1 id="1-twint-설치">1. twint 설치</h1>
<p>우선 설치부터 하겠습니다. 트위터 업데이트로 인해 트윈트 기존 버전은 오류가 발생합니다. 아래 누군가가 깃허브에 올려놓은 트윈트로 설치해주세요. 혹시 이전에 twint를 설치한 적이 있다면, 꼭 삭제 후 새로 설치해야 합니다.</p>
<pre><code class="language-python">!pip install git+https://github.com/woluxwolu/twint.git
import twint</code></pre>
<h1 id="2-데이터-수집">2. 데이터 수집</h1>
<h2 id="21-쿼리-서치">2.1. 쿼리 서치</h2>
<p>첫번째로는, 쿼리를 통해 검색되는 트윗을 모두 수집하는 코드를 실행해보겠습니다. 서치 쿼리 외에도 언어, 날짜 등 여러 조건을 추가할 수 있으니, 공식 문서를 참고해주세요 (<a href="https://github.com/twintproject/twint">https://github.com/twintproject/twint</a>).     <code>config.Limit = 100</code>처럼 리밋을 걸어주면 날짜 순으로 100개만 수집되고, 리밋이 없으면 해당하는 모든 트윗이 수집됩니다. &#39;squid game&#39;이라는 검색어와 날짜를 설정하여 트윗을 수집해보겠습니다.</p>
<pre><code class="language-python"># Configure
config = twint.Config()
config.Search = &#39;squid game&#39;
config.Lang = &quot;en&quot;
config.Since = &#39;2021-09-17&#39;
config.Until = &#39;2021-11-26&#39;
config.Store_json = True
config.Output = &quot;squid game.json&quot;

# Run
twint.run.Search(config)</code></pre>
<h2 id="22-특정-유저-트윗">2.2. 특정 유저 트윗</h2>
<p>또는 특정 유저의 트윗을 수집하는 것도 가능합니다. 도널드 트럼프의 계정의 모든 트윗을 수집하는 코드는 아래와 같습니다.</p>
<pre><code class="language-python">import twint

# Configure
c = twint.Config()
c.Username = &quot;realDonaldTrump&quot;
config.Store_json = True
config.Output = &quot;Trump.json&quot;

# Run
twint.run.Search(c)</code></pre>
<p>만약 트럼프의 트윗 중 &#39;great&#39;가 들어간 트윗만 수집하고 싶다면 <code>c.Search = &quot;great&quot;</code>를 추가해주면 됩니다. 쿼리 검색과 마찬가지로 언어, 날짜 등의 조건을 추가할 수 있습니다.</p>
<h2 id="23-그-외">2.3. 그 외</h2>
<p>그 외에도 특정 유저의 팔로워 목록, 팔로잉 목록을 가져오는 것도 가능합니다.</p>
<pre><code class="language-python"># Get follwer list
twint -u username --followers

# Get follwoing list
twint -u username --following</code></pre>
<p>팔로잉 하는 계정 또는 팔로워의 계정에 대한 정보를 더 알고 싶다면 뒤에 <code>--user-full</code>을 추가합니다.</p>
<pre><code class="language-python">twint -u username --followers --user-full
twint -u username --following --user-full</code></pre>
<h1 id="3-한계">3. 한계</h1>
<p>이상 twint를 활용해서 트위터를 스크래핑 해봤습니다. </p>
<p>저는 &#39;squid game&#39; 코드를 실행했을 때 2021-11-26부터 2021-11-15까지만 수집되고 끊겼습니다. 그래서 2021-11-14부터 다시 실행했는데요. 이처럼 간혹 수집이 안정적이지 않을 때는 프로그램을 종료하고 기다린 후 재실행하면 다시 작동할 수 있습니다. 그리고 수집된 데이터에도 결함이 있는지 잘 확인하는 것도 중요하겠습니다.</p>
<p>하지만 이마저도 트위터에서 언제 막을지 모르기 때문에 (🥲) 필요한 데이터가 있다면 트위터 API를 활용해 주기적으로 아카이빙 해놓는 것을 추천드립니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[넷플릭스 데이터를 분석하자]]></title>
            <link>https://velog.io/@mare-solis/%EB%84%B7%ED%94%8C%EB%A6%AD%EC%8A%A4-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EB%B6%84%EC%84%9D%ED%95%98%EC%9E%90</link>
            <guid>https://velog.io/@mare-solis/%EB%84%B7%ED%94%8C%EB%A6%AD%EC%8A%A4-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EB%B6%84%EC%84%9D%ED%95%98%EC%9E%90</guid>
            <pubDate>Mon, 07 Feb 2022 20:45:03 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/mare-solis/post/3d5db219-c4a5-4c2e-9659-4104829fa078/img.png" alt=""></p>
<p>지난번에 넷플릭스에서 어떤 데이터를 수집하고 제공하는지 알아봤었는데요, 저에 대해 많은 데이터를 수집한다는 것에 흠칫한 한편, 그걸 제가 다운로드 받을 수 있게끔 한 점은 흡족했습니다. 그럼 넷플릭스에서 줬으니까 제 데이터를 한번 잘 써보겠습니다!</p>
<p><img src="https://images.velog.io/images/mare-solis/post/f6d0b34d-e92c-4fa5-b5cd-04658e00e473/image.png" alt=""></p>
<hr>
<h2 id="1-데이터-가공">1. 데이터 가공</h2>
<p>먼저 데이터를 로드해줍니다. csv 파일을 데이터프레임으로 변환하겠습니다.</p>
<pre><code class="language-python">import pandas as pd

df = pd.read_csv(&#39;ViewingActivity.csv&#39;)
df.head()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/c03c75e0-b5f4-4c47-9e61-7fe2aa67603b/image.png" alt=""></p>
<br>

<p>기본적으로 해줄 건 해줘야겠죠? 문자열로 되어 있는 <code>Start Time</code>을 datetime 형식으로 바꿔줍니다.</p>
<pre><code class="language-python">df[&#39;Start Time&#39;] = pd.to_datetime(df[&#39;Start Time&#39;])
df.info()</code></pre>
<pre><code>&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;
RangeIndex: 7015 entries, 0 to 7014
Data columns (total 11 columns):
 #   Column                   Non-Null Count  Dtype         
---  ------                   --------------  -----         
 0   index                    7015 non-null   int64         
 1   Profile Name             7015 non-null   object        
 2   Start Time               7015 non-null   datetime64[ns]
 3   Duration                 7015 non-null   object        
 4   Attributes               2332 non-null   object        
 5   Title                    7015 non-null   object        
 6   Supplemental Video Type  1898 non-null   object        
 7   Device Type              7015 non-null   object        
 8   Bookmark                 7015 non-null   object        
 9   Latest Bookmark          7015 non-null   object        
 10  Country                  7015 non-null   object        
dtypes: datetime64[ns](1), int64(1), object(9)
memory usage: 603.0+ KB</code></pre><br>

<p>그리고 지표에 따르면 이 시간은 UTC 기준입니다. 따라서 이 시간을 한국 시간대로 변환한 열을 <code>kst_time</code>이라는 이름으로 만들겠습니다.</p>
<pre><code class="language-python">df[&#39;kst_time&#39;] = (
    df[&#39;Start Time&#39;].dt.tz_localize(&quot;UTC&quot;) 
                 .dt.tz_convert(&quot;Asia/Seoul&quot;) 
)
df.head()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/a3934ec3-471b-45ff-b5a7-95570146af85/image.png" alt=""></p>
<br>

<p>본편은 <code>supplemental Video Type</code>가 널 값인 반면, 예고편이나 부가 영상에는 표시가 되어있습니다. 이번에는 본편을 본 것만 분석할 것이기 때문에 부가 영상들은 필요없을 것 같습니다. <code>supplemental Video Type</code>가 널 값인 것만 뽑아내겠습니다.</p>
<pre><code class="language-python">import numpy as np

df_main = df.loc[df[&#39;Supplemental Video Type&#39;].isnull()]
df_main.head()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/7e8fd3b4-dcfd-4f4d-aa3d-b6043ebac310/image.png" alt=""></p>
<br>

<p>그리고 제가 하나 더 추가하고 싶은 변수가 있는데요, 작품이 영화인지 시리즈인지 구분하는 변수입니다. 나중에 분석할 때 영화/시리즈도 같이 보면 좋을 것 같습니다. 영화인지 시리즈인지는 제목으로 파악할 수 있습니다. 시리즈의 경우 제목에 시즌과 회차 정보가 같이 있기 때문이죠. 따라서 제목에 <code>시즌</code> 또는 <code>시리즈</code>라는 단어가 들어있으면 시리즈로 코딩해주겠습니다.</p>
<pre><code class="language-python">df_main[&#39;Movie or Series&#39;] = np.nan
df_main[&#39;Movie or Series&#39;] = df_main[&#39;Movie or Series&#39;].loc[df_main[&#39;Title&#39;].str.contains(&#39;시즌|시리즈&#39;)].replace(np.nan, &quot;Series&quot;)
df_main[&#39;Movie or Series&#39;] = df_main[&#39;Movie or Series&#39;].replace(np.nan, &#39;Movie&#39;)
df_main.head()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/9be83ce0-6d88-4b60-86a7-be8f4598b158/image.png" alt=""></p>
<br>


<h2 id="2-데이터-분석-eda">2. 데이터 분석 (EDA)</h2>
<p>이 정도면 분석에 필요한 데이터 가공은 끝난 것 같습니다! 바로 분석에 들어가 보도록 하겠습니다.</p>
<h3 id="--기기-종류타입에-따른-세션-수">- 기기 종류/타입에 따른 세션 수</h3>
<p>첫번째로 제 눈에 띈 것은 기기 타입입니다. 데이터가 2019년부터 2022년 1월까지 있는데, 제가 이 기간에 기기를 자주 교체했고, 새로 구비도 많이 했거든요. 과연 제가 가장 많이 사용한 기기는 무엇일까요?</p>
<pre><code class="language-python">import matplotlib.pyplot as plt

df_main[&#39;Device Type&#39;].value_counts().plot(kind=&quot;bar&quot;, color = &#39;#42f5a7&#39;)
plt.ylabel(&quot;No. of Sessions&quot;)
plt.title(&quot;No. of Sessions by Device Type&quot;)
plt.xticks(rotation=90)
plt.show()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/b4f4f6dd-1518-4f4c-9e6a-dbec0fca87e5/image.png" alt=""></p>
<p>가장 많이 사용한 것은 아이폰 6, 그리고 이후 교체한 아이폰 SE 순이네요. 저는 모바일 기기를 주로 사용하고, PC를 부가적으로 사용하는 사람인 것 같습니다. 그렇다면 기기 타입별로도 한번 보죠! 기간별로도 차이가 있을테니 히스토그램으로 그려보겠습니다.</p>
<pre><code class="language-python">import seaborn as sns

sns.histplot(df_main[df_main[&#39;Device Type&#39;].str.contains(&#39;iPhone&#39;)][&#39;year&#39;], label=&quot;Mobile&quot;, color = &#39;#003f5c&#39;)
sns.histplot(df_main[df_main[&#39;Device Type&#39;].str.contains(&#39;MAC|PC&#39;)][&#39;year&#39;], label=&quot;PC&quot;, color = &#39;#7a5195&#39;)
sns.histplot(df_main[df_main[&#39;Device Type&#39;].str.contains(&#39;iPad|Tablet&#39;)][&#39;year&#39;], label=&quot;Tablet PC&quot;, color = &#39;#ef5675&#39;)
sns.histplot(df_main[df_main[&#39;Device Type&#39;].str.contains(&#39;Chromecast&#39;)][&#39;year&#39;], label=&quot;TV&quot;, color = &#39;#ffa600&#39;)

plt.title(&quot;Distributions of Device Types Over Years&quot;)
plt.legend()
plt.show()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/6d80b6b6-2393-439a-8bf2-40c670caf549/image.png" alt=""></p>
<p>저는 모바일 기기를 사용해서 영상을 많이 시청했습니다. 다음은 PC네요. 2020년 하반기부터 PC 사용이 급증한 것을 알 수 있는데, 제가 PC를 바꾸면서 그렇게 된 것 같습니다. 2021년 하반기부터는 TV와 태블릿 PC 사용이 생겼는데요, 제가 이무렵 크롬캐스트와 아이패드를 장만했기 때문입니다. 저는 타 기기 사용이 늘면서 모바일 사용이 감소할 것이라고 생각했는데, 꼭 그런 건 아닌 것 같습니다. 모바일 사용이 줄었을 때는 PC 사용도 줄었고, 모바일 사용이 증가했을 때는 PC 사용도 증가했네요. 하지만 전반적으로 봤을 때 모바일 사용이 감소할 것 같긴 합니다.</p>
<p><span style=color:grey>📌 주의사항: 여기에서는 duration이 아니라 세션수로만 보기 때문에 모바일이 다른 기기보다 사용량이 많아보일 수 있습니다. 하지만 duration으로 보면 결과가 다를 수도 있겠죠..!</span></p>
<h3 id="--기기-타입에-따른-시청-시간대-분포">- 기기 타입에 따른 시청 시간대 분포</h3>
<p>다음은 시간대 분포를 보겠습니다. 체감상 항상 넷플릭스를 끼고 사는 것 같긴 합니다만, 그래도 실제 데이터로 보면 다를 것이라고 믿습니다. 보통 식사 시간이나 멀티 태스킹할 때는 모바일 기기를 사용하고, 집중을 할 때는 좀 더 큰 기기를 사용하는데, 데이터는 뭐라고 말할까요?</p>
<pre><code class="language-python">sns.histplot(df_main[df_main[&#39;Device Type&#39;].str.contains(&#39;iPhone&#39;)][&#39;hour&#39;], label=&quot;Mobile&quot;, color = &#39;#003f5c&#39;)
sns.histplot(df_main[df_main[&#39;Device Type&#39;].str.contains(&#39;MAC|PC&#39;)][&#39;hour&#39;], label=&quot;PC&quot;, color = &#39;#7a5195&#39;)
sns.histplot(df_main[df_main[&#39;Device Type&#39;].str.contains(&#39;iPad|Tablet&#39;)][&#39;hour&#39;], label=&quot;Tablet PC&quot;, color = &#39;#ef5675&#39;)
sns.histplot(df_main[df_main[&#39;Device Type&#39;].str.contains(&#39;Chromecast&#39;)][&#39;hour&#39;], label=&quot;TV&quot;, color = &#39;#ffa600&#39;)
plt.title(&quot;Distributions of Viewing Hour for Different Device Types&quot;)
plt.legend()
plt.show()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/f93507d5-a706-4913-bcf4-f4a3c025f468/image.png" alt=""></p>
<p>온종일 넷플릭스를 끼고 산다는 제 체감이 틀리지 않았네요. 이렇게 또 반성을 하게 됩니다. 모바일 기기의 경우, 자는 시간 빼고는 거의 계속 넷플릭스를 틀어놓고 있었네요. 심지어 심야에 사용량이 가장 많습니다. 반면, PC는 확실히 저녁 시간에 사용이 많은 것을 볼 수 있습니다. TV도 저녁 때 사용이 증가합니다. 태블릿 PC는 딱 모바일 기기와 PC를 섞어놓은 패턴이네요. 흥미롭습니다.</p>
<h3 id="--영화-vs-시리즈">- 영화 VS. 시리즈</h3>
<p>그렇다면 영화/시리즈로 구분했을 때 저의 시청 패턴도 한번 분석해보겠습니다 저는 나름 둘 다 많이 본다고 자신하는데, 아무래도 시리즈는 배경처럼 계속 켜놓고 있는 경우가 많아 차이가 많이 날 것 같긴 합니다. </p>
<pre><code class="language-python">sns.histplot(df_main[df_main[&#39;Movie or Series&#39;] == &#39;Series&#39;][&#39;year&#39;], label=&quot;Series&quot;, color = &#39;#003f5c&#39;)
sns.histplot(df_main[df_main[&#39;Movie or Series&#39;] == &#39;Movie&#39;][&#39;year&#39;], label=&quot;Movie&quot;, color = &#39;#ffa600&#39;)

plt.title(&quot;Movie Or Series Over Years&quot;)
plt.legend()
plt.show()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/d7dba78d-a8ba-41ab-b542-77cf43735f02/image.png" alt=""></p>
<p>영화와 시리즈의 차이는 생각보다 더 많이 납니다. 나름 열심히 산다고 살았는데 이것만 보면 저는 무척이나 한가한 사람인 것 같네요. 2021년 중순에는 인턴을 해서 드라마를 볼 시간이 많이 없었습니다만, 그때를 제외하면 아주 하늘을 찌릅니다. 
<img src="https://images.velog.io/images/mare-solis/post/1a8294d8-fe6e-4982-bf3b-b6471243fc4c/image.png" alt=""></p>
<p>반면 영화는 상반기보다는 하반기에 많이 봤군요. 또 재밌는 건, 저한테 있어서 영화와 시리즈는 대체 관계가 아닌가 봅니다. 영화를 더 많이 본다고 시리즈를 덜 보지 않고, 시리즈를 덜 본다고 영화를 더 보지 않네요. 오히려 콘텐츠를 많이 소비할 때는 둘 다 많이 소비하는 패턴을 보입니다.</p>
<h3 id="--영화시리즈-시간대-분포">- 영화/시리즈 시간대 분포</h3>
<p>영화, 시리즈 별로 언제 많이 봤는지 시간대 분포도 살펴보겠습니다.</p>
<pre><code class="language-python">sns.histplot(df_main[df_main[&#39;Movie or Series&#39;] == &#39;Series&#39;][&#39;hour&#39;], label=&quot;Series&quot;, color = &#39;#003f5c&#39;)
sns.histplot(df_main[df_main[&#39;Movie or Series&#39;] == &#39;Movie&#39;][&#39;hour&#39;], label=&quot;Movie&quot;, color = &#39;#ffa600&#39;)
plt.title(&quot;Distributions of Viewing Hour for Different Content Types&quot;)
plt.legend()
plt.show()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/36526aa3-5763-4d73-b0f4-77d3b527e8ca/image.png" alt=""></p>
<p>예상대로 영화는 저녁부터 밤 시간에 많이 시청한 것을 알 수 있습니다. 반면 시리즈는 꾸준히 사용량이 있긴 하지만, 밥 먹는 시간 두번에 튀고, 저녁 시간에는 잠깐 감소했다가 밤에 다시 증가합니다. 제가 넷플릭스라면, 밥 먹을 시간에는 기벼운 시리즈를, 밤에는 영화를 추천하겠습니다.</p>
<h3 id="--영화시리즈-기기별-시간대-분포">- 영화/시리즈 기기별 시간대 분포</h3>
<p>영화와 시리즈를 따로 보며 조금 더 깊이 들어가보겠습니다. 먼저 제가 아주 팬인 것으로 보이는 시리즈부터!</p>
<pre><code class="language-python">sns.histplot(df_main[(df_main[&#39;Device Type&#39;].str.contains(&#39;iPhone&#39;)) &amp; (df_main[&#39;Movie or Series&#39;] == &#39;Series&#39;)][&#39;hour&#39;], label=&quot;Mobile&quot;, color = &#39;#003f5c&#39;)
sns.histplot(df_main[(df_main[&#39;Device Type&#39;].str.contains(&#39;MAC|PC&#39;)) &amp; (df_main[&#39;Movie or Series&#39;] == &#39;Series&#39;)][&#39;hour&#39;], label=&quot;PC&quot;, color = &#39;#7a5195&#39;)
sns.histplot(df_main[(df_main[&#39;Device Type&#39;].str.contains(&#39;iPad|Tablet&#39;)) &amp; (df_main[&#39;Movie or Series&#39;] == &#39;Series&#39;)][&#39;hour&#39;], label=&quot;Tablet PC&quot;, color = &#39;#ef5675&#39;)
sns.histplot(df_main[(df_main[&#39;Device Type&#39;].str.contains(&#39;Chromecast&#39;)) &amp; (df_main[&#39;Movie or Series&#39;] == &#39;Series&#39;)][&#39;hour&#39;], label=&quot;TV&quot;, color = &#39;#ffa600&#39;)
plt.title(&quot;Viewing Activity for Series&quot;)
plt.legend()
plt.show()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/8b399523-0daf-4572-8771-318d4123bb8d/image.png" alt=""></p>
<p>시리즈는 예상대로 모바일로 많이 봤지만, 생각보다 PC의 비중도 낮지 않습니다. 역시 TV로는 많이 시청하지 않았네요.</p>
<br>

<pre><code class="language-python">sns.histplot(df_main[(df_main[&#39;Device Type&#39;].str.contains(&#39;iPhone&#39;)) &amp; (df_main[&#39;Movie or Series&#39;] == &#39;Movie&#39;)][&#39;hour&#39;], label=&quot;Mobile&quot;, color = &#39;#003f5c&#39;)
sns.histplot(df_main[(df_main[&#39;Device Type&#39;].str.contains(&#39;MAC|PC&#39;)) &amp; (df_main[&#39;Movie or Series&#39;] == &#39;Movie&#39;)][&#39;hour&#39;], label=&quot;PC&quot;, color = &#39;#7a5195&#39;)
sns.histplot(df_main[(df_main[&#39;Device Type&#39;].str.contains(&#39;iPad|Tablet&#39;)) &amp; (df_main[&#39;Movie or Series&#39;] == &#39;Movie&#39;)][&#39;hour&#39;], label=&quot;Tablet PC&quot;, color = &#39;#ef5675&#39;)
sns.histplot(df_main[(df_main[&#39;Device Type&#39;].str.contains(&#39;Chromecast&#39;)) &amp; (df_main[&#39;Movie or Series&#39;] == &#39;Movie&#39;)][&#39;hour&#39;], label=&quot;TV&quot;, color = &#39;#ffa600&#39;)
plt.title(&quot;Viewing Activity for Movies&quot;)
plt.legend()
plt.show()</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/d2b969d7-5d07-4d28-a798-b1acd8a893dd/image.png" alt=""></p>
<p>영화는 확연히 다릅니다. 모바일의 비중이 낮고 PC 비중이 압도적으로 가장 높습니다. 심지어 저녁 시간에는 TV 사용량이 모바일 사용량을 넘어서네요. 영화는 좀 더 집중해서 큰 화면으로 봐야한다는 게 제 지론인가봅니다. 참고로 화면 크기는 TV &gt; PC &gt; 태블릿 PC &gt; 모바일 순입니다.</p>
<br>

<p>오늘은 여기까지입니다! 넷플릭스 데이터를 분석해보니 재미는 있지만 반성을 좀 해야겠네요. <span style=color:grey>(심지어 글을 쓰고 있는 지금도 넷플릭스 틀어놓고 있습니다.) </span> 다음에는 영화/시리즈를 타이틀로도 좀 더 자세히 살펴보도록 하겠습니다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[넷플릭스에서는 어떤 데이터를 수집할까?]]></title>
            <link>https://velog.io/@mare-solis/%EB%84%B7%ED%94%8C%EB%A6%AD%EC%8A%A4%EC%97%90%EC%84%9C%EB%8A%94-%EC%96%B4%EB%96%A4-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%88%98%EC%A7%91%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@mare-solis/%EB%84%B7%ED%94%8C%EB%A6%AD%EC%8A%A4%EC%97%90%EC%84%9C%EB%8A%94-%EC%96%B4%EB%96%A4-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%88%98%EC%A7%91%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Sat, 05 Feb 2022 18:22:34 GMT</pubDate>
            <description><![CDATA[<p>넷플릭스는 콘텐츠 서비스이기도 하지만 테크 기업의 이미지도 있습니다. 데이터를 굉장히 잘 활용하고 추천 알고리즘에 공을 들이는 것으로 알려져 있죠. 그래서 과연 넷플릭스에서는 데이터를 얼마나 수집하는지 궁금하기도 합니다. 그런데 넷플릭스 계정 정보에 가면 자신의 데이터를 다운로드 받을 수 있다는 것 알고 계셨나요? 넷플릭스의 데이터, 함께 보도록 하겠습니다.</p>
<hr>
<h2 id="1-데이터-다운로드">1. 데이터 다운로드</h2>
<p>넷플릭스 홈페이지에서 계정 페이지에 들어가면 개인 정보 다운로드라는 항목이 있습니다. 제 기억으로는 작년 말까지는 제가 시청한 콘텐츠에 관한 데이터 하나만 다운로드 받을 수 있었는데 최근 다시 보니 제공받을 수 있는 정보가 훨씬 많아졌더군요. 하지만 절차도 좀 까다로워졌습니다. 예전에는 그냥 바로 csv 파일로 다운로드 받을 수 있었는데 최근에는 정보를 요청해야 합니다. </p>
<p><img src="https://images.velog.io/images/mare-solis/post/07051d1b-aa21-4e0b-b942-30649cf930b4/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/mare-solis/post/af79805e-29e1-4939-b711-e889bc7283aa/image.png" alt=""></p>
<br>

<p>요청 후에는 하루 뒤 &quot;다운로드 준비 완료!&quot;라는 메일이 옵니다.
<img src="https://velog.velcdn.com/images/mare-solis/post/b89e0a97-07b6-4c19-a85a-8a6ead6e0a5a/image.png" alt=""></p>
<h2 id="2-항목-설명">2. 항목 설명</h2>
<p>netflix-report라는 폴더가 다운로드 되었네요. 자, 그렇다면 가장 첫번째로 추가정보.pdf를 보도록 하겠습니다. 여기에는 넷플릭스가 수집하는 데이터가 항목 별로 나와있습니다. 아마 이용약관에도 나와있지 않았을까 싶네요. 하지만 난 이용약관을 잘 읽지 않지 🌝 
<img src="https://images.velog.io/images/mare-solis/post/420cb38f-b3de-44f7-a7f4-4ff4c22058a6/image.png" alt=""></p>
<p>넷플릭스가 수집하는 정보는 네가지 종류로, <strong>회원이 넷플릭스에 제공하는 정보, 넷플릭스가 자동으로 수집하는 정보, 파트너사 제공 정보, 다른 출처에서 얻은 정보</strong>가 있습니다. 다 흥미롭지만 이 중에서 눈여겨 볼 것은 넷플릭스가 자동으로 수집하는 정보겠죠!</p>
<blockquote>
<ul>
<li>콘텐츠 선택,시청한 프로그램 및 검색어 등 회원의 Netflix 서비스 내 활동</li>
<li>Netflix가 발송한 이메일과 문자메시지, 그리고 Netflix가 푸시 알림 및 온라인 메시징 채널을 통해 보낸 메시지를 회원이 수신하고 이에 대응한 내용</li>
<li>문의한 일시와 이유,채팅 대화 기록, (전화 문의인 경우) 전화번호와 통화 녹음등 회원의 Netflix 고객 센터 문의에 관한 세부 내용</li>
<li>디바이스 ID등 의 고유식별자(회원의 Wi-Fi 네트워크에서 Netflix 이용이가능한 디바이스 포함)</li>
<li>재설정 가능 디바이스 식별자(광고 식별자로도 알려짐). 예를 들어 이러한 식별자가 있는 모바일 디바이스, 태블릿 및 스트리밍 미디어 디바이스 등에서 사용하는 식별자 (자세한 내용은 아래 &#39;쿠키 및 인터넷 광고&#39; 섹션 참조)</li>
<li>디바이스 및 소프트웨어 특성(유형및구성등), 연결정보, 페이지뷰 관련 통계, 참조 소스(예: 참조 URL), IP 주소(회원의 대략적인 위치 정보), 브라우저 및 표준 웹 서버 로그 정보</li>
<li>광고 데이터(광고 이용 여부 및 게재, 사이트 URL, 날짜 및 시간 관련 정보등)를 비롯해 쿠키, 웹 비콘 및 기타 기술을 사용해 수집한 정보 (자세한 내용은 &#39;쿠키 및 인터넷 광고&#39; 섹션 참조)</li>
</ul>
</blockquote>
<br>

<p>두번째 파일인 표지.pdf에는 말그대로 csv 파일과 표에 있는 변수 이름이 무엇을 의미하는지 상세히 설명하고 있습니다. 데이터를 보다가 이해가 되지 않는다면 이 파일을 보면 되겠습니다. 
<img src="https://images.velog.io/images/mare-solis/post/00837955-f659-4f33-be49-882a1c49b972/image.png" alt=""></p>
<br>

<h2 id="3-데이터-살펴보기">3. 데이터 살펴보기</h2>
<p>첫번째 폴더인 ACCOUNT에 들어가 보니, 세개의 파일이 있습니다. 그 중 AccountDetails.csv의 표는 열이 하나로, 저의 기본적인 계정 정보가 담겨 있습니다. 그닥 흥미로운 정보는 없으니 넘어가겠습니다. </p>
<p>두번째 파일은 SubscriptionHistory.csv입니다. 제가 해당 계정을 통해 서비스를 구독하고 해지한 기록이 남아있습니다. 이것도 마찬가지로 기본적인 정보입니다만, 제가 예전에 구독했을 때의 패키지 정보와 이번에 새로 구독했을 때 패키지 정보를 비교하여 수집하는 것은 흥미롭네요.</p>
<table>
<thead>
<tr>
<th align="center">Plan Change Old Category</th>
<th align="center">Plan Change Old Max Concurrent Streams</th>
<th align="center">Plan Change Old Max Streaming Quality</th>
<th align="center">Plan Change New Category</th>
<th align="center">Plan Change New Max Concurrent Streams</th>
<th align="center">Plan Change New Max Streaming Quality</th>
</tr>
</thead>
<tbody><tr>
<td align="center">STREAMING ONLY</td>
<td align="center">2</td>
<td align="center">HD</td>
<td align="center">STREAMING ONLY</td>
<td align="center">4</td>
<td align="center">UHD</td>
</tr>
</tbody></table>
<br>

<p>두번째 폴더는 CLICKSTREAM으로, 파일은 하나입니다. 제가 어떤 OS로 언제 무엇을 클릭했는지 볼 수 있습니다. 어떤 걸 클릭했나 살펴보니 아래와 같습니다 (참고로  웹에서 접속한 정보에 대해서는 클릭한 페이지 URL까지 표시됩니다.)</p>
<ul>
<li>accountMenu</li>
<li>addProfile</li>
<li>browseTitles</li>
<li>browseTitlesGallery</li>
<li>cachedVideos</li>
<li>deviceSurvey</li>
<li>downloadsTab</li>
<li>editProfileAvatar</li>
<li>gameDetails</li>
<li>login</li>
<li>movieDetails</li>
<li>newsFeed</li>
<li>nmLanding</li>
<li>orderConfirmation</li>
<li>orderFinal</li>
<li>playback</li>
<li>postPlay</li>
<li>profilesGate</li>
<li>search</li>
<li>secondaryLanguagesSelector</li>
<li>updateProfiles</li>
<li>updateProfilesKids</li>
</ul>
<br>

<p>제 생각에는 다음 폴더가 찐일 것 같은데요, CONTENT_INTERACTION 폴더입니다. 가장 많은 파일이 있습니다. 첫번째인 IndicatedPreferences.csv는 처음 넷플릭스에 가입할 때 선호하는 콘텐츠를 고르도록 하는데, 그 정보라고 합니다. 워낙 예전에 해서 저는 잘 기억나지도 않네요 🙄</p>
<table>
<thead>
<tr>
<th align="center">Show</th>
<th align="center">Has Watched</th>
<th align="center">Is Interested</th>
<th align="center">Event Date</th>
</tr>
</thead>
<tbody><tr>
<td align="center">The Good Place</td>
<td align="center">FALSE</td>
<td align="center">TRUE</td>
<td align="center">2018-08-27</td>
</tr>
<tr>
<td align="center">Marvel&#39;s The Punisher</td>
<td align="center"></td>
<td align="center"></td>
<td align="center">2019-05-11</td>
</tr>
</tbody></table>
<br>

<p>두번째는 InteractiveTitles.csv입니다. 2018년에 &lt;블랙미러: 밴더스내치&gt; 나온 거 기억하시나요? 그때 참 열심히 했었는데 그 기록이 남아있었네요. 제가 어떤 선택을 언제 했는지, 그리고 이 선택을 예전에도 한 적이 있는지 나와 있습니다. countdown_complete와 interrupted는 제가 카운트다운 전에 선택을 했는지 아닌지를 의미하는 것 같네요. 어떤 선택지에서 고민을 많이 했는지 알 수 있습니다.</p>
<table>
<thead>
<tr>
<th align="center">Title Desc</th>
<th align="center">Selection Type</th>
<th align="center">Choice Segment Id</th>
<th align="center">Has Watched</th>
<th align="center">Source</th>
<th align="center">Utc Timestamp</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Black Mirror: Bandersnatch</td>
<td align="center">countdown_complete</td>
<td align="center">책상을 내리친다</td>
<td align="center">FALSE</td>
<td align="center">android</td>
<td align="center">2018-12-30 14:28:40</td>
</tr>
<tr>
<td align="center">Black Mirror: Bandersnatch</td>
<td align="center">countdown_interrupted</td>
<td align="center">되돌아가기</td>
<td align="center">FALSE</td>
<td align="center">android</td>
<td align="center">2018-12-30 14:28:36</td>
</tr>
<tr>
<td align="center">Black Mirror: Bandersnatch</td>
<td align="center">countdown_interrupted</td>
<td align="center">컴퓨터를 망가뜨린다</td>
<td align="center">FALSE</td>
<td align="center">android</td>
<td align="center">2018-12-30 14:28:06</td>
</tr>
<tr>
<td align="center">Black Mirror: Bandersnatch</td>
<td align="center">countdown_complete</td>
<td align="center">약을 먹는다</td>
<td align="center">FALSE</td>
<td align="center">android</td>
<td align="center">2018-12-30 14:27:23</td>
</tr>
<tr>
<td align="center">Black Mirror: Bandersnatch</td>
<td align="center">countdown_interrupted</td>
<td align="center">손톱을 물어뜯는다</td>
<td align="center">FALSE</td>
<td align="center">android</td>
<td align="center">2018-12-30 14:26:51</td>
</tr>
</tbody></table>
<br>

<p>My List는 당연히! 내가 찜한 콘텐츠를 의미합니다. 생각보다는 간단하네요.</p>
<table>
<thead>
<tr>
<th align="center">Profile Name</th>
<th align="center">Title Name</th>
<th align="center">Country</th>
<th align="center">Utc Title Add Date</th>
</tr>
</thead>
<tbody><tr>
<td align="center">User</td>
<td align="center">Call My Agent!</td>
<td align="center">South Korea</td>
<td align="center">2022-01-06</td>
</tr>
<tr>
<td align="center">User</td>
<td align="center">Mid90s</td>
<td align="center">South Korea</td>
<td align="center">2022-01-06</td>
</tr>
<tr>
<td align="center">User</td>
<td align="center">The Stranger</td>
<td align="center">South Korea</td>
<td align="center">2022-01-04</td>
</tr>
</tbody></table>
<br>

<p>다음은 PlaybackRelatedEvents.csv입니다. 제가 콘텐츠 시청 중 수행한 작업에 대한 정보가 담겨있습니다. Playtraces 중 하나를 보겠습니다.</p>
<span style="color:grey">
[{"eventType":"start","sessionOffsetMs":0,"mediaOffsetMs":429001},{"eventType":"playing","sessionOffsetMs":654,"mediaOffsetMs":429001},{"eventType":"paused","sessionOffsetMs":4056,"mediaOffsetMs":432000},{"eventType":"reposition","sessionOffsetMs":4057,"mediaOffsetMs":442186},{"eventType":"playing","sessionOffsetMs":4254,"mediaOffsetMs":442186},{"eventType":"paused","sessionOffsetMs":4984,"mediaOffsetMs":443000},{"eventType":"reposition","sessionOffsetMs":4985,"mediaOffsetMs":452831},{"eventType":"playing","sessionOffsetMs":5351,"mediaOffsetMs":452831},{"eventType":"stopped","sessionOffsetMs":883113,"mediaOffsetMs":1328660}]
</span>

<p>제가 콘텐츠를 시작하고 재생하다가 일시정지를 했고, 10초 이동해 다시 재생했네요. 그리고 한번 더 멈추고 10초 이동, 재생, 이후 종료했습니다. sessionOfseetMs는 세션에서 어느 시점에 이런 이벤트가 발생했는지, mediaOffsetMs는 영상에서 어느 시점에 이벤트가 발생했는지 알려줍니다. 넷플릭스가 이런 정보를 이용해 &lt;하우스 오브 카드&gt;를 제작했다는 얘기를 들은 적이 있는데, 실제로 수집을 하긴 하네요..!</p>
<br>

<p>다음은 Ratings.csv입니다. 넷플릭스는 thumb up/down의 단순한 방식으로 콘텐츠르 평가하도록 하는데, 여기에는 Star Value라는 항목도 있습니다. 표지에는 &quot;프로필 사용자가 특정TV 프로그램 또는 영화에 마지막으로 남긴 별점&quot;이라고 나오고, 0은 평가를 삭제, -1은 관심 없음, -2는 선호 콘텐츠 선택 당시 시청한 적 없음이라고 합니다. 제 데이터에는 Star Value가 나오지 않네요. </p>
<table>
<thead>
<tr>
<th align="center">Title Name</th>
<th align="center">Rating Type</th>
<th align="center">Star Value</th>
<th align="center">Thumbs Value</th>
<th align="center">Device Model</th>
<th align="center">Event Utc Ts</th>
<th align="center">Region View Date</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Master of None</td>
<td align="center">thumb</td>
<td align="center"></td>
<td align="center">1</td>
<td align="center">HTML 5</td>
<td align="center">2021-05-22 02:53:37</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">Love and Monsters</td>
<td align="center">thumb</td>
<td align="center"></td>
<td align="center">2</td>
<td align="center">iPhone</td>
<td align="center">2021-04-22 15:10:19</td>
<td align="center"></td>
</tr>
</tbody></table>
<br>

<p>다음은 SearchHistory.csv 파일입니다. 검색은 제가 넷플릭스에서 가장 좋아하는 기능이기도 합니다. 검색이 너무 잘 되기 때문이죠! 그리고 넷플릭스에 없는 콘텐츠를 자주 검색하면 얼마 뒤 실제로 그 콘텐츠가 들어온다는 것,  우연의 일치인지는 모르겠지만 저는 경험해봤다고 생각합니다 😗</p>
<table>
<thead>
<tr>
<th align="center">Country Iso Code</th>
<th align="center">Device</th>
<th align="center">Is Kids</th>
<th align="center">Query Typed</th>
<th align="center">Displayed Name</th>
<th align="center">Action</th>
<th align="center">Section</th>
<th align="center">Utc Timestamp</th>
</tr>
</thead>
<tbody><tr>
<td align="center">KR</td>
<td align="center">iPhone</td>
<td align="center">0</td>
<td align="center">미국tv</td>
<td align="center">미국 TV 드라마</td>
<td align="center">view_suggestion_info</td>
<td align="center">suggestion_results</td>
<td align="center">2021-10-12 13:32:33</td>
</tr>
<tr>
<td align="center">KR</td>
<td align="center">iPhone</td>
<td align="center">0</td>
<td align="center">스릴러</td>
<td align="center">스릴러·범죄</td>
<td align="center">view_suggestion_info</td>
<td align="center">suggestion_results</td>
<td align="center">2021-10-12 13:32:14</td>
</tr>
<tr>
<td align="center">KR</td>
<td align="center">iPhone</td>
<td align="center">0</td>
<td align="center">크리스마스</td>
<td align="center">렛 잇 스노우</td>
<td align="center">view_video_info</td>
<td align="center">suggestion_title_results</td>
<td align="center">2021-11-23 15:32:16</td>
</tr>
<tr>
<td align="center">KR</td>
<td align="center">Android Tablet</td>
<td align="center">0</td>
<td align="center">벽난</td>
<td align="center">벽난로 4K: 가상의 따뜻한 자작나무 벽난로</td>
<td align="center">play</td>
<td align="center">video_info</td>
<td align="center">2021-10-29 09:42:18</td>
</tr>
<tr>
<td align="center">이렇게 제목, 장르, 특성 뭘로 검색해도 넷플릭스는 대부분 만족할만한 결과를 내놓는데요, 제가 이상하게 검색해도 찰떡같이 알아듣습니다. 이후 저는 더 많은 제안된 검색어를 보기도 했고, 콘텐츠 리스트가 나오면 상세 정보를 보거나, 바로 재생을 하기도 했습니다.</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<br>

<p>마지막으로 ViewingActivity.csv는 가장 중요하다고도 할 수 있는 정보입니다. 구독형 서비스의 경우 Duration을 바탕으로 정산이 이루어지기도 하죠. 어디에 북마크가 저장되었는지에 관한 정보도 여기에 있네요.  Latest Bookmark의 경우, 표지에서는 &quot;해당 북마크가 TV 프로그램 또는 영화의 가장 최근 재생 세션에서 가장 최근에 시청한 위치인지 여부&quot;라고 나와있는데요, 다른 게 아니라 숫자가 있으면 &quot;그 이후에 콘텐츠를 보지 않았으며, 지금도 저 위치에 북마크가 되어 있군!&quot; Not latest view는 &quot;이번 세션 이후에 또 이 콘텐츠를 봤구나&quot;라고 이해하면 되겠습니다. </p>
<table>
<thead>
<tr>
<th align="center">Start Time</th>
<th align="center">Duration</th>
<th align="center">Attributes</th>
<th align="center">Title</th>
<th align="center">Supplemental Video Type</th>
<th align="center">Bookmark</th>
<th align="center">Latest Bookmark</th>
</tr>
</thead>
<tbody><tr>
<td align="center">2021-12-24 12:46:46</td>
<td align="center">00:42:30</td>
<td align="center"></td>
<td align="center">고요의 바다: 시즌 1: 세 개의 저장고 (2화)</td>
<td align="center"></td>
<td align="center">00:42:30</td>
<td align="center">00:42:30</td>
</tr>
<tr>
<td align="center">2021-12-24 11:59:58</td>
<td align="center">00:00:05</td>
<td align="center"></td>
<td align="center">고요의 바다: 시즌 1: 발해기지 (1화)</td>
<td align="center"></td>
<td align="center">00:00:05</td>
<td align="center">Not latest view</td>
</tr>
<tr>
<td align="center">2021-12-24 11:59:56</td>
<td align="center">00:46:42</td>
<td align="center"></td>
<td align="center">고요의 바다: 시즌 1: 발해기지 (1화)</td>
<td align="center"></td>
<td align="center">00:46:42</td>
<td align="center">00:46:42</td>
</tr>
<tr>
<td align="center">2021-12-24 11:59:28</td>
<td align="center">00:00:32</td>
<td align="center">Autoplayed: user action: None;</td>
<td align="center">시즌 1 (티저 예고편 1): 고요의 바다</td>
<td align="center">TEASER_TRAILER</td>
<td align="center">00:00:32</td>
<td align="center">Not latest view</td>
</tr>
</tbody></table>
<br>

<p>자, 이렇게 오늘은 넷플릭스가 제공하는 개인 정보를 살펴봤습니다. 이외에도 9개의 폴더가 더 있지만 이건 찐 개인정보에 별로 흥미없는 것들이라 패스하죠. 다음에는 이번에 살펴봤던 데이터를 한번 분석해보는 것도 재밌겠네요!</p>
<p><img src="https://images.velog.io/images/mare-solis/post/2146cd8e-7aa8-400e-87ad-125e23762a6f/netflix-netflix-logo.gif" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BERT] KeyBert로 리뷰 키워드 추출하기]]></title>
            <link>https://velog.io/@mare-solis/BERT-keyBert%EB%A1%9C-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@mare-solis/BERT-keyBert%EB%A1%9C-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 04 Feb 2022 20:38:43 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/mare-solis/post/9576787e-b44b-4d53-92a7-e7f85e4e92e8/image.png" alt=""></p>
<blockquote>
<p>BERT: Bidirectional Encoder Representations from Transformer</p>
</blockquote>
<h2 id="1-bert">1. BERT</h2>
<p>BERT는 2018년에 자연어 처리를 위해 구글에서 고안한 트랜스포머 기반의 머신러닝 기법입니다. BERT의 가장 큰 특징은 문장 전체의 구조를 양방향으로 학습하여 문맥을 파악할 수 있다는 것입니다. 가령, 기존의 Word2vec, Glove와 같은 임베딩 방식은 문맥 파악 없이 단어를 임베딩했다면, BERT는 같은 단어라고 하더라도 앞뒤 문맥을 통해 구분할 수 있다는 것이죠! <span style='color:grey'>(참고로 BERT는 저 노란 친구의 이름이기도 합니다.) </span>
<br></p>
<p>BERT는 두 단계로 이루어집니다.
👆 사전학습 (Pre-training): 영문 위키피디아와 BooksCorpus의 데이터를 사용하여 두 가지 학습을 하는데, 하나는 단어를 무작위로 가려놓고 원래 단어를 맞추는 학습 (Masked LM), 다른 하나는 문장의 순서를 예측하는 것을 학습합니다 (Next Sentence Prediction, NSP). 
✌️ 미세 조정 (fine-tuning): 사전학습 시 사용된 파라미터를 모두 조정하여 모델이 어느 한 태스크에 국한되지 않고 범용적으로 쓰일 수 있도록 합니다.</p>
<h2 id="2-keybert">2. KeyBERT</h2>
<p>키워드 추출을 위해서는 BERT를 적용한 오픈 소스 파이썬 모듈인 KeyBERT를 사용하겠습니다. KeyBERT의 원리는 BERT를 이용해 문서 레벨 (document-level)에서의 주제 (representation)를 파악하도록 하고, N-gram을 위해 단어를 임베딩 합니다. 이후 코사인 유사도를 계산하여 어떤 N-gram 단어 또는 구가 문서와 가장 유사한지 찾아냅니다. 가장 유사한 단어들은 문서를 가장 잘 설명할 수 있는 키워드로 분류됩니다 (<a href="https://maartengr.github.io/KeyBERT/index.html">https://maartengr.github.io/KeyBERT/index.html</a>). </p>
<h2 id="3-데이터-분석">3. 데이터 분석</h2>
<p>그렇다면 KeyBert를 사용해서 넷플릭스에 있는 한국 작품들에 대한 외국 시청자들의 반응을 알아보도록 하겠습니다. </p>
<h3 id="31-데이터-수집">3.1. 데이터 수집</h3>
<p>데이터를 수집할 작품은 모두 10개로, 플릭스 패트롤에서 상위 열개의 작품을 선정했습니다 (<a href="https://flixpatrol.com/">https://flixpatrol.com/</a>). </p>
<table>
<thead>
<tr>
<th align="center">제목</th>
<th align="center">영어 제목</th>
<th align="center">플릭스 패트롤 포인트</th>
<th align="center">영화/시리즈</th>
<th align="center">방영일</th>
</tr>
</thead>
<tbody><tr>
<td align="center">오징어 게임</td>
<td align="center">Squid Game</td>
<td align="center">43,657</td>
<td align="center">시리즈</td>
<td align="center">2021.9.17</td>
</tr>
<tr>
<td align="center">빈센조</td>
<td align="center">Vincenzo</td>
<td align="center">19,792</td>
<td align="center">시리즈</td>
<td align="center">2021.2.20</td>
</tr>
<tr>
<td align="center">갯마을 차차차</td>
<td align="center">Hometown Cha-Cha-Cha</td>
<td align="center">10,172</td>
<td align="center">시리즈</td>
<td align="center">2021.8.28</td>
</tr>
<tr>
<td align="center">마이 네임</td>
<td align="center">My Name</td>
<td align="center">8,595</td>
<td align="center">시리즈</td>
<td align="center">2021.10.15</td>
</tr>
<tr>
<td align="center">스타트업</td>
<td align="center">Start-Up</td>
<td align="center">8,404</td>
<td align="center">시리즈</td>
<td align="center">2020.10.17</td>
</tr>
<tr>
<td align="center">알고 있지만</td>
<td align="center">Nevertheless</td>
<td align="center">7,235</td>
<td align="center">시리즈</td>
<td align="center">2021.6.19</td>
</tr>
<tr>
<td align="center">슬기로운 의사생활</td>
<td align="center">Hospital Playlist</td>
<td align="center">7,102</td>
<td align="center">시리즈</td>
<td align="center">2021.6.17</td>
</tr>
<tr>
<td align="center">#살아있다</td>
<td align="center">#Alive</td>
<td align="center">6,928</td>
<td align="center">영화</td>
<td align="center">2020.9.8</td>
</tr>
<tr>
<td align="center">청춘기록</td>
<td align="center">Record of Youth</td>
<td align="center">5,966</td>
<td align="center">시리즈</td>
<td align="center">2020.9.7</td>
</tr>
<tr>
<td align="center">승리호</td>
<td align="center">Space Sweepers</td>
<td align="center">5,662</td>
<td align="center">영화</td>
<td align="center">2021.2.5</td>
</tr>
</tbody></table>
<p>이번에 외국 시청자의 반응을 보기 위해 사용할 데이터는 IMDb 리뷰입니다. 수집된 데이터는 다음과 같습니다. 
<img src="https://images.velog.io/images/mare-solis/post/c4a23601-c1d0-4a84-a0a0-fb27693f0b5c/image.png" alt=""></p>
<h3 id="32-키워드-추출">3.2. 키워드 추출</h3>
<p>KeyBert의 기본적인 사용법은 개발자가 정리한 이 문서를 참고해주세요(<a href="https://github.com/MaartenGr/KeyBERT">https://github.com/MaartenGr/KeyBERT</a>). 제가 작성한 코드는 다음과 같습니다.</p>
<pre><code class="language-python">def BERT(title):

    array_text = pd.DataFrame(df[df[&#39;title&#39;] == title][&#39;text&#39;]).to_numpy()

    bow = []
    from keybert import KeyBERT
    kw_extractor = KeyBERT(&#39;distilbert-base-nli-mean-tokens&#39;)
    for j in range(len(array_text)):
        keywords = kw_extractor.extract_keywords(array_text[j][0])
        bow.append(keywords)

    new_bow = []
    for i in range(0, len(bow)):
        for j in range(len(bow[i])):
            new_bow.append(bow[i][j])

    keyword = pd.DataFrame(new_bow, columns=[&#39;keyword&#39;, &#39;weight&#39;])
    print(keyword.groupby(&#39;keyword&#39;).agg(&#39;sum&#39;).sort_values(&#39;weight&#39;, ascending=False).head(20))
</code></pre>
<p>따라서 <code>BERT(&#39;vincenzo&#39;)</code>라고 입력하면 드라마 &lt;빈센조&gt;의 키워드가 추출된 아웃풋이 나옵니다. </p>
<p>👉 <strong>아웃풋</strong></p>
<pre><code>             weight
keyword            
mafia        3.7755
comedy       3.6292
best         2.6592
love         2.6583
thriller     2.3891
good         1.7765
romance      1.4485
acting       1.1075
italian      1.0790
perfect      0.9724
worth        0.9630
drama        0.9415
netflix      0.8274
watching     0.7717
korean       0.7549
movie        0.7046
slapstick    0.7029
great        0.7028
funny        0.6778
exaggerated  0.6716</code></pre><h2 id="4-시각화">4. 시각화</h2>
<p><img src="https://images.velog.io/images/mare-solis/post/2e596146-6822-4d6c-a75f-ba4b3d4c9ae8/image.png" alt="">
<img src="https://images.velog.io/images/mare-solis/post/4032e4d5-2295-4a45-b0ec-bac3ce52b019/image.png" alt="">
<img src="https://images.velog.io/images/mare-solis/post/84bd4685-f540-4bb2-b356-274721091178/image.png" alt="">
<img src="https://images.velog.io/images/mare-solis/post/c2ffd208-40c4-47f3-aed5-010980d2bbf5/image.png" alt="">
<img src="https://images.velog.io/images/mare-solis/post/8b083324-0ff3-4a61-ae38-17c51b80ed01/image.png" alt="">
<img src="https://images.velog.io/images/mare-solis/post/4688661d-5f2f-488a-b01b-d7a487aaaa64/image.png" alt="">
<img src="https://images.velog.io/images/mare-solis/post/cd853235-a392-450e-a81d-1feb92b2f71e/image.png" alt="">
<img src="https://images.velog.io/images/mare-solis/post/87d072a7-32cb-4d43-af2b-777befae9826/image.png" alt="">
<img src="https://images.velog.io/images/mare-solis/post/4e3d6bd8-f859-4199-9f83-2196c50cfdf7/image.png" alt="">
<img src="https://images.velog.io/images/mare-solis/post/3bc0f04e-db97-4eb7-aec3-b4eb7d160cc0/image.png" alt=""></p>
<h2 id="5-tf-idf-비교">5. TF-IDF 비교</h2>
<p>그렇다면 KeyBert의 성능이 더 나은지 보기 위해 기존에 단어의 중요도를 파악하기 위해 사용하던 TF-IDF와 비교해보겠습니다. </p>
<blockquote>
<p>TF-IDF: 정보 검색과 텍스트 마이닝에서 이용하는 가중치로, 여러 문서로 이루어진 문서군이 있을 때 어떤 단어가 특정 문서 내에서 얼마나 중요한 것인지를 나타내는 통계적 수치 (위키피디아).</p>
</blockquote>
<table>
<thead>
<tr>
<th align="center">TF-IDF Keyword</th>
<th align="center">TF-IDF score</th>
<th align="center">keyBERT Keyword</th>
<th align="center">KeyBERT score</th>
</tr>
</thead>
<tbody><tr>
<td align="center">far</td>
<td align="center">0.254888</td>
<td align="center">mafia</td>
<td align="center">3.7725</td>
</tr>
<tr>
<td align="center">series</td>
<td align="center">0.227292</td>
<td align="center">comedy</td>
<td align="center">3.6292</td>
</tr>
<tr>
<td align="center">great</td>
<td align="center">0.216156</td>
<td align="center">best</td>
<td align="center">2.6592</td>
</tr>
<tr>
<td align="center">is</td>
<td align="center">0.200286</td>
<td align="center">love</td>
<td align="center">2.6583</td>
</tr>
<tr>
<td align="center">which</td>
<td align="center">0.181828</td>
<td align="center">thriller</td>
<td align="center">2.3891</td>
</tr>
<tr>
<td align="center">so</td>
<td align="center">0.174995</td>
<td align="center">good</td>
<td align="center">1.7765</td>
</tr>
<tr>
<td align="center">for</td>
<td align="center">0.165621</td>
<td align="center">romance</td>
<td align="center">1.4485</td>
</tr>
<tr>
<td align="center">episodes</td>
<td align="center">0.140714</td>
<td align="center">acting</td>
<td align="center">1.1075</td>
</tr>
<tr>
<td align="center">flaws</td>
<td align="center">0.135521</td>
<td align="center">italian</td>
<td align="center">1.0790</td>
</tr>
<tr>
<td align="center">hell</td>
<td align="center">0.135521</td>
<td align="center">perfect</td>
<td align="center">0.9724</td>
</tr>
</tbody></table>
<br>

<p>딱 봐도 KeyBERT를 통해 추출한 키워드가 훨씬 의미있다는 것을 볼 수 있습니다. TF-IDF를 통해 추출된 단어는 의미없는 단어를 제거하기 위해 전처리가 많이 필요할 것 같아 보이지만, KeyBERT는 별도의 전처리 과정 없이도 만족할만한 결과를 얻을 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LDA 토픽 모델링으로 콘텐츠 리뷰를 분석하자 ]]></title>
            <link>https://velog.io/@mare-solis/LDA-%ED%86%A0%ED%94%BD-%EB%AA%A8%EB%8D%B8%EB%A7%81%EC%9C%BC%EB%A1%9C-%EC%BD%98%ED%85%90%EC%B8%A0-%EB%A6%AC%EB%B7%B0%EB%A5%BC-%EB%B6%84%EC%84%9D%ED%95%98%EC%9E%90</link>
            <guid>https://velog.io/@mare-solis/LDA-%ED%86%A0%ED%94%BD-%EB%AA%A8%EB%8D%B8%EB%A7%81%EC%9C%BC%EB%A1%9C-%EC%BD%98%ED%85%90%EC%B8%A0-%EB%A6%AC%EB%B7%B0%EB%A5%BC-%EB%B6%84%EC%84%9D%ED%95%98%EC%9E%90</guid>
            <pubDate>Fri, 04 Feb 2022 17:51:49 GMT</pubDate>
            <description><![CDATA[<p>저는 얼마 전까지만 해도 리뷰 분석을 위해 LDA 토픽 모델링을 적극적으로 활용했습니다. 다른 분석들 보다도 어떤 주제에 대해 여론이 형성되었는지 확인하기 편리해서 특히 연구를 시작하는 단계에서 한번 해볼만한 분석이죠. 물론 토픽모델링 자체로도 하나의 연구가 될 수도 있고요! 이번에는 LDA 토픽 모델링으로 콘텐츠 리뷰를 분석해보겠습니다.</p>
<hr>
<h2 id="1-데이터-전처리">1. 데이터 전처리</h2>
<pre><code class="language-python">from konlpy.tag import Mecab
from tqdm import tqdm
import re
import pickle
import csv
import pandas as pd
from pandas import DataFrame 
import numpy as np</code></pre>
<br>

<p>우선 데이터를 수집해보겠습니다. 콘텐츠에 대한 의견이 담겨있는 많은 텍스트 데이터가 필요하겠죠. 저는 트위터를 선택했고, 넷플릭스 드라마 &lt;스위트홈&gt;에 대한 트윗을 분석하기로 했습니다. 데이터는 아래처럼 수집되었습니다. </p>
<pre><code class="language-python">title = &#39;스위트홈.csv&#39;</code></pre>
<p><img src="https://images.velog.io/images/mare-solis/post/0ea1f309-6bd1-4ec4-a631-f771fba2932c/image.png" alt=""></p>
<br>
데이터를 보니 별다른 내용 없이 URL만 있는 경우가 많았는데요, 이런 경우에는 시청자의 의견이 포함되었다고 보기 어렵겠죠. 이런 데이터는 삭제했습니다. 이후 한국어 텍스트만 보기 위해 기본적인 텍스트 정제를 했습니다. 


<pre><code class="language-python">def clean_text(text):
    text = text.replace(&quot;.&quot;, &quot;&quot;).strip()
    text = text.replace(&quot;·&quot;, &quot; &quot;).strip()
    pattern = &#39;[^ ㄱ-ㅣ가-힣|0-9]+&#39;
    text = re.sub(pattern=pattern, repl=&#39;&#39;, string=text)
    return text</code></pre>
<br>

<p>그리고 문장을 토큰화 해야 합니다. 저는 KoNLPy Mecab 태그 중 일반명사, 고유명사, 형용사, 어근만 추출하도록 하겠습니다. Mecab 품사는 이 문서에 설명되어 있습니다 (<a href="https://docs.google.com/spreadsheets/d/1OGAjUvalBuX-oZvZ_-9tEfYD2gQe7hTGsgUpiiBSXI8/edit#gid=0">https://docs.google.com/spreadsheets/d/1OGAjUvalBuX-oZvZ_-9tEfYD2gQe7hTGsgUpiiBSXI8/edit#gid=0</a>).</p>
<pre><code class="language-python">
def get_nouns(tokenizer, sentence):
    tagged = tokenizer.pos(sentence)
    nouns = [s for s, t in tagged if t in [&#39;NNG&#39;, &#39;NNP&#39;, &#39;VA&#39;, &#39;XR&#39;] and len(s) &gt;1]
    return nouns

def tokenize(df):
    tokenizer = Mecab(dicpath=&#39;/usr/local/lib/mecab/dic/mecab-ko-dic&#39;)
    processed_data = []
    for sent in tqdm(df[&#39;text&#39;]):
        sentence = clean_text(str(sent).replace(&quot;\n&quot;, &quot;&quot;).strip())
        processed_data.append(get_nouns(tokenizer, sentence))
    return processed_data</code></pre>
<br>

<p>그 다음엔 이렇게 토큰화 된 데이터를 다른 파일로 저장하도록 합니다. </p>
<pre><code class="language-python">def save_processed_data(processed_data):
    with open(&quot;tokenized_data_&quot;+title, &#39;w&#39;, newline=&quot;&quot;, encoding=&#39;utf-8&#39;) as f:
        writer = csv.writer(f)
        for data in processed_data:
            writer.writerow(data)

if __name__ == &#39;__main__&#39;:
    df = pd.read_csv(&quot;file_name.csv&quot;)
    df.columns=[&#39;user&#39;, &#39;date&#39;, &#39;time&#39;, &#39;text&#39;, &#39;comment&#39;, &#39;like&#39;, &#39;share&#39;]
    df.dropna(how=&#39;any&#39;)
    processed_data = tokenize(df)
    save_processed_data(processed_data)</code></pre>
<p>👉 <strong>아웃풋</strong></p>
<p><img src="https://images.velog.io/images/mare-solis/post/db161b61-25da-49e0-97a0-1f1754201e0c/image.png" alt="">
<br></p>
<p>그리고 분석을 위해서는 이걸 다시 리스트로 만들어야 합니다. </p>
<pre><code class="language-python">processed_data = [sent.strip().split(&quot;,&quot;) for sent in tqdm(open(&quot;tokenized_data_&quot;+title,&#39;r&#39;,encoding=&#39;utf-8&#39;).readlines())]
processed_data = DataFrame(processed_data)
processed_data[0] = processed_data[0].replace(&quot;&quot;, np.nan)
processed_data = processed_data[processed_data[0].notnull()]
processed_data = processed_data.values.tolist()
processed_data2=[]
for i in processed_data:
    i = list(filter(None, i))
    processed_data2.append(i)
processed_data = processed_data2
processed_data</code></pre>
<p>👉 <strong>아웃풋</strong></p>
<pre><code>[[&#39;스위트&#39;, &#39;새벽&#39;, &#39;시간&#39;],
 [&#39;스위트&#39;, &#39;송강&#39;],
 [&#39;스위트&#39;, &#39;스위트&#39;, &#39;나용&#39;],
 [&#39;스위트&#39;],
 [&#39;스위트&#39;],
 [&#39;앞자리&#39;, ...</code></pre><br>

<h2 id="2-lda-토픽모델링">2. LDA 토픽모델링</h2>
<h3 id="21-bag-of-words">2.1 Bag of words</h3>
<p>LDA 토픽모델링을 하는데 활용할 수 있는 패키지가 하나는 아니겠지만, 가장 많이 활용하는 패키지는 Gensim일 것 같습니다. &quot;인간을 위한 토픽 모델링 (topic modelling for humans)&quot;라는 모토답게 공식 다큐멘테이션만 봐도 이해할 수 있도록 쉬운 문법으로 이루어져 있습니다. LDA 모델 뿐만 아니라 Word2vec 모델도 제공합니다(<a href="https://radimrehurek.com/gensim/auto_examples/tutorials/run_lda.html#">https://radimrehurek.com/gensim/auto_examples/tutorials/run_lda.html#</a>). Gensim을 설치한 후 필요한 패키지를 import 해줍니다.</p>
<pre><code class="language-python">from gensim.models.ldamodel import LdaModel
from gensim.models.callbacks import CoherenceMetric
from gensim import corpora
from gensim.models.callbacks import PerplexityMetric

import logging
logging.basicConfig(format=&#39;%(asctime)s : %(levelname)s : %(message)s&#39;, level=logging.INFO)</code></pre>
<br>

<p>첫번째로 Bag of words라고 하는 단어 가방을 만들기 위해 고유한 단어들의 사전을 만들어야 합니다. 사전에는 단어와 고유 번호 정보가 들어있습니다.</p>
<pre><code class="language-python">dictionary = corpora.Dictionary(processed_data)</code></pre>
<br>

<p>사전은 필터링을 할 수 있습니다. 너무 흔한 단어나 너무 독특한 단어는 제외하는 것입니다. 예를 들어 본 분석에서는 &quot;스위트홈&quot;과 같은 단어는 너무 자주 등장할텐데, 이렇게 흔한 단어는 의미가 없을 수 있죠. 반대로 빈도가 1인 단어가 포함되면 너무 많은 단어가 생겨 분석에 혼선을 줄 수 있습니다. 따라서 저는 빈도가 2 이상인 단어와 전체의 50%로 이상 차지하는 단어는 필터링했습니다.</p>
<pre><code class="language-python">dictionary.filter_extremes(no_below=2, no_above=0.5)</code></pre>
<br>

<p>이렇게 사전이 만들어지면 사전 속의 단어가 문장에서 몇 번 출현하는지 빈도를 세서 벡터화 합니다. 이걸 바로 bag of words라고 하고, 이렇게 구조화된 언어를 코퍼스라고 합니다. </p>
<pre><code class="language-python">corpus = [dictionary.doc2bow(text) for text in processed_data]</code></pre>
<br>

<h3 id="22-모델링">2.2 모델링</h3>
<p>다음은 본격적인 모델링입니다. 조정 가능한 파라미터가 굉장히 많고, 이걸 어떻게 설정하느냐에 따라 걸리는 시간이나 결과도 천차만별입니다. </p>
<pre><code class="language-phython">class gensim.models.ldamodel.LdaModel(corpus=None, num_topics=100, id2word=None, distributed=False, chunksize=2000, passes=1, update_every=1, alpha=&#39;symmetric&#39;, eta=None, decay=0.5, offset=1.0, eval_every=10, iterations=50, gamma_threshold=0.001, minimum_probability=0.01, random_state=None, ns_conf=None, minimum_phi_value=0.01, per_word_topics=False, callbacks=None, dtype=&lt;class &#39;numpy.float32&#39;&gt;)</code></pre>
<br>

<p>그중에서도 반드시 조정이 필요한 할 변수는 <code>num_topics</code>, <code>chunksize</code>, <code>passes</code>, <code>interations</code>, <code>eval_every</code>입니다. 각 변수를 간단하게 설명하자면, </p>
<p>📌 <code>num_topics</code>: 생성될 토픽의 개수
📌 <code>chunksize</code>: 한번의 트레이닝에 처리될 문서의 개수
📌 <code>passes</code>: 전체 코퍼스 트레이닝 횟수
📌 <code>interations</code>: 문서 당 반복 횟수</p>
<p>물론 이 파라미터를 다른 숫자로 여러번 해서 가장 정확도 높은 모델을 선택하는 것이 가장 좋습니다. 모델의 정확도는 토픽의 일관성으로도 볼 수 있을텐데, 토픽의 일관성은 Coherence를 보면 됩니다. 파라미터 <code>eval_every=1</code>로 설정하여, 매 pass마다 문서의 Convergence 평가하고, 대부분의 문서가 포함되는 pass를 선정할 수도 있습니다.</p>
<br>

<p>그리하여! 저는 아래와 같이 설정해 모델링 했습니다. <code>eval_every</code>는 시간이 오래 걸리므로 이번에는 <code>None</code>으로 설정하겠습니다. <code>alpha</code>, <code>eta</code>    는 모두 <code>auto</code>로 해줍니다.</p>
<pre><code class="language-python">num_topics = 5
chunksize = 2000
passes = 20
iterations = 400
eval_every = None

temp = dictionary[0]
id2word = dictionary.id2token

model = LdaModel(
    corpus=corpus,
    id2word=id2word,
    chunksize=chunksize,
    alpha=&#39;auto&#39;,
    eta=&#39;auto&#39;,
    iterations=iterations,
    num_topics=num_topics,
    passes=passes,
    eval_every=eval_every
)</code></pre>
<br>

<p>그리고 토픽이 어떻게 형성되었는지, Coherence는 적당하게 나왔는지 확인해보겠습니다. 하나의 토픽 당 20개의 단어가 기본으로 보여지지만, 이는 변경 가능합니다.</p>
<pre><code class="language-python">top_topics = model.top_topics(corpus) #, num_words=20)

# Average topic coherence is the sum of topic coherences of all topics, divided by the number of topics.
avg_topic_coherence = sum([t[1] for t in top_topics]) / num_topics
print(&#39;Average topic coherence: %.4f.&#39; % avg_topic_coherence)

from pprint import pprint
pprint(top_topics)</code></pre>
<p>👉 <strong>아웃풋</strong></p>
<pre><code>Average topic coherence: -5.5557.
[([(0.06853353, &#39;괴물&#39;),
   (0.04417699, &#39;송강&#39;),
   (0.037925135, &#39;생각&#39;),
   (0.036093775, &#39;현수&#39;),
   (0.029977145, &#39;트친&#39;),
   (0.02422037, &#39;얘기&#39;),
   (0.021502791, &#39;원작&#39;),
   (0.020061782, &#39;은혁&#39;),
   (0.015362978, &#39;장면&#39;),
   (0.0135506485, &#39;은유&#39;),
   (0.013274875, &#39;탐라&#39;),
   (0.01321878, &#39;아저씨&#39;),
   (0.012525685, &#39;인간&#39;),
   (0.012497223, &#39;지수&#39;),
   (0.011028776, &#39;소리&#39;),
   (0.010934056, &#39;세계관&#39;),
   (0.010197583, &#39;이야기&#39;),
   (0.008990835, &#39;상욱&#39;),
   (0.00896408, &#39;마음&#39;),
   (0.008290118, &#39;주인공&#39;)],
...</code></pre><br>

<h2 id="3-시각화">3. 시각화</h2>
<p>위의 결과만으로도 충분히 이해가 되긴 하지만, 자동으로 시각화를 할수도 있습니다. 먼저 pyLDAvis를 설치해주고 패키지를 import합니다.</p>
<pre><code class="language-python">import pickle
import pyLDAvis.gensim_models as gensimvis
import pyLDAvis
from gensim.models.coherencemodel import CoherenceModel
import matplotlib.pyplot as plt</code></pre>
<p>pyLDAvis가 Gensim 함수를 지원하기 때문에 코드는 간단합니다.</p>
<pre><code class="language-python">lda_visualization = gensimvis.prepare(model, corpus, dictionary, sort_topics=False)
pyLDAvis.save_html(lda_visualization, &#39;file_name.html&#39;)</code></pre>
<p>👉 <strong>아웃풋</strong>
그럼 아래와  같은 html 파일이 만들어집니다. 토픽 별로 단어와 빈도를 확인할 수 있습니다.</p>
<p><img src="https://images.velog.io/images/mare-solis/post/bee86b98-87ba-45be-a12a-7ce317277943/image.png" alt=""></p>
<br>

<h3 id="31-결과-해석">3.1. 결과 해석</h3>
<p>LDA를 활용한 토픽 모델링은 여기까지로, 이제 각각의 토픽이 무엇을 의미하는지 파악하는 것은 사람의 몫입니다. 토픽에 해당하는 단어들을 보고 왜 이 단어들이 하나의 토픽으로 뭉쳐졌을지 추론한 뒤, 토픽에 이름을 붙입니다. 즉, 라벨링을 하는 것이죠. 저는 아래와 같이 라벨링을 해봤습니다.</p>
<p>📌 <strong>토픽 1. 스토리</strong>
<img src="https://images.velog.io/images/mare-solis/post/3a453d19-2326-4827-97ad-1aad496c38a3/image.png" alt=""></p>
<p>📌 <strong>토픽 2. 시청 행태</strong>
<img src="https://images.velog.io/images/mare-solis/post/76d17816-af42-4f24-a0ef-16546b726825/image.png" alt=""></p>
<p>📌 <strong>토픽 3. 연출</strong>
<img src="https://images.velog.io/images/mare-solis/post/ccaa7932-afa6-49fd-b0ea-9a9730776374/image.png" alt=""></p>
<p>📌 <strong>토픽 4. 연관 작품</strong>
<img src="https://images.velog.io/images/mare-solis/post/d36400c0-795e-4e6c-8a26-e31208ab2147/image.png" alt=""></p>
<p>📌 <strong>토픽 5. 배우</strong>
<img src="https://images.velog.io/images/mare-solis/post/755e8cc5-6aac-4538-a5bf-cd6d6647176b/image.png" alt=""></p>
<p>저는 이 정도로 정리해봤는데요, 토픽 모델링의 특성 상 라벨링에는 다른 의견이 존재할 수도 있습니다. 하지만 라벨링을 할 때는 단어들을 보고 이들의 공통점을 최대한 잘 설명할 수 있는 토픽 이름을 지어야 합니다. 만약 여러 사람이 분석에 참여한다면 논의나 블라인드 라벨링 등의 방법을 통해 모두가 동의할만한 주제를 찾을 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[영화, 책을 부활시키다]]></title>
            <link>https://velog.io/@mare-solis/%EC%98%81%ED%99%94-%EC%B1%85%EC%9D%84-%EB%B6%80%ED%99%9C%EC%8B%9C%ED%82%A4%EB%8B%A4</link>
            <guid>https://velog.io/@mare-solis/%EC%98%81%ED%99%94-%EC%B1%85%EC%9D%84-%EB%B6%80%ED%99%9C%EC%8B%9C%ED%82%A4%EB%8B%A4</guid>
            <pubDate>Mon, 24 Jan 2022 18:53:56 GMT</pubDate>
            <description><![CDATA[<p>앞에서는 원작의 힘을 알아봤다면 이번엔 반대로 영화화의 힘을 알아볼 차례입니다. 한국에서는 이른바 &quot;스크린셀러&quot;라는 말이 등장할 정도로 영화로 인해 베스트셀러가 된 책들도 많은데요, 영화의 흥행은 과연 원작에 어떤 영향을 줄 수 있을까요? 이번에는 두가지 연구문제를 함께 알아보겠습니다.</p>
<blockquote>
<p>스크린셀러 (screen + bestseller): 영화의 흥행으로 인기를 얻게 된 원작 소설을 일컫는 신조어.</p>
</blockquote>
<p>✏️ <strong>연구 문제</strong></p>
<ol>
<li>원작 도서가 있는 영화는 그렇지 않은 영화보다 더 흥행할까?</li>
<li>원작 도서의 인기가 많을수록 영화가 더 흥행할까?</li>
</ol>
<p><strong>3. 영화가 개봉하면 원작 도서의 인기가 전보다 많아질까?</strong>
<strong>4. 영화의 흥행 성적이 좋을수록 원작 도서의 인기가 많아질까?</strong></p>
<hr>
<h3 id="데이터">데이터</h3>
<h3 id="분석">분석</h3>
<h4 id="1-t-test">1. t-test</h4>
<p>먼저 연구문제 3번, &quot;영화가 개봉하면 원작 도서의 인기가 전보다 많아질까?&quot;를 알아보기 위해 대출량 데이터를 영화 개봉 30일 전부터 개봉 전일까지, 그리고 영화 개봉일부터 30일까지로 나누었습니다. 이후 paired t-test를 통해 동일한 기간동안 의미있는 변화가 나타났는지 알 수 있습니다. </p>
<p>결과를 보니 영화 개봉 전 30일과 개봉 후 30일 간에는 뚜렷한 차이가 있네요 (t=-7.456, p&lt;.001). 개봉 후에 대출량이 유의미하게 증가한 것이 보입니다.</p>
<table>
<thead>
<tr>
<th></th>
<th>N</th>
<th align="right">Mean</th>
<th align="right">Standard deviation</th>
</tr>
</thead>
<tbody><tr>
<td>LOANS_PRE_30</td>
<td>132</td>
<td align="right">276.65</td>
<td align="right">467.877</td>
</tr>
<tr>
<td>LOANS_POST_30</td>
<td>132</td>
<td align="right">337.11</td>
<td align="right">508.308</td>
</tr>
<tr>
<td><br></td>
<td></td>
<td align="right"></td>
<td align="right"></td>
</tr>
</tbody></table>
<p>혹시 그렇다면 30일보다 긴 기간은 어떨까요? 영화 개봉 1년 전부터 30일 전까지, 그리고 영화 개봉 후 30일부터 1년까지의 기간을 비교해보니 여기에서도 확연한 차이가 보이네요 (t=-4.295, p&lt;.001). </p>
<table>
<thead>
<tr>
<th></th>
<th>N</th>
<th align="right">Mean</th>
<th align="right">Standard deviation</th>
</tr>
</thead>
<tbody><tr>
<td>LOANS_PRE_365</td>
<td>108</td>
<td align="right">1974.11</td>
<td align="right">3977.261</td>
</tr>
<tr>
<td>LOANS_POST_365</td>
<td>108</td>
<td align="right">2663.66</td>
<td align="right">4511.504</td>
</tr>
</tbody></table>
<br>

<p>두번의 t-test 결과, 영화 개봉을 전후로 책 대출량이 증가한다는 것을 알 수 있습니다. 즉, 일단 영화가 개봉하기만 해도 책 대출량이 증가한다는 의미로 볼  수 있겠네요.</p>
<p><img src="https://images.velog.io/images/mare-solis/post/9d382ce4-4aa2-4f1d-9b58-996b3d62f550/image.png" alt=""></p>
<h4 id="2-회귀분석">2. 회귀분석</h4>
<p>그렇다면 다음은 연구문제 4번, &quot;영화의 흥행 성적이 좋을수록 원작 도서의 인기가 많아질까?&quot;을 검증하기 위해 회귀분석을 진행하겠습니다. </p>
<p>변수는 책의 장르인 소설, 비소설, 만화로 나누어 책의 장르가 대출량에 미치는 영향력을 통제했습니다. 그 결과, 영화의 관객 수는 대출량에 매우 큰 영향을 미치는 것으로 나타났습니다. 영화의 관객 수가 많을수록 대출량도 많아집니다. 이러한 효과는 30일 단기뿐만 아니라 1년 장기적으로도 마찬가지였습니다. </p>
<p><img src="https://images.velog.io/images/mare-solis/post/adb22c83-d023-49a5-a7b1-0466b159ea75/image.png" alt=""></p>
<h3 id="결론">결론</h3>
<p>&quot;스크린셀러&quot;는 허튼 말이 아니었네요! 이번 분석에서는 영화화의 강력한 힘을 제대로 알 수 있는 결과를 얻었습니다. 영화 개봉만으로도 대출량은 전에 비해 증가하는 효과가 있고, 특히 관객 수가 많을수록 대출량도 많아집니다. 이러한 효과를 나타내는 용어도 있습니다. 상호 스필오버 효과 (reciprocal spillover effect)입니다. 1편에서 스필오버 효과에 대해 설명했었는데요, 전에 나온 상품 때문에 이후에 나온 상품이 후광효과를 누린다는 것이었죠. 상호 스필오버 효과는 반대로 이후에 나온 상품 때문에 이전의 상품이 재주목 받는다는 이론입니다. 영화로 인해 다시 부활하는 원작 도서의 경우와 딱 맞아 떨어지죠!</p>
<h3 id="📝-연구-끝">📝 연구 끝!</h3>
<p>자, 이번 연구는 여기까지입니다. 지금까지의 분석을 바탕으로 한 최종 결론은 이렇게 내릴 수 있겠네요.</p>
<blockquote>
<ol>
<li>책을 바탕으로 한 영화를 만들자.</li>
<li>책의 인기보다 더 중요한 게 있을 수 있다.</li>
<li>영화는 책의 꺼진 생명의 불씨도 살릴 수 있다.</li>
</ol>
</blockquote>
<p>제가 좋아하는 책 중에서도 영화화되면 좋겠다 싶은 책들이 많은데요, 제작자님들 뭐하십니까. 만들어주십쇼! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[원작이 인기있으면 영화도 흥행할까?]]></title>
            <link>https://velog.io/@mare-solis/%EC%9B%90%EC%9E%91%EC%9D%B4-%EC%9D%B8%EA%B8%B0%EC%9E%88%EC%9C%BC%EB%A9%B4-%EC%98%81%ED%99%94%EB%8F%84-%ED%9D%A5%ED%96%89%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@mare-solis/%EC%9B%90%EC%9E%91%EC%9D%B4-%EC%9D%B8%EA%B8%B0%EC%9E%88%EC%9C%BC%EB%A9%B4-%EC%98%81%ED%99%94%EB%8F%84-%ED%9D%A5%ED%96%89%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Mon, 24 Jan 2022 16:01:28 GMT</pubDate>
            <description><![CDATA[<p>지난 편에서는 원작이 있는 영화는 관객 수가 더 많다는 결과를 얻었습니다. 그렇다면 원작의 인기와 영화의 흥행도 상관이 있을까요? 이번에는 원작이 본래 가진 힘에 더 집중해보도록 하겠습니다. 
<br></p>
<p>✏️ <strong>연구 문제</strong></p>
<ol>
<li>원작 도서가 있는 영화는 그렇지 않은 영화보다 더 흥행할까?</li>
</ol>
<p><strong>2. 원작 도서의 인기가 많을수록 영화가 더 흥행할까?</strong></p>
<hr>
<h3 id="데이터">데이터</h3>
<h4 id="1-영화-데이터">1. 영화 데이터</h4>
<p>지난번에는 도서가 한국에서 출간되었는지 여부는 보지 않고 영화가 책을 원작으로 했는지 아닌지만 구분했습니다. 하지만 이번에는 분석을 위해 도서 데이터가 반드시 있어야 하기 때문에 한국에서 출간된 적이 있는 도서를 영화화 한 작품만 샘플링 되었습니다. </p>
<h4 id="2-도서-데이터">2. 도서 데이터</h4>
<p>일반적으로 영화의 흥행하면 수익이나 관객 수로 성과를 측정하고, 책하면 판매량을 떠올릴텐데요, 영화 데이터를 영화진흥위원회에서 제공하는 것과 달리, 안타깝게도 책 판매량 데이터는 제공하는 곳이 없습니다🥲 따라서 제가 떠올린 방법은 도서 대출 데이터를 활용하는 것입니다. 국립중앙도서관 빅데이터 센터에서 운영하는 도서관 정보나루 (<a href="https://www.data4library.kr/)%EC%97%90%EC%84%9C">https://www.data4library.kr/)에서</a> 전국의 공공 도서관 대출 정보를 제공하기 때문이죠! 따라서 책의 인기를 측정하기 위한 척도로는 책 판매량을 사용했습니다. </p>
<h3 id="분석">분석</h3>
<h4 id="0-분석에-들어가기-전">0. 분석에 들어가기 전</h4>
<p>이번에는 영화 관객 수에 영향을 미치는 요소들을 조절 변수로 추가해 회귀분석을 진행할 것입니다. 영화 관객 수에 영향을 미치는 요소로는 장르, 국적, 관람가, 속편 여부 (해당 영화가 다른 영화의 속편인지)가 있습니다 <span style="color:grey">(이 변수들은 영화 관객 수와의 상관분석을 통해 선정되었습니다)</span>. 한편, 스크린 수는 영화 관객 수에 미치는 영향이 매우 크지만 두개의 변수가 독립적이지 않다고 판단하여 제외되었습니다.</p>
<h4 id="1-회귀분석">1. 회귀분석</h4>
<p>우리가 이번에 알아보고자 하는 것은 영화와 상관없이 책이 기존에 가지고 있던 인기가 영화의 흥행에 어떤 영향을 미치는지 보는 것입니다. 따라서 독립변수가 되는 책의 대출량은 영화 개봉에 최소한으로 영향을 받았어야 겠지요. 저는 이 기간을 영화 개봉 1년 전 - 30일 전 까지로 잡았습니다. 영화 개봉 30일 전이면 그래도 영화 개봉으로 인해 책의 대출량이 증가하는, 역의 관계를 배제할 수 있다고 생각했기 때문입니다. </p>
<p>회귀 분석 결과를 보면, 대출량의 Coefficient는 거의 0에 가까운 것을 알 수 있습니다. 그러니 당연히 모델의 R<sup>2</sup> 증가량도 유의하지 않습니다. 즉, 이 기간의 대출량은 관객 수에 유의미한 영향을 미치지 않습니다. 첫째주 관객 수와 최종 관객 수 모두에 말이죠. 
<img src="https://images.velog.io/images/mare-solis/post/8bbe37a0-771f-4d29-b149-e1bcc9358d85/image.png" alt=""></p>
<p>그렇다면 영화 개봉 30일 전부터 개봉 전일까지의 대출량도 한번 보도록 합시다. 이대로 끝내긴 아쉬우니까요. 이 기간의 대출량은 영화 개봉에 아주 큰 영향을 받았을 것입니다. 영화 홍보가 보통 4주 정도 진행되기 때문입니다. 이 때 대출량이 많았다면 영화의 흥행 성적 역시 좋지 않았을까요?</p>
<p>결론은 아닙니다. 역시나 Coefficient는 0에 가까우며, R<sup>2</sup> 역시 유의하지 않습니다. </p>
<p><img src="https://images.velog.io/images/mare-solis/post/9e43fa29-b04c-4ed1-a568-8e4bdf56a84a/image.png" alt=""></p>
<h3 id="결론">결론</h3>
<p>자, 그렇다면 왜 이런 결과가 나왔을까요? 상식적으로 책의 인기가 많으면 영화의 흥행에도 도움이 될 것 같고, 심지어 애초에 책이 인기가 많았으니까 영화화가 되었을 수도 있는데 말이죠. </p>
<p>우선 이렇게 해석해 볼 수 있을 것 같습니다. 지난 편에서 나타났듯 책을 원작으로 한 영화는 미국 영화가 굉장히 많았습니다. 그런데 미국에서 책이 베스트셀러였어서 영화화가 진행되었다고 한들, 그 책이 반드시 한국에서도 인기있었다는 법은 없죠. 여기서는 한국 데이터로 분석이 진행되다 보니 이런 사례가 많았을 수 있습니다.</p>
<p>또는 전편의 결과를 같이 놓고 보면 이런 해석도 가능합니다. 사실 책이 원작이라는 것 자체가 중요할 뿐, 책의 인기는 별로 상관이 없다는 거죠. 책의 혹여 많은 사람의 주목을 받지 못했을지라도 책이 원작이라는 것 자체에서 얻을 수 있는 이점도 많습니다. 1편에서 언급했듯, 사람들은 <strong>&quot;영화화할 정도면 스토리가 좋나보네!&quot;</strong> 하는 경향이 있기 때문이죠. 실제로 제작자의 관점에서 보더라도 스토리가 좋으니까 영화화를 결정했을 것이고요. 이렇게 원작이 있다는 것 자체에서 드는 신뢰감이 있기 때문에 원작의 인기는 별로 중요하지 않을 수 있습니다. 그러니까 인기가 많았든 적었든, 신선하고 좋은 스토리가 많이 발굴되면 좋겠네요!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[원작이 있는 영화는 더 흥행할까?]]></title>
            <link>https://velog.io/@mare-solis/%EC%9B%90%EC%9E%91%EC%9D%B4-%EC%9E%88%EB%8A%94-%EC%98%81%ED%99%94%EB%8A%94-%EB%8D%94-%ED%9D%A5%ED%96%89%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@mare-solis/%EC%9B%90%EC%9E%91%EC%9D%B4-%EC%9E%88%EB%8A%94-%EC%98%81%ED%99%94%EB%8A%94-%EB%8D%94-%ED%9D%A5%ED%96%89%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Mon, 24 Jan 2022 13:37:59 GMT</pubDate>
            <description><![CDATA[<p>분석에 들어가기 전에 연구문제를 다시 정립해보도록 하겠습니다. 이번 편에서 알고싶은 것은 원작, 그 중에서도 책이 영화화에 끼치는 영향이므로, 첫번째 연구문제는 &quot;원작 도서가 있는 영화는 그렇지 않은 영화보다 더 흥행할까?&quot;입니다.
<br></p>
<p>✏️ <strong>연구 문제</strong>
<strong>1. 원작 도서가 있는 영화는 그렇지 않은 영화보다 더 흥행할까?</strong></p>
<hr>
<h3 id="데이터">데이터</h3>
<h4 id="1-영화-데이터">1. 영화 데이터</h4>
<p>연구를 위해서는 데이터를 수집해야겠죠? 영화에 관련된 데이터는 영화진흥위원회에서 운영하는 전산망에서 쉽게 구할 수 있습니다 (<a href="https://www.kobis.or.kr/">https://www.kobis.or.kr/</a>). 저는 2015년부터 2018년까지 한국에서 개봉한 영화를 대상으로 했고, 그중에서 최대 상영관이 100개 미만이었던 영화는 제외했습니다. 그 결과, 1072개의 영화가 샘플링되었습니다. 영화 제목, 개봉일, 장르, 국적, 관람가, 첫째주 관객 수, (누적) 관객 수, 상영관 수 등의 데이터가 수집되었습니다.</p>
<h3 id="분석">분석</h3>
<h4 id="0-분석에-들어가기-전">0. 분석에 들어가기 전</h4>
<p>연구문제를 위한 분석에 들어가기 전에, 수집된 데이터를 먼저 살펴보겠습니다. 1072개의 영화 중에서는 미국 영화 421개로 가장 많았고, 그 뒤를 한국, 일본 영화가 따랐습니다. 393개의 영화에 원작이 있었는데요, 원작은 책부터 연극, 게임, 다른 영화에 이르기까지 다양했습니다 <span style="color:grey">(&lt;터닝메카드&gt;와 같이 장난감을 원작으로 한 영화도 있습니다...!)</span>. 그 중 273개가 책을 원작으로 했습니다. 책도 장르가 다양했는데요, 소설이 가장 많았고, 만화, 논픽션 (수필, 전기, 회고록, 르포르타주 등)이 뒤를 이었습니다. 미국 영화 중 책을 원작으로 한 영화는 131개로 31.1% 였던 반면, 한국 영화 중 책을 원작으로 한 영화는 42개로 13.3%에 그쳤습니다. 
<img src="https://images.velog.io/images/mare-solis/post/54b7f3fd-f27d-453b-9db7-dcf61c669196/image.png" alt=""></p>
<br>

<h4 id="1-t-test">1. t-test</h4>
<p>첫번째 연구문제를 위해 먼저 &#39;책&#39;이라는 변수를 만들어 원작 도서가 있는 영화는 1, 그렇지 않은 영화는 0으로 코딩합니다. 원작 도서가 있는지의 여부는 일일이 찾아보는 수밖에 없습니다 <span style='color:grey'>(위에서 상영관 100개 미만인 영화는 제외하길 잘 했네요 🥲)</span>. 외국 영화는 대부분 원작자를 표시하고 있기 때문에 imdb 페이지의 제작진 항목을 살펴보는 것이 도움이 됩니다. </p>
<p>첫번째 연구문제는 &#39;책&#39;과 &#39;관객 수&#39; 두 변수 간의 t-test를 통해 결과를 볼 수 있습니다. 관객 수는 첫째 주 관객 수와 전체 관객수를 따로 보겠습니다. 그 이유는 전편에서 설명한 스필오버 효과를 더 잘 보기 위함입니다. 영화에 대한 정보가 아직 많지 않은 첫째주에는 책이라는 정보가 있을 경우 큰 견인 효과가 있을 것이라고 가정할 수 있습니다. 하지만 효과가 최종 관객 수에 미치는 영향력은 떨어질 수도 있을 것입니다. </p>
<p>우선 첫째주부터 볼까요? 예상과 같이 첫째주에는 책을 원작으로 한 영화가 그렇지 않은 영화보다 관객 수가 많은 것으로 나타났습니다 (t=2.582, p=.01).</p>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">BOOK_MOVIE</th>
<th align="center">N</th>
<th align="right">Mean</th>
<th align="right">Standard deviation</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1st_ADM</td>
<td align="center">1</td>
<td align="center">273</td>
<td align="right">541553.51</td>
<td align="right">1014267.528</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">0</td>
<td align="center">799</td>
<td align="right">370267.64</td>
<td align="right">710843.376</td>
</tr>
</tbody></table>
<br>

<p>최종 관객 수도 봅시다. 책을 원작으로 한 영화는 그렇지 않은 영화보다 더 많은 최종 관객 수를 보였네요 (t=2.054) t-value는 첫째주 관객 수 결과 비해 낮고 p-value는 더 높긴 하지만 그래도 유의한 모델임이 검증되었습니다. </p>
<table>
<thead>
<tr>
<th align="left"></th>
<th align="center">BOOK_MOVIE</th>
<th align="right">N</th>
<th align="right">Mean</th>
<th align="right">Standard deviation</th>
</tr>
</thead>
<tbody><tr>
<td align="left">TOTAL_ADM</td>
<td align="center">1</td>
<td align="right">273</td>
<td align="right">993793.84</td>
<td align="right">2066343.151</td>
</tr>
<tr>
<td align="left"></td>
<td align="center">0</td>
<td align="right">799</td>
<td align="right">712426.19</td>
<td align="right">1581399.751</td>
</tr>
</tbody></table>
<br>

<h3 id="결론">결론</h3>
<p><img src="https://images.velog.io/images/mare-solis/post/12701e38-5180-4282-8e0d-c3a20ba884e0/image.png" alt="">
즉, 첫번째 연구 문제에 대한 답은 <strong>&quot;그렇다!</strong>&quot;가 되겠네요. 책을 바탕으로 한 영화는 첫째 주 관객 수도, 최종 관객 수도 더 많았습니다. 특히 첫째주뿐만 아니라 최종 관객 수에서도 우위를 보였다는 점에서 책을 영화화 하는 것이 마케팅 효과 이상의 흥행성를 보여주는 것 같습니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[할리우드에는 책 스카우트 팀이 있다고?]]></title>
            <link>https://velog.io/@mare-solis/%ED%95%A0%EB%A6%AC%EC%9A%B0%EB%93%9C%EC%97%90%EB%8A%94-%EC%B1%85-%EC%8A%A4%EC%B9%B4%EC%9A%B0%ED%8A%B8-%ED%8C%80%EC%9D%B4-%EC%9E%88%EB%8B%A4%EA%B3%A0</link>
            <guid>https://velog.io/@mare-solis/%ED%95%A0%EB%A6%AC%EC%9A%B0%EB%93%9C%EC%97%90%EB%8A%94-%EC%B1%85-%EC%8A%A4%EC%B9%B4%EC%9A%B0%ED%8A%B8-%ED%8C%80%EC%9D%B4-%EC%9E%88%EB%8B%A4%EA%B3%A0</guid>
            <pubDate>Thu, 20 Jan 2022 15:58:37 GMT</pubDate>
            <description><![CDATA[<p>&lt;반지의 제왕&gt;과 &lt;해리 포터&gt; 같은 장대한 판타지부터 설렘 치사량의 &lt;콜 미 바이 유어 네임&gt;, &lt;내가 사랑했던 모든 남자들에게&gt;, 그리고 진한 감동을 선사하는 &lt;라이프 오브 파이&gt;, &lt;원더&gt;에 이르기까지, 우리가 사랑한 영화들 중에는 책을 바탕으로 한 영화가 많죠. 내가 좋아하는 책이 영화화된다고 하면 제작 관련 소식을 목 빠지게 기다리고, 읽지 않은 책이라도 하더라도 괜히 원작이 있다고 하면 기대가 되기 마련입니다. 이번 편에서는 실제 사례를 통해 영화화의 힘을 떠올려보겠습니다.</p>
<hr>
<br>
성공한 책은 영화 관계자에게 있어 가장 매력적인 시나리오임에 틀림없습니다. 관계자만 읽을 수 있는 여타 시나리오와 달리, 이미 대중에 공개되어 그들의 반응을 확인할 수 있기 때문입니다. 베스트셀러를 두고 영화사들 간의 치열한 물밑 전쟁이 벌어지기도 합니다. 혹은 아직 베스트셀러가 되지 않았더라도 더 좋은 책을 누구보다 더 빨리 찾아내기 위한 "책 스카우트" 팀은 할리우드 스튜디오에게 이제 필수라고 하죠. LA 타임스에 따르면, 최근 코로나로 인해 콘텐츠 소비량이 늘며 책 영화화에 대한 수요가 증가했다고 합니다. 폭증하는 콘텐츠 수요를 감당하기에 책이 든든한 원천이 되어주기 때문일 것입니다.

<p><a href="https://www.hollywoodreporter.com/lifestyle/lifestyle-news/next-gone-girl-meet-6-794580/"><img src="https://images.velog.io/images/mare-solis/post/f716e02b-b958-4ea6-9188-9167310f4685/thr_book_scouts%20(1).jpeg" alt=""></a></p>
<h5 id="span-stylecolorgraycenter할리우드의-책-스카우트-팀-사진을-누르면-관련-기사로-이동합니다centerspan"><span style="color:gray"><center>할리우드의 책 스카우트 팀. 사진을 누르면 관련 기사로 이동합니다.</center></span></h5>
<br>
특히, 책을 원작으로 한 영화 중에는 가성비 갑 영화들이 많습니다. <나를 찾아줘>는 6천만 달러의 제작비로 3억 6천만 달러의 수익을 거뒀고, <안녕, 헤이즐>은 1천6백만 달러의 제작비로 3억 7백만 달러를, <헝거 게임>은 7천8백만 달러의 제작비로 6억 9천만 달러에 달하는 수익을 냈습니다. 

<p><img src="https://images.velog.io/images/mare-solis/post/82aae48b-f7d5-4062-b4aa-e6523829a3ad/%E1%84%83%E1%85%A1%E1%84%8B%E1%85%AE%E1%86%AB%E1%84%85%E1%85%A9%E1%84%83%E1%85%B3.jpeg" alt=""></p>
<br>
한국도 할리우드만큼은 아니지만 책을 영화화하여 좋은 성적을 거둔 사례가 있었습니다. 종이책은 아니지만 웹툰을 원작으로 한 <신과 함께>가 천만 관객을 모으며 한국형 블록버스터를 선보였는데, 아마 원작이 없는 시나리오였다면 영화로 만들어질 수조차 없었을지도 모를 일입니다. 제작비가 많이 드는 영화일수록 위험부담을 줄이고자 안전한 선택을 하기 때문에, 같은 제작비라면 이미 정립된 흥행공식이 있는, 예컨대 <베테랑>이나 <암살> 같은 영화를 만드는 것이 보다 현명한 판단일 수 있기 때문이죠. 하지만 <신과 함께>는 이미 웹툰으로서 스토리의 흥행 가능성을 보여준 바 있어 제작자에게 더 나은 선택지를 제공한 셈입니다. <신과 함께>는 한국 영화 최초로 시리즈가 쌍으로 천만 관객을 달성하기도 했습니다.

<p><img src="https://images.velog.io/images/mare-solis/post/f5a624a2-1d68-480b-8b8e-7704794596ab/%E1%84%89%E1%85%B5%E1%86%AB%E1%84%80%E1%85%AA%E1%84%92%E1%85%A1%E1%86%B7%E1%84%81%E1%85%A6_%E1%84%8B%E1%85%B5%E1%86%AB%E1%84%80%E1%85%AA%E1%84%8B%E1%85%A7%E1%86%AB_1920x1080.jpeg" alt=""></p>
<br>
마케팅에서는 영화화를 브랜드 연장(Brand extension) 또는 상품 연장(Product extension)으로 보기도 합니다. 네이버라는 포털 서비스가 네이버 블로그, 네이버 페이, 네이버 지도 등의 서비스로 확장되듯, 책이 영화로 확장된다는 것입니다. 이렇게 기존의 브랜드가 확장할 경우, 이미 구축해놓은 브랜드 이미지, 지식, 태도, 경험 등을 그대로 가져올 수 있다는 이점이 있습니다. 우리 기억은 한 가지 노드(Node)가 형성되면 새로운 정보가 들어왔을 때 연관성이 있는 기존 노드에 붙여가며 구조화됩니다. 이를 연상 기억 장치(Associative Network Memory Model)라고 하는데요, 때문에 네이버 페이가 새로 나왔을 때, "네이버 포털 서비스를 사용해 보니 네이버는 편리하고 신뢰할 수 있지. 네이버 페이도 그럴 거야"라고 생각하는 것입니다. 이것을 스필오버 효과(Spillover Effect)라고 합니다.

<p><img src="https://images.velog.io/images/mare-solis/post/adc4c2f0-9abc-415c-853e-b36d4e40902c/50-Figure3.1-1.png" alt=""></p>
<h5 id="span-stylecolorgraycenter연상-기억-장치의-예-뉴욕하면-연상되는-다양한-정보들이-있습니다centerspan"><span style="color:gray"><center>연상 기억 장치의 예. 뉴욕하면 연상되는 다양한 정보들이 있습니다.</center></span></h5>
<br>
스필오버 효과를 증대하기 위해서는 신호(Cue)를 사용합니다. 위에서 예시로 든 네이버가 서비스에 모두 네이버라는 이름을 동일하게 유지한 것도 기존 브랜드의 이미지를 효과적으로 가져오기 위한 신호로, 가장 흔하게 쓰이는 기법입니다. 더 나아가 애플의 아이폰 12, 13처럼 숫자만 증가시키는 경우도 있습니다. 이전 브랜드가 가진 이미지, 사용자의 경험과 같은 기억을 더 쉽게 불러오기 위한 것이죠. 이름이 아니더라도 동일한 광고 음악, 모델 등도 좋은 신호가 될 수 있습니다. 아이폰이 비슷비슷한 디자인을 유지하는 것 역시 스필오버 효과를 극대화하기 위한 신호라고 볼 수 있습니다.

<p><img src="https://images.velog.io/images/mare-solis/post/13b5f3ea-f3af-418c-bc73-3bf3da75bafe/iPhone12Pro-color-lineup-5up.gif" alt=""></p>
<br>
특히나 팬층이 두꺼운 브랜드의 경우, 스필오버 효과가 막강한 역할을 합니다. 책의 경우에도 팬층이 두꺼운 브랜드 중 하나입니다. 가장 쉽게 생각할 수 있는 책의 팬층은 마블, DC 코믹스의 팬일 것입니다.  슈퍼 히어로는 이들의 열렬한 지지를 바탕으로 너드의 전유물에서 대중문화의 대명사로 우뚝 설 수 있었습니다. <반지의 제왕>이나 <왕좌의 게임>도 비슷한 예입니다. 또 떠올릴 수 있는 강력한 팬층은 10대 여성입니다. 이들의 영향력은 <트와일라잇>이라는 신드롬을 만들어냈고, 이후에도 <퍼시 잭슨>, <헝거게임>, <메이즈러너>와 같은 트렌드로 이어졌습니다. 최근에는 <키싱 부스>, <애프터>와 같은 웹 소설이 영화화되기도 했죠. 또 미국에서 큰 영향력을 행사하는 집단은 4, 50대 주부들입니다. 북클럽을 결성하여 독서량이 많고, 입소문이 빠르게 퍼지며, 구매력도 있기 때문입니다. 북클럽을 운영하는 배우 리즈 위더스푼은 자신이 선정한 책을 직접 영화화하며 제작자로 우뚝 섰습니다.

<p><img src="https://images.velog.io/images/mare-solis/post/caed8963-bf90-4b89-821e-c9411f552d14/nicole-kidman-centre-is-featured-in-the-david-e-kelley-created-series-alongside-the-likes-reese-witherspoon-3rd-left-shailene-woodley-right-laura-dern-left-and-zoe-kravitz-2nd-right-.jpeg" alt=""></p>
<h5 id="span-stylecolorgraycenter동명의-소설을-원작으로-한-hbo의-미드-빅-리틀-라이즈-리즈-위더스푼이-제작하고-출연했습니다centerspan"><span style="color:gray"><center>동명의 소설을 원작으로 한 HBO의 미드 &lt;빅 리틀 라이즈&gt;. 리즈 위더스푼이 제작하고 출연했습니다.</center></span></h5>
<br>
그런데 브랜드 연장에 관한 흥미로운 견해 중 하나는, 스필오버 효과가 없더라도 소비자는 브랜드 연장 자체를 긍정적으로 본다는 것입니다. 기존 브랜드에 대한 경험이나 이미지가 없어도 해당 브랜드가 연장 브랜드 또는 상품을 가지고 있을 경우 이를 좋은 퀄리티에 대한 증거라고 생각하는 경향이 있습니다. 서두에서 말했듯 영화가 원작이 있다고 하면 "뭔진 몰라도 재밌으니까 영화화했겠지", 또는 "원작이 있으니까 스토리가 탄탄하겠다" 하는 생각이 많은 사람들에게서 나타난다는 것입니다.

<p><img src="https://images.velog.io/images/mare-solis/post/41357c44-02b1-4d8d-afaf-a5105467edce/SE-3e07ee36-80c3-4865-bf2c-912734171712.png" alt=""></p>
<h5 id="span-stylecolorgraycenter한국에서-베스트셀러가-되지-못했지만-북미-베스트셀러라고-홍보하기도-합니다br-그것만으로도-충분히-신뢰도가-높아질-수-있기-때문이죠centerspan"><span style="color:gray"><center>한국에서 베스트셀러가 되지 못했지만 &quot;북미 베스트셀러&quot;라고 홍보하기도 합니다.<br> 그것만으로도 충분히 신뢰도가 높아질 수 있기 때문이죠.</center></span></h5>
<br>
이렇듯, 원작을 영화화하는 것은 안전하다는 제작자의 믿음은 경험적으로는 어느 정도 증명된 듯합니다. 하지만, 이 믿음을 통계적으로도 증명할 수 있을까요? 다음 편에서는 본격적인 분석을 진행해 보도록 하겠습니다.]]></description>
        </item>
    </channel>
</rss>