Python Programming
  • Home
  • Intro
    • History & Background
    • Python Setup
  • Exercises
    • Chapter 5: Lists, Tuples, Sets
    • Chapter 6: Strings
    • Chapter 7: Dictionaries
    • Chapter 8: Control flow
    • Chapter 9: Functions
    • Chapter 14: Exceptions
    • Chapter 15: Classes
  • Exploring Data
    • NumPy & pandas
    • Inspecting data
    • Visualization
  • Library System
  • Netflix Movie Analysis
    • Notes
    • Project-Native
    • Project-pandas
  • References
    • QPB Part 1
    • QPB Part 2
    • QPB Part 3
    • QPB Part 4

On this page

  • Cleaned Data
  • Data Wrangling
    • subsetting
    • query()
    • sort_values()
    • assign()
    • groupby(), agg(), apply()
  • Exploratory Data Analysis (EDA)
    • 기본통계
    • 시청자 분석
      • 가장 활발한 시청자 TOP 5
      • 시청자별 통계
    • 작품별 분석
    • 장르 분석
    • 시간대 분석
    • 평점 분석
    • 종합 리포트
  • 분석 코드를 모듈로 재사용하기
    • 1. 모듈 불러오기
    • 2. 함수 스타일로 사용하기
    • 3. 클래스 스타일로 사용하기
    • 4. 종합 리포트

Project: Netflix Prize Data

Load packages
# numerical calculation & data frames
import numpy as np
import pandas as pd

# visualization
import matplotlib.pyplot as plt
import seaborn as sns
import seaborn.objects as so

# pandas options
pd.set_option('mode.copy_on_write', True)  # pandas 2.0
pd.options.display.float_format = '{:.3f}'.format  # pd.reset_option('display.float_format')
# pd.options.display.max_rows = 7  # max number of rows to display

# NumPy options
np.set_printoptions(precision = 2, suppress=True)  # suppress scientific notation
np.set_printoptions(legacy='1.25')  # numpy 1.25 표현 방식


# matplotlib options
from matplotlib import style
theme_dict = {**style.library['ggplot'], "grid.linestyle": ":", 'axes.facecolor': 'white', 'grid.color': '.6',}
so.Plot.config.theme.update(theme_dict)

# theme_dict = {**sns.axes_style("whitegrid"), "grid.linestyle": ":"}
# so.Plot.config.theme.update(theme_dict)

# For high resolution display
import matplotlib_inline
matplotlib_inline.backend_inline.set_matplotlib_formats("retina")

Cleaned Data

File: netflix_ratings.parquet

netflix = pd.read_parquet("data/netflix_ratings_titles.parquet")
netflix.info()
<class 'pandas.DataFrame'>
RangeIndex: 1246558 entries, 0 to 1246557
Data columns (total 17 columns):
 #   Column        Non-Null Count    Dtype         
---  ------        --------------    -----         
 0   viewer_id     1246558 non-null  Int32         
 1   rating        1246558 non-null  Int8          
 2   watch_date    1246558 non-null  datetime64[ns]
 3   release_year  1246558 non-null  int64         
 4   title         1246558 non-null  str           
 5   record_id     1246558 non-null  str           
 6   media_type    1246558 non-null  str           
 7   director      1245701 non-null  str           
 8   cast          1246558 non-null  str           
 9   country       1246109 non-null  str           
 10  date_added    1246558 non-null  str           
 11  MPAA_rating   1246558 non-null  str           
 12  duration      1246558 non-null  str           
 13  genre         1246558 non-null  object        
 14  description   1246558 non-null  str           
 15  runtime       1245701 non-null  Int32         
 16  num_episodes  857 non-null      Int32         
dtypes: Int32(3), Int8(1), datetime64[ns](1), int64(1), object(1), str(10)
memory usage: 593.3+ MB
netflix.head(3)
viewer_id rating watch_date release_year title record_id media_type director cast country date_added MPAA_rating duration genre description runtime num_episodes
0 2191540 4 2004-06-23 2004 50 First Dates s6019 Movie Peter Segal Adam Sandler, Drew Barrymore, Rob Schneider, S... United States December 1, 2020 PG-13 99 min [Comedies, Romantic Movies] After falling for a pretty art teacher who has... 99 <NA>
1 998702 2 2005-08-26 2002 Men in Black II s7444 Movie Barry Sonnenfeld Tommy Lee Jones, Will Smith, Rip Torn, Lara Fl... United States October 1, 2019 PG-13 88 min [Action & Adventure, Comedies, Sci-Fi & Fantasy] Will Smith and Tommy Lee Jones reprise their r... 88 <NA>
2 1914163 4 2005-03-21 2004 50 First Dates s6019 Movie Peter Segal Adam Sandler, Drew Barrymore, Rob Schneider, S... United States December 1, 2020 PG-13 99 min [Comedies, Romantic Movies] After falling for a pretty art teacher who has... 99 <NA>

Data Wrangling

참고서: Python for Data Analysis (3e) by Wes McKinney (파이썬 라이브러리를 활용한 데이터 분석)

대략 다음과 같은 transform들을 조합하여 분석에 필요한 상태로 바꿈

  • 변수들(열)과 관측치(행)를 선택: subsetting
  • 조건에 맞는 부분(관측치, 행)만 필터링: query()
  • 조건에 맞도록 행을 재정렬: sort_values()
  • 변수들과 함수들을 이용하여 새로운 변수를 생성: assign()
  • 카테고리별로 나뉘어진 데이터에 대한 통계치를 생성: groupby(), agg(), apply()
netflix_1990 = (
    netflix
    .loc[:, ["title", "rating", "watch_date", "release_year"]]  # 특정 열을 선택
    .query("release_year >= 1990")                              # 조건에 맞는 행만 필터링
    .assign(                                                    # 새로운 열/변수를 생성
        decade=lambda x: x["release_year"] // 10 * 10,          # 10년 단위
        weekday=lambda x: x["watch_date"].dt.day_name().str[:3] # 요일
    )
    .sort_values("release_year")                                # 조건에 따라 행을 정렬
)
netflix_1990
title rating watch_date release_year decade weekday
406248 Rocky V 3 2004-02-20 1990 1990 Fri
847433 Rocky V 1 2004-02-13 1990 1990 Fri
268823 Rocky V 2 2005-05-18 1990 1990 Wed
... ... ... ... ... ... ...
476261 King's Ransom 2 2005-08-31 2005 2000 Wed
476074 Coach Carter 2 2005-09-14 2005 2000 Wed
109441 The Amityville Horror 3 2005-11-07 2005 2000 Mon

1149195 rows × 6 columns

표시줄 수 지정
# max number of rows to display
pd.options.display.max_rows = 6

# reset
pd.options.display.max_rows = 0

subsetting

변수들(열)과 관측치(행)를 선택

  • Bracket []
  • Dot-notation .
  • iloc, loc
# Bracket [strings]
netflix[["title", "rating"]]
title rating
0 50 First Dates 4
1 Men in Black II 2
2 50 First Dates 4
... ... ...
1246555 Bad Boys II 3
1246556 Something's Gotta Give 4
1246557 The American President 5

1246558 rows × 2 columns

# Bracket [slicing]
netflix[:3]
viewer_id rating watch_date release_year title record_id media_type director cast country date_added MPAA_rating duration genre description runtime num_episodes
0 2191540 4 2004-06-23 2004 50 First Dates s6019 Movie Peter Segal Adam Sandler, Drew Barrymore, Rob Schneider, S... United States December 1, 2020 PG-13 99 min [Comedies, Romantic Movies] After falling for a pretty art teacher who has... 99 <NA>
1 998702 2 2005-08-26 2002 Men in Black II s7444 Movie Barry Sonnenfeld Tommy Lee Jones, Will Smith, Rip Torn, Lara Fl... United States October 1, 2019 PG-13 88 min [Action & Adventure, Comedies, Sci-Fi & Fantasy] Will Smith and Tommy Lee Jones reprise their r... 88 <NA>
2 1914163 4 2005-03-21 2004 50 First Dates s6019 Movie Peter Segal Adam Sandler, Drew Barrymore, Rob Schneider, S... United States December 1, 2020 PG-13 99 min [Comedies, Romantic Movies] After falling for a pretty art teacher who has... 99 <NA>
# dot-notation
netflix.title
0                  50 First Dates
1                 Men in Black II
2                  50 First Dates
                    ...          
1246555               Bad Boys II
1246556    Something's Gotta Give
1246557    The American President
Name: title, Length: 1246558, dtype: str
# `loc`: label-based indexing
netflix.loc[:, ["title", "rating"]]
title rating
0 50 First Dates 4
1 Men in Black II 2
2 50 First Dates 4
... ... ...
1246555 Bad Boys II 3
1246556 Something's Gotta Give 4
1246557 The American President 5

1246558 rows × 2 columns

# `iloc`: position-based indexing
netflix.iloc[100:103, :2]
viewer_id rating
100 563447 4
101 2233688 4
102 2174838 2

query()

조건에 맞는 부분(관측치, 행)만 필터링

Conditional operators
>,  >=,  <,  <=,
==  (equal to),  !=  (not equal to)
and, & (and)
or, | (or)
not, ~ (not)
in (includes), not in (not included)

netflix.query("release_year >= 1990 & release_year < 2000")
viewer_id rating watch_date release_year title record_id media_type director cast country date_added MPAA_rating duration genre description runtime num_episodes
3 2041113 3 2003-12-30 1995 Bad Boys s6212 Movie Michael Bay Will Smith, Martin Lawrence, Téa Leoni, Tchéky... United States October 1, 2019 R 119 min [Action & Adventure, Comedies] In this fast-paced actioner, two Miami narcoti... 119 <NA>
4 948394 4 2005-04-01 1996 Dragonheart s6642 Movie Rob Cohen Sean Connery, Dennis Quaid, David Thewlis, Pet... United States January 1, 2020 PG-13 103 min [Action & Adventure, Sci-Fi & Fantasy] In ancient times when majestic fire-breathers ... 103 <NA>
8 79898 4 2005-06-24 1999 Superstar s8131 Movie Bruce McCulloch Molly Shannon, Will Ferrell, Elaine Hendrix, H... United States November 20, 2019 PG-13 82 min [Comedies] A socially awkward Catholic schoolgirl vows to... 82 <NA>
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1246552 1161577 4 2004-06-06 1995 Bad Boys s6212 Movie Michael Bay Will Smith, Martin Lawrence, Téa Leoni, Tchéky... United States October 1, 2019 R 119 min [Action & Adventure, Comedies] In this fast-paced actioner, two Miami narcoti... 119 <NA>
1246553 26124 3 2005-09-02 1996 The Mirror Has Two Faces s819 Movie Barbra Streisand Barbra Streisand, Jeff Bridges, Lauren Bacall,... United States June 2, 2021 PG-13 127 min [Comedies, Dramas, Romantic Movies] Tired of being single, middle-aged professor R... 127 <NA>
1246557 811068 5 2004-08-26 1995 The American President s8188 Movie Rob Reiner Michael Douglas, Annette Bening, Martin Sheen,... United States January 1, 2021 PG-13 113 min [Comedies, Dramas, Romantic Movies] The widowed president strikes up a romance wit... 113 <NA>

428354 rows × 17 columns

netflix.query("rating in [1, 5]")
viewer_id rating watch_date release_year title record_id media_type director cast country date_added MPAA_rating duration genre description runtime num_episodes
9 268405 5 2005-11-02 2004 A Cinderella Story s128 Movie Mark Rosman Hilary Duff, Chad Michael Murray, Jennifer Coo... United States, Canada September 1, 2021 PG 95 min [Children & Family Movies, Comedies] Teen Sam meets the boy of her dreams at a danc... 95 <NA>
15 914520 1 2004-06-14 2003 S.W.A.T. s7913 Movie Clark Johnson Samuel L. Jackson, Colin Farrell, Michelle Rod... United States January 1, 2021 PG-13 117 min [Action & Adventure] A veteran cop is tasked with drafting and trai... 117 <NA>
18 86305 5 2005-10-24 2005 The Amityville Horror s8189 Movie Andrew Douglas Ryan Reynolds, Melissa George, Chloë Grace Mor... United States January 1, 2020 R 89 min [Horror Movies] This hair-raising remake of the 1979 horror hi... 89 <NA>
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1246548 2612134 5 2003-12-23 2003 Bad Boys II s6213 Movie Michael Bay Will Smith, Martin Lawrence, Jordi Mollà, Gabr... United States October 1, 2019 R 147 min [Action & Adventure, Comedies] In this hyperkinetic sequel, a pair of Miami n... 147 <NA>
1246551 340807 5 2003-08-12 1999 American Beauty s6136 Movie Sam Mendes Kevin Spacey, Annette Bening, Thora Birch, Wes... United States January 1, 2020 R 122 min [Dramas] While struggling to endure his tightly wound w... 122 <NA>
1246557 811068 5 2004-08-26 1995 The American President s8188 Movie Rob Reiner Michael Douglas, Annette Bening, Martin Sheen,... United States January 1, 2021 PG-13 113 min [Comedies, Dramas, Romantic Movies] The widowed president strikes up a romance wit... 113 <NA>

320750 rows × 17 columns

# title에 game이 포함되어 있는 행만 필터링
netflix.loc[netflix.title.str.contains("Game"), :]  # .str: 문자열 처리

# 동일한 작업을 query()를 이용해 필터링
netflix.query("title.str.contains('Game')")
viewer_id rating watch_date release_year title record_id media_type director cast country date_added MPAA_rating duration genre description runtime num_episodes
108 1611338 4 2003-02-27 1997 The Game s601 Movie David Fincher Michael Douglas, Sean Penn, Deborah Kara Unger... United States July 1, 2021 R 129 min [Thrillers] An aloof investment banker's life spirals into... 129 <NA>
187 2634345 5 2005-06-28 1997 The Game s601 Movie David Fincher Michael Douglas, Sean Penn, Deborah Kara Unger... United States July 1, 2021 R 129 min [Thrillers] An aloof investment banker's life spirals into... 129 <NA>
245 465580 3 2004-02-09 1997 The Game s601 Movie David Fincher Michael Douglas, Sean Penn, Deborah Kara Unger... United States July 1, 2021 R 129 min [Thrillers] An aloof investment banker's life spirals into... 129 <NA>
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1246315 715480 4 2005-08-13 1997 The Game s601 Movie David Fincher Michael Douglas, Sean Penn, Deborah Kara Unger... United States July 1, 2021 R 129 min [Thrillers] An aloof investment banker's life spirals into... 129 <NA>
1246407 2567821 2 2003-05-18 1997 The Game s601 Movie David Fincher Michael Douglas, Sean Penn, Deborah Kara Unger... United States July 1, 2021 R 129 min [Thrillers] An aloof investment banker's life spirals into... 129 <NA>
1246415 1154697 4 2004-11-17 1997 The Game s601 Movie David Fincher Michael Douglas, Sean Penn, Deborah Kara Unger... United States July 1, 2021 R 129 min [Thrillers] An aloof investment banker's life spirals into... 129 <NA>

19341 rows × 17 columns

sort_values()

조건에 맞도록 행을 재정렬

netflix.sort_values("release_year")  # year에 대해 오름차순 정렬
netflix.sort_values("release_year", ascending=False)  # year에 대해 내림차순 정렬
netflix.sort_values(["release_year", "rating"], ascending=False)  # year 다음 rating에 대해 내림차순 정렬
viewer_id rating watch_date release_year title record_id media_type director cast country date_added MPAA_rating duration genre description runtime num_episodes
18 86305 5 2005-10-24 2005 The Amityville Horror s8189 Movie Andrew Douglas Ryan Reynolds, Melissa George, Chloë Grace Mor... United States January 1, 2020 R 89 min [Horror Movies] This hair-raising remake of the 1979 horror hi... 89 <NA>
31 666338 5 2005-08-19 2005 Coach Carter s6511 Movie Thomas Carter Samuel L. Jackson, Rob Brown, Robert Ri'chard,... United States, Germany January 1, 2020 PG-13 137 min [Dramas, Sports Movies] Controversial basketball coach Ken Carter puts... 137 <NA>
189 642572 5 2005-07-27 2005 Coach Carter s6511 Movie Thomas Carter Samuel L. Jackson, Rob Brown, Robert Ri'chard,... United States, Germany January 1, 2020 PG-13 137 min [Dramas, Sports Movies] Controversial basketball coach Ken Carter puts... 137 <NA>
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1230179 2537543 1 2005-12-02 1965 The Cincinnati Kid s8250 Movie Norman Jewison Steve McQueen, Edward G. Robinson, Ann-Margret... United States November 1, 2019 TV-14 103 min [Classic Movies, Dramas] In Depression-era New Orleans, cocksure stud p... 103 <NA>
1232551 455843 1 2004-01-12 1965 Doctor Zhivago s6620 Movie David Lean Omar Sharif, Julie Christie, Geraldine Chaplin... United States, Italy, United Kingdom, Liechten... November 1, 2019 PG-13 200 min [Classic Movies, Dramas, Romantic Movies] A young physician and his beautiful mistress g... 200 <NA>
1240585 2185183 1 2005-06-07 1965 Doctor Zhivago s6620 Movie David Lean Omar Sharif, Julie Christie, Geraldine Chaplin... United States, Italy, United Kingdom, Liechten... November 1, 2019 PG-13 200 min [Classic Movies, Dramas, Romantic Movies] A young physician and his beautiful mistress g... 200 <NA>

1246558 rows × 17 columns

assign()

변수들과 함수들을 이용하여 새로운 변수를 생성

가령, 1990년대, 2000년대 등등과 같이 10년 단위로 새로운 값을 생성하려면,

netflix["release_year"]  # pandas Series 객체, 그 값들은 NumPy array
0          2004
1          2002
2          2004
           ... 
1246555    2003
1246556    2003
1246557    1995
Name: release_year, Length: 1246558, dtype: int64
netflix["release_year"] // 10  # NumPy array에 대한 나눗셈(몫) 연산
0          200
1          200
2          200
          ... 
1246555    200
1246556    200
1246557    199
Name: release_year, Length: 1246558, dtype: int64
netflix.assign(
    decade=netflix["release_year"] // 10 * 10, # 10년 단위
)
viewer_id rating watch_date release_year title record_id media_type director cast country date_added MPAA_rating duration genre description runtime num_episodes decade
0 2191540 4 2004-06-23 2004 50 First Dates s6019 Movie Peter Segal Adam Sandler, Drew Barrymore, Rob Schneider, S... United States December 1, 2020 PG-13 99 min [Comedies, Romantic Movies] After falling for a pretty art teacher who has... 99 <NA> 2000
1 998702 2 2005-08-26 2002 Men in Black II s7444 Movie Barry Sonnenfeld Tommy Lee Jones, Will Smith, Rip Torn, Lara Fl... United States October 1, 2019 PG-13 88 min [Action & Adventure, Comedies, Sci-Fi & Fantasy] Will Smith and Tommy Lee Jones reprise their r... 88 <NA> 2000
2 1914163 4 2005-03-21 2004 50 First Dates s6019 Movie Peter Segal Adam Sandler, Drew Barrymore, Rob Schneider, S... United States December 1, 2020 PG-13 99 min [Comedies, Romantic Movies] After falling for a pretty art teacher who has... 99 <NA> 2000
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1246555 1991791 3 2004-01-06 2003 Bad Boys II s6213 Movie Michael Bay Will Smith, Martin Lawrence, Jordi Mollà, Gabr... United States October 1, 2019 R 147 min [Action & Adventure, Comedies] In this hyperkinetic sequel, a pair of Miami n... 147 <NA> 2000
1246556 925565 4 2005-11-20 2003 Something's Gotta Give s8056 Movie Nancy Meyers Jack Nicholson, Diane Keaton, Keanu Reeves, Fr... United States August 1, 2019 PG-13 128 min [Comedies, Romantic Movies] Still sexy at 60, Harry Sanborn wines and dine... 128 <NA> 2000
1246557 811068 5 2004-08-26 1995 The American President s8188 Movie Rob Reiner Michael Douglas, Annette Bening, Martin Sheen,... United States January 1, 2021 PG-13 113 min [Comedies, Dramas, Romantic Movies] The widowed president strikes up a romance wit... 113 <NA> 1990

1246558 rows × 18 columns

# lambda를 이용한 값 생성
netflix.assign(
    decade=lambda x: x["release_year"] // 10 * 10, # 10년 단위
    weekday=lambda x: x["watch_date"].dt.day_name().str[:3] # 요일
)
viewer_id rating watch_date release_year title record_id media_type director cast country date_added MPAA_rating duration genre description runtime num_episodes decade weekday
0 2191540 4 2004-06-23 2004 50 First Dates s6019 Movie Peter Segal Adam Sandler, Drew Barrymore, Rob Schneider, S... United States December 1, 2020 PG-13 99 min [Comedies, Romantic Movies] After falling for a pretty art teacher who has... 99 <NA> 2000 Wed
1 998702 2 2005-08-26 2002 Men in Black II s7444 Movie Barry Sonnenfeld Tommy Lee Jones, Will Smith, Rip Torn, Lara Fl... United States October 1, 2019 PG-13 88 min [Action & Adventure, Comedies, Sci-Fi & Fantasy] Will Smith and Tommy Lee Jones reprise their r... 88 <NA> 2000 Fri
2 1914163 4 2005-03-21 2004 50 First Dates s6019 Movie Peter Segal Adam Sandler, Drew Barrymore, Rob Schneider, S... United States December 1, 2020 PG-13 99 min [Comedies, Romantic Movies] After falling for a pretty art teacher who has... 99 <NA> 2000 Mon
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1246555 1991791 3 2004-01-06 2003 Bad Boys II s6213 Movie Michael Bay Will Smith, Martin Lawrence, Jordi Mollà, Gabr... United States October 1, 2019 R 147 min [Action & Adventure, Comedies] In this hyperkinetic sequel, a pair of Miami n... 147 <NA> 2000 Tue
1246556 925565 4 2005-11-20 2003 Something's Gotta Give s8056 Movie Nancy Meyers Jack Nicholson, Diane Keaton, Keanu Reeves, Fr... United States August 1, 2019 PG-13 128 min [Comedies, Romantic Movies] Still sexy at 60, Harry Sanborn wines and dine... 128 <NA> 2000 Sun
1246557 811068 5 2004-08-26 1995 The American President s8188 Movie Rob Reiner Michael Douglas, Annette Bening, Martin Sheen,... United States January 1, 2021 PG-13 113 min [Comedies, Dramas, Romantic Movies] The widowed president strikes up a romance wit... 113 <NA> 1990 Thu

1246558 rows × 19 columns

groupby(), agg(), apply()

카테고리별로 나뉘어진 데이터에 대한 통계치를 생성

  • groupby()는 데이터를 의미있는 그룹으로 나누어 분석할 수 있도록 해줌
  • .count(), .sum(), .mean(), .min(), .max()과 같은 통계치를 구하는 methods와 함께 효과적으로 자주 활용됨

아래 표는 groupby()와 함께 자주 쓰이는 효율적인 methods

Source: Ch.10 in Python for Data Analysis (3e) by Wes McKinney

netflix.columns
Index(['viewer_id', 'rating', 'watch_date', 'release_year', 'title',
       'record_id', 'media_type', 'director', 'cast', 'country', 'date_added',
       'MPAA_rating', 'duration', 'genre', 'description', 'runtime',
       'num_episodes'],
      dtype='str')
netflix.groupby("title")["rating"].mean()
title
50 First Dates                 3.752
A Cinderella Story             3.625
About a Boy                    3.589
                                ... 
Training Day                   3.571
Tremors 4: The Legend Begins   3.043
Under Siege                    3.313
Name: rating, Length: 94, dtype: Float64
netflix.groupby("viewer_id")["rating"].agg(["mean", "std"])
mean std
viewer_id
6 3.250 1.035
7 4.071 1.141
8 4.000 <NA>
... ... ...
2649409 4.000 <NA>
2649426 4.000 0.000
2649429 4.833 0.408

316804 rows × 2 columns

def min_max(x):
    return pd.Series([x.min(), x.max()], index=["min", "max"])  # Series를 반환

netflix.groupby("title")["rating"].apply(min_max)
title                            
50 First Dates                min    1
                              max    5
A Cinderella Story            min    1
                                    ..
Tremors 4: The Legend Begins  max    5
Under Siege                   min    1
                              max    5
Name: rating, Length: 188, dtype: int8
def standardize_by_user(x):
    return (x - x.mean()) / x.std()

(
    netflix
    .groupby("viewer_id")["rating"]
    .apply(standardize_by_user)
    .reset_index(level=0)
)
viewer_id rating
422187 6 0.725
723559 6 -0.242
726864 6 0.725
... ... ...
1009754 2649429 0.408
1132274 2649429 0.408
1228870 2649429 0.408

1246558 rows × 2 columns

Exploratory Data Analysis (EDA)

netflix = pd.read_parquet("data/netflix_ratings_titles.parquet")

기본통계

  • 총 시청 기록 수: 1246558개
  • 총 시청자 수: 316804명
  • 고유 작품 수: 94개
  • 총 시청 시간: 2391943.3시간
  • 전체 평균 평점: 3.59/10
# 총 시청 기록 수
netflix.shape
(1246558, 17)
# 총 시청자 수
netflix["viewer_id"].nunique()
316804
# 고유 작품 수
netflix["title"].nunique()
94
# 총 시청 시간
netflix["runtime"].sum() / 60
2391943.316666667
# 전체 평균 평점: 3.59/10
netflix["rating"].mean()
3.58698833106843
def get_basic_stats(db):
    return {
        "총 시청 기록수": db.shape[0],
        "총 시청자 수": db["viewer_id"].nunique(),
        "고유 작품 수": db["title"].nunique(),
        "총 시청 시간": db["runtime"].sum() / 60,
        "전체 평균 평점": db["rating"].mean()
    }

get_basic_stats(netflix)
{'총 시청 기록수': 1246558,
 '총 시청자 수': 316804,
 '고유 작품 수': 94,
 '총 시청 시간': 2391943.316666667,
 '전체 평균 평점': 3.58698833106843}
NumPy 스칼라값 표현 예전 방식으로 수정
np.set_printoptions(legacy='1.25')

시청자 분석

가장 활발한 시청자 TOP 5

  1. 387418: 45회 시청
  2. 305344: 43회 시청
  3. 1664010: 43회 시청
  4. 2439493: 40회 시청
  5. 2606799: 38회 시청
# 가장 활발한 시청자 TOP 5
netflix.value_counts("viewer_id")[:5].reset_index(name="count")
viewer_id count
0 387418 45
1 305344 43
2 1664010 43
3 2439493 40
4 2606799 38

시청자별 통계

[6] 시청 횟수: 8회 평균 평점: 3.25/10

[7] 시청 횟수: 14회 평균 평점: 4.07/10

[8] 시청 횟수: 1회 평균 평점: 4.00/10

[10] 시청 횟수: 1회 평균 평점: 4.00/10

[59] 시청 횟수: 1회 평균 평점: 4.00/10

# 시청자별 통계
user_stats = netflix.groupby("viewer_id")["rating"].agg(["mean", "std", "count"])
user_stats[:5]  # 처음 5개 레코드만 표시
mean std count
viewer_id
6 3.250 1.035 8
7 4.071 1.141 14
8 4.000 <NA> 1
10 4.000 <NA> 1
59 4.000 <NA> 1

작품별 분석

평균 평점 TOP 10 작품 (최소 3명 이상 평가)

  1. Kabhi Khushi Kabhie Gham
    평균 평점: 4.24/10 (97명 평가)
  2. The Pianist
    평균 평점: 4.12/10 (30497명 평가)
  3. Coach Carter
    평균 평점: 4.07/10 (30022명 평가)
  4. Kuch Kuch Hota Hai
    평균 평점: 4.00/10 (271명 평가)
  5. Doctor Zhivago
    평균 평점: 3.98/10 (8810명 평가)
  6. Like Water for Chocolate
    평균 평점: 3.97/10 (13459명 평가)
  7. American Beauty
    평균 평점: 3.96/10 (77407명 평가)
  8. Lock, Stock and Two Smoking Barrels 평균 평점: 3.93/10 (19899명 평가)
  9. Charlotte’s Web
    평균 평점: 3.92/10 (13693명 평가)
  10. Jaws
    평균 평점: 3.88/10 (40425명 평가)
# 평균 평점 TOP 10 작품 (최소 3명 이상 평가)
def get_top_rated_media(n=10, min_ratings=3):
    return (
        netflix
        .groupby("title")["rating"]
        .agg(["mean", "count"])
        .query("count >= @min_ratings")
        .nlargest(n, "mean")
    )

get_top_rated_media()
mean count
title
Kabhi Khushi Kabhie Gham 4.237 97
The Pianist 4.116 30497
Coach Carter 4.071 30022
... ... ...
Lock, Stock and Two Smoking Barrels 3.933 19899
Charlotte's Web 3.917 13693
Jaws 3.880 40425

10 rows × 2 columns

장르 분석

장르별 통계

Comedies: 시청 횟수: 606749회 평균 평점: 3.51/10 시청자 수: 243514명 총 시청 시간: 1083382.5시간

Action & Adventure: 시청 횟수: 466348회 평균 평점: 3.52/10 시청자 수: 217876명 총 시청 시간: 912268.1시간

Dramas: 시청 횟수: 428928회 평균 평점: 3.75/10 시청자 수: 200592명 총 시청 시간: 874892.6시간

…

# 장르별 통계: 시청 횟수, 평균 평점, 시청자 수, 총 시청시간

netflix_long = netflix.explode('genre')

genre_stats = (
    netflix_long.groupby("genre")
    .agg(
        count=("rating", "size"),
        mean_rating=("rating", "mean"),
        total_viewers=("viewer_id", "nunique"),  # nunique(): 고유 값 개수 함수
        total_runtime=("runtime", "sum"),
    )
    .assign(
        total_runtime=lambda x: x["total_runtime"] / 60
    )
    .reset_index()
)
genre_stats
genre count mean_rating total_viewers total_runtime
0 Action & Adventure 466348 3.518 217876 912268.133
1 Anime Series 126 3.627 126 0.000
2 Children & Family Movies 106728 3.319 69248 163799.883
... ... ... ... ... ...
15 Sports Movies 49586 3.819 45149 104607.100
16 TV Dramas 731 3.765 731 0.000
17 Thrillers 133365 3.551 89527 271388.767

18 rows × 5 columns

# 장르 분포 시각화: 시청 횟수
order_by_count = genre_stats.sort_values("count", ascending=False)["genre"].values
(
    so.Plot(genre_stats, y="genre", x="count")
    .add(so.Bar())
    .scale(y=so.Nominal(order=order_by_count))
)

시간대 분석

월별 시청 추이

1999-11 1회
1999-12 30회
2000-01 1009회
2000-02 1089회
2000-03 916회

netflix = netflix.assign(
    year_month=lambda x: x["watch_date"].dt.to_period("M")
)
# 월별 시청 추이
netflix.value_counts("year_month").sort_index()
year_month
1999-11        1
1999-12       30
2000-01     1009
           ...  
2005-10    65141
2005-11    38613
2005-12    21827
Freq: M, Name: count, Length: 74, dtype: int64
viewing_by_month = netflix.value_counts("year_month").sort_index().reset_index()

(
    so.Plot(viewing_by_month, x="count", y="year_month")
    .add(so.Bars())
    .layout(size=(6, 10))
)

# 시각화: seaborn에서 직접 계산하여 그리기
(
    so.Plot(netflix, y="year_month")
    .add(so.Bars(), so.Hist())
    .layout(size=(6, 10))
)

# 요일별 시청 패턴
netflix = netflix.assign(
    weekday=lambda x: x["watch_date"].dt.day_name().str[:3] # 요일
)

netflix["weekday"] = netflix["weekday"].astype("category").cat.set_categories(["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]) # 요일 순서 지정을 위해 카테고리 변환
netflix.value_counts("weekday").sort_index()
weekday
Mon    214181
Tue    221189
Wed    206516
        ...  
Fri    167458
Sat    123017
Sun    133268
Name: count, Length: 7, dtype: int64
# 요일별 시청 패턴 시각화
(
    so.Plot(netflix, y="weekday")
    .add(so.Bars(), so.Hist())
)

평점 분석

전체 평점 분포

5점: 266619개
4점: 433481개
3점: 365585개
2점: 126742개
1점: 54131개

# 전체 평점 분포
netflix.value_counts("rating").sort_index()
rating
1     54131
2    126742
3    365585
4    433481
5    266619
Name: count, dtype: int64
# 시각화
(
    so.Plot(netflix, y="rating")
    .add(so.Bar(), so.Hist(discrete=True))
)

종합 리포트

시청 기록 종합 리포트

  • 총 시청 기록 수: 1246558개
  • 총 시청자 수: 316804명
  • 고유 작품 수: 94개
  • 총 시청 시간: 2391943.3시간
  • 전체 평균 평점: 3.59/10

가장 인기 있는 장르: Comedies

평균 평점이 가장 높은 TOP 3 작품:

  1. Kabhi Khushi Kabhie Gham (평균: 4.24/10, 97명 평가)
  2. The Pianist (평균: 4.12/10, 30497명 평가)
  3. Coach Carter (평균: 4.07/10, 30022명 평가)
def get_summary_report(db):
    return {
        "총 시청 기록 수": db.shape[0],
        "총 시청자 수": db["viewer_id"].nunique(),
        "고유 작품 수": db["title"].nunique(),
        "총 시청 시간": db["runtime"].sum() / 60,
        "전체 평균 평점": db["rating"].mean(),
        "가장 인기 있는 장르": genre_stats.set_index("genre")["count"].idxmax(),
        "평균 평점이 가장 높은 TOP 3 작품": get_top_rated_media(3, 3).reset_index().to_dict(orient="records")
    }

get_summary_report(netflix)
{'총 시청 기록 수': 1246558,
 '총 시청자 수': 316804,
 '고유 작품 수': 94,
 '총 시청 시간': 2391943.316666667,
 '전체 평균 평점': 3.58698833106843,
 '가장 인기 있는 장르': 'Comedies',
 '평균 평점이 가장 높은 TOP 3 작품': [{'title': 'Kabhi Khushi Kabhie Gham',
   'mean': 4.237113402061856,
   'count': 97},
  {'title': 'The Pianist', 'mean': 4.116142571400466, 'count': 30497},
  {'title': 'Coach Carter', 'mean': 4.070748118046765, 'count': 30022}]}

분석 코드를 모듈로 재사용하기

지금까지 EDA 과정에서 작성한 코드를 살펴보면, 비슷한 패턴이 반복됩니다.

  • 기본 통계 계산 (get_basic_stats)
  • 평균 평점 TOP 작품 (get_top_rated_media)
  • 장르별 집계 (groupby + agg)
  • 종합 리포트 (get_summary_report)

이렇게 반복적으로 쓰이는 코드는 별도의 모듈(.py 파일)로 분리해 두면

  1. 여러 노트북·스크립트에서 import 해서 재사용할 수 있고,
  2. 분석 로직과 노트북의 서술이 분리되어 노트북이 깔끔해지며,
  3. 함수/클래스 단위로 테스트하기 쉬워집니다.

여기서는 EDA 코드를 netflix_analysis.py 모듈로 정리했습니다. 이 모듈은 두 가지 스타일을 모두 제공합니다.

  • 순수 함수: na.basic_stats(df), na.top_rated_titles(df) 처럼 DataFrame을 인자로 받아 결과를 돌려줍니다.
  • NetflixAnalyzer 클래스: 데이터와 분석 동작을 하나의 객체로 묶어(캡슐화) analyzer.basic_stats() 처럼 메서드로 호출합니다.

1. 모듈 불러오기

import 모듈명 as 별칭 형태로 불러옵니다. 같은 폴더에 있는 netflix_analysis.py 파일이 그대로 모듈이 됩니다.

import netflix_analysis as na

na.setup_display()  # 모듈에 정의된 출력 환경 설정 함수

2. 함수 스타일로 사용하기

DataFrame을 인자로 넘기면 결과를 돌려주는 순수 함수들입니다. 앞에서 직접 작성했던 get_basic_stats, get_top_rated_media 와 같은 일을 모듈 함수가 대신 해줍니다.

netflix = na.load_netflix_data("data/netflix_ratings_titles.parquet")

# 기본 통계 (직접 만든 get_basic_stats 와 동일한 결과)
na.basic_stats(netflix)
# 평균 평점 TOP 10 작품 (최소 3명 이상 평가)
na.top_rated_titles(netflix, n=10, min_ratings=3)
# 장르별 통계 → 그대로 시각화 함수에 넘기기
genre_stats = na.genre_stats(netflix)
na.plot_genre_ranking(genre_stats, metric="count")

3. 클래스 스타일로 사용하기

함수 방식은 매번 netflix DataFrame을 인자로 넘겨야 합니다. NetflixAnalyzer 클래스는 데이터를 한 번 담아 두면, 이후에는 인자 없이 메서드만 호출하면 됩니다. 또한

  • 생성 시 파생 변수(decade, weekday, year_month, runtime_hours)를 자동으로 추가하고,
  • 비용이 큰 장르 집계 결과를 내부에 캐싱하며,
  • filter_* 메서드는 새 분석기를 돌려주어 체이닝이 가능합니다.
# 분석기 객체 생성 (parquet 파일에서 바로 생성)
analyzer = na.NetflixAnalyzer.from_parquet("data/netflix_ratings_titles.parquet")
analyzer  # __repr__ 로 요약 정보가 출력됨
# 인자 없이 메서드 호출
analyzer.top_rated_titles(n=5)
# 필터링 → 체이닝: "Dramas" 장르 & 1990년대 작품 중 평균 평점 TOP 5
(
    analyzer
    .filter_by_genre("Dramas")
    .filter_by_year_range(1990, 1999)
    .top_rated_titles(n=5)
)
# 클래스 메서드로 바로 시각화 (요일별 시청 패턴)
analyzer.plot_weekday_pattern()

4. 종합 리포트

summary_report() 는 기본 통계, 인기 장르, 평균 평점 TOP 작품을 묶은 SummaryReport 객체를 돌려줍니다. print() 하면 사람이 읽기 좋은 형태로 출력됩니다.

report = analyzer.summary_report(top_n=3, min_ratings=3)
print(report)
# JSON 저장 등에 쓰기 좋은 딕셔너리 형태로도 변환 가능
report.to_dict()

This work © 2025 by Sungkyun Cho is licensed under CC BY-NC-SA 4.0