본문 바로가기
추천시스템 앱 개발/데이터

[데이터 분석] Movielens(무비렌즈) 데이터 분석 3 - 인기 영화 분석

by 직_장인 2025. 3. 16.

1-3. 인기 영화 분석

1-3-1. 가장 많이 평가한 영화

  • 사람들이 어떤 장르의 영화를 주로 찾는지 궁금하다.
  • 이때 사람들이 가장 많이 평가한 영화를 보면 힌트를 얻을 수 있을 것 같다.
# 가장 많이 평가된 영화 (평점 수 기준)
movie_rating_counts = ratings['movieId'].value_counts().reset_index()
movie_rating_counts.columns = ['movieId', 'rating_count']
popular_movies = movie_rating_counts.merge(movies, on='movieId')

top_rated_movies = popular_movies.sort_values('rating_count', ascending=False).head(20)
print("가장 많이 평가된 영화 (상위 20개):")
display(top_rated_movies[['title', 'rating_count', 'genres']])
  • 가장 많이 평가된 영화
    • 사람들의 영화 평가 정보가 담겨있는 ratings 데이터프레임에서 movieId를 기준으로 갯수를 확인하기 위해 value_counts() 함수를 사용하여 movie_rating_counts로 만든다.
    • 영화명(title)을 확인하기 위해, merge()함수를 이용하여, movie_rating_counts에 'movieId'를 기준으로 movies 데이터프레임을 결합시킨다. 이를 popular_movies로 만든다.
    • popular_movies 데이터프레임을 점수 갯수인 rating_count를 내림차순으로 정렬하고 20개만 표시한다.

  • 시각화
    • 그래프로도 확인해본다.
# 시각화
plt.figure(figsize=(14, 10))
sns.barplot(x='rating_count', y='title', data=top_rated_movies.head(15))
plt.title('가장 많이 평가된 영화 (상위 15개)', fontsize=15)
plt.xlabel('평점 수', fontsize=12)
plt.ylabel('영화 제목', fontsize=12)
plt.grid(True, alpha=0.3)
plt.show()

  • 분석 결과
    • 평점이 높은 영화들은 주로 드라마, 스릴러, 어드벤쳐 영화다. 
      • 스릴러 장르의 평균 평점이 높지 않았던 걸 생각하면, 스릴러 영화는 명작 아니면 졸작 느낌..?
    • 가장 많이 평가된 영화 대부분이 1990년대 영화이다. 이 그래프는 실제 이 시기에 영화가 얼마나 많이 만들어졌는지와 함께 봐야 의미가 있을 것 같다. 시간에 따른 트렌드는 아래에서 살펴보기로 한다. 

 

1-3-2. 평균 평점이 높은 영화

  • 의미있는 평균값
    • 우리가 장르별 영화 분포 분석에서 평균값을 계산할 때, 갯수를 중요하게 생각하지는 않았다.
    • 하지만, 그건 영화를 크게 장르별로 구분했을 때 평균을 계산하기 위한 데이터 수가 충분하다는 가정이 있었기 때문이다.
    • 만약 영화별로 평균 평점을 구하려면 똑같이 해도 될까?
    • 아니다. 한번 점수를 5점으로 받아서 평균이 5점인 영화와, 100번 점수를 5점으로 받아 평균이 5점인 영화를 비교한다면 평균 점수는 같을 것이다. 하지만 명백히 다른 의미를 갖는다.
    • 따라서, 평균값이 의미있는 영화를 기준(최소 100개 이상의 평점이 있는 영화)으로 평균 평점이 높은 영화를 확인한다,
# 평균 평점이 높은 영화 (최소 100개 이상의 평점이 있는 영화 중)
movie_avg_ratings = ratings.groupby('movieId')['rating'].agg(['mean', 'count']).reset_index()
min_ratings = 100  # 최소 평점 수 기준
qualified_movies = movie_avg_ratings[movie_avg_ratings['count'] >= min_ratings]
qualified_movies = qualified_movies.merge(movies, on='movieId')

top_avg_rated = qualified_movies.sort_values('mean', ascending=False).head(20)
print(f"\n평균 평점이 높은 영화 (최소 {min_ratings}개 이상의 평점, 상위 20개):")
display(top_avg_rated[['title', 'mean', 'count', 'genres']])

 

  • 평균 평점이 높은 영화
    • ratings 데이터프레임을 groupby() 함수를 이용하여, movieId를 기준으로 묶고 점수(rating)값을 표시한다.
    • 이때 agg() 함수를 이용하여 점수 평균(mean), 점수 갯수(count)에 대해 값을 구하고 이를 movie_avg_ratings로 만든다.
    • movie_avg_ratings 데이터프레임에서 갯수가 min_ratings(=100)보다 큰 영화만 필터링 한다.
    • 영화명(title)을 확인하기 위해 movies 데이터프레임을 결합한다.
    • 평점을 기준으로 정렬한다.

  • 시각화
    • genre_ratings_df의 Avg_Rating(평균 평점) 값을 시각화한다.
# 시각화
plt.figure(figsize=(14, 10))
sns.barplot(x='mean', y='title', data=top_avg_rated.head(15), palette='viridis')
plt.title(f'평균 평점이 높은 영화 (최소 {min_ratings}개 이상의 평점, 상위 15개)', fontsize=15)
plt.xlabel('평균 평점', fontsize=12)
plt.ylabel('영화 제목', fontsize=12)
plt.grid(True, alpha=0.3)
plt.xlim(4.0, 5.0)  # 차이를 더 명확하게 보기 위해 축 범위 조정
plt.show()

  • 분석 결과
    • 평점 갯수를 기준으로 높은 위치를 차지했던 스릴러(Thriller) 영화가 평균 평점을 기준으로도 상위권에 위치해있다. 명작 아니면 졸작이라는 가정이 신빙성이 있어보인다.
    • 또한 평점 갯수와 평균 평점 사이약한 상관관계가 있는 것 같기도 하다.

 

1-3-3. 상관 관계 분석

  • 평점 수와 평균 평점 사이의 관계 분석
    • 상관관계(correlation) 값을 계산하는 corr() 함수를 이용하여 손쉽게 계산 가능하다.
# 상관계수 계산
correlation = movie_avg_ratings['count'].corr(movie_avg_ratings['mean'])
print(f"평점 수와 평균 평점의 피어슨 상관계수: {correlation:.4f}")
  • 평점 수와 평균 평점의 피어슨 상관계수: 0.1273
    • 상관계수는 0 ~ 1의 값을 가지며, 1에 가까울수록 강한 상관관계를 갖는다.
    • 일반적으로 0.1~0.3이면 매우 약한 상관관계라고 해석한다.
    • (상관계수를 볼 때 p-value도 같이 확인해야 하는데, 이번 분석에선 생략한다.)
  • 시각화
    • 상관관계가 약하더라도 특정 패턴이 있을 수 있으므로, seaborn의 scatterplot()을 활용해 산점도를 그려본다.
# 평점 수와 평균 평점 사이의 관계 분석
plt.figure(figsize=(10, 6))
sns.scatterplot(x='count', y='mean', data=movie_avg_ratings, alpha=0.5)
plt.title('평점 수와 평균 평점의 관계', fontsize=15)
plt.xlabel('평점 수', fontsize=12)
plt.ylabel('평균 평점', fontsize=12)
plt.xscale('log')  # 로그 스케일로 표시하여 분포를 더 잘 볼 수 있게 함
plt.grid(True, alpha=0.3)
plt.show()

  • 분석 결과
    • 산점도로 표현하니 추세가 잘 보인다. 평점 갯수가 많아질 수록 평균 평점이 높아지는걸 볼 수 있다.
    • 재미있는 영화일 수록 많이 보고 평점도 높게 주지만, 재미없는 영화는 많이 안보고 점수를 주지도 않은 것으로 해석할 수도 있다.

 

1-3-4. 트렌드 분석

  • 연도별 영화 수 분석
    • 가장 많이 평가된 영화를 확인할 때, 동일 시점에 얼마나 많은 영화가 만들어졌는지 같이 확인해봐야 한다는걸 알았다.
    • 연도별로 얼마나 많은 영화가 만들어졌는지 확인해보자.
    • movies 데이터프레임의 title에 각 영화의 개봉 연도가 함께 표시되어 있다.
    • movies 데이터프레임의 title에서 str(string:문자열)의 extract() 함수를 이용하여 괄호 안에 4자리 값(연도)을 추출한다.
    • 데이터 타입을 float으로 바꾼다.(int로 하는게 직관적으로 좋지만, Nan(빈 값)이 있는 경우엔 int로 변환이 안되기 때문에 float으로 한다.)
    • 이 값을 movies의 year 컬럼으로 지정한다.
# 연도 추출 및 정리
movies['year'] = movies['title'].str.extract(r'\((\d{4})\)')[0]
movies['year'] = movies['year'].astype(float)
  • 시각화
    • movies 데이터프레임의 year 값의 갯수를 계산하여, 연도 별 영화 수를 year_counts로 만든다.
    • year_counts는 pandas의 series 타입이 된다. index(연도)와 value(갯수)만 있기 때문에 뒤에 plot을 붙여서 바로 시각화 할 수 있다.
# 연도별 영화 수 분석
year_counts = movies['year'].value_counts().sort_index()
plt.figure(figsize=(15, 6))
year_counts.plot(kind='line', marker='o', markersize=4)
plt.title('연도별 영화 수', fontsize=15)
plt.xlabel('개봉 연도', fontsize=12)
plt.ylabel('영화 수', fontsize=12)
plt.grid(True, alpha=0.3)
plt.show()

  • 분석 결과
    • 1980년대부터 2000년대까지 영화 산업이 급격하게 성장했고, 2000년 이후로는 250~300개 수준으로 유지된다.
    • 1990년대에 이후로 좋은 평가를 받은 작품다른 많은 경쟁작들보다 좋은 평가를 받은 것이기 때문에 명작이라고 이야기할 수 있을 것이다.
  • 최근 장르 트렌드 분석
    • 2000년 이후부터 장르 별 영화 수를 파악해보자.
    • for문을 이용해서 장르를 하나씩 가져오고, recent_years(2000~2021)의 연도를 하나씩 가져온다.
    • 이 두가지 조건을 만족하는 영화를 movies 데이터프레임에서 색인한 후 len() 함수로 갯수를 계산하여 count 값으로 만든다.
    • 이렇게 하나의 장르의 연도별 영화 갯수를 yearly_counts 리스트로 묶은 후 genre_trends인 dictonary에 장르(genre)를 key로, yearly_counts 리스트를 value로 값을 입력한다.
    • 모든 장르에 대해 계산한 뒤 데이터프레임 형태로 만든다.
# 최근 20년간 장르 트렌드 분석
recent_years = range(2000, 2021)
genre_trends = {}

for genre in sorted(set(all_genres)):
    yearly_counts = []
    for year in recent_years:
        # 해당 연도, 해당 장르의 영화 수
        count = len(movies[(movies['year'] == year) & (movies['genres'].str.contains(genre))])
        yearly_counts.append(count)
    genre_trends[genre] = yearly_counts

genre_trends = pd.DataFrame(genre_trends)
genre_trends

genre_trends

  • 시각화
    • 상위 8개 장르에 대해서 시각화한다.
    • genre_trends 데이터프레임에서 sum() 함수를 이용하여 열 방향(axis=0)으로 장르 별 총 갯수를 구한 뒤 정렬하여 상위 8개 장르를 top_tenre_names로 만든다.
    • 각 장르별로 연도에 따른 영화 갯수값을 계산해두었기 때문에, for문을 이용하여 장르별 plot을 반복해서 그리면 된다.
# 상위 8개 장르만 시각화
top_genres = genre_trends.sum(axis=0).sort_values(ascending=False).head(8)
top_genre_names = top_genres.index

plt.figure(figsize=(15, 8))
for genre in top_genre_names:
    if genre in genre_trends:
        plt.plot(list(recent_years), genre_trends[genre], marker='o', markersize=4, label=genre)

plt.title('최근 20년간 주요 장르 트렌드', fontsize=15)
plt.xlabel('연도', fontsize=12)
plt.ylabel('영화 수', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, alpha=0.3)
plt.show()

  • 분석 결과
    • 드라마, 코미디는 다른 장르와 묶인 경우가 많기 때문에 대체적으로 높지만, 2010년 이후로 그 격차가 줄어 거의 동일한 비율이 된다.
    • 스릴러, 액션, SF의 경우 시기에 따라 변동이 있다. 아무래도 연도별로 영화 제작자가 선호하는 장르가 바뀌는 것 같다.

댓글