import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn
from matplotlib import font_manager, rc
font_path = "C:\Windows\Fonts\gulim.ttc"
font = font_manager.FontProperties(fname=font_path).get_name()
rc('font', family=font)
wine = pd.read_csv('./datas/winemag-data-130k-v2.csv')
wine.head()
Unnamed: 0 | country | description | designation | points | price | province | region_1 | region_2 | taster_name | taster_twitter_handle | title | variety | winery | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | Italy | Aromas include tropical fruit, broom, brimston... | Vulkà Bianco | 87 | NaN | Sicily & Sardinia | Etna | NaN | Kerin O’Keefe | @kerinokeefe | Nicosia 2013 Vulkà Bianco (Etna) | White Blend | Nicosia |
1 | 1 | Portugal | This is ripe and fruity, a wine that is smooth... | Avidagos | 87 | 15.0 | Douro | NaN | NaN | Roger Voss | @vossroger | Quinta dos Avidagos 2011 Avidagos Red (Douro) | Portuguese Red | Quinta dos Avidagos |
2 | 2 | US | Tart and snappy, the flavors of lime flesh and... | NaN | 87 | 14.0 | Oregon | Willamette Valley | Willamette Valley | Paul Gregutt | @paulgwine | Rainstorm 2013 Pinot Gris (Willamette Valley) | Pinot Gris | Rainstorm |
3 | 3 | US | Pineapple rind, lemon pith and orange blossom ... | Reserve Late Harvest | 87 | 13.0 | Michigan | Lake Michigan Shore | NaN | Alexander Peartree | NaN | St. Julian 2013 Reserve Late Harvest Riesling ... | Riesling | St. Julian |
4 | 4 | US | Much like the regular bottling from 2012, this... | Vintner's Reserve Wild Child Block | 87 | 65.0 | Oregon | Willamette Valley | Willamette Valley | Paul Gregutt | @paulgwine | Sweet Cheeks 2012 Vintner's Reserve Wild Child... | Pinot Noir | Sweet Cheeks |
wine.describe()
Unnamed: 0 | points | price | |
---|---|---|---|
count | 129971.000000 | 129971.000000 | 120975.000000 |
mean | 64985.000000 | 88.447138 | 35.363389 |
std | 37519.540256 | 3.039730 | 41.022218 |
min | 0.000000 | 80.000000 | 4.000000 |
25% | 32492.500000 | 86.000000 | 17.000000 |
50% | 64985.000000 | 88.000000 | 25.000000 |
75% | 97477.500000 | 91.000000 | 42.000000 |
max | 129970.000000 | 100.000000 | 3300.000000 |
와인 데이터를 살펴보니 129971 개의 와인 데이터에 대해 price, points 지표가 존재함을 확인했다. 먼저 데이터에 대한 분석을 해 본 뒤, 최종적으로는 머신러닝을 이용해 어떠한 특성이 와인의 가격지표에 영향을 미쳤는지 확인해 보고자 한다. 먼저 확인 가능한 지표들은 country, province, region_1, region_2, variety winery 등이다.
wine[wine.price.notna()].sort_values("price").head()
Unnamed: 0 | country | description | designation | points | price | province | region_1 | region_2 | taster_name | taster_twitter_handle | title | variety | winery | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
20484 | 20484 | US | Fruity, soft and rather sweet, this wine smell... | NaN | 85 | 4.0 | California | Clarksburg | Central Valley | Jim Gordon | @gordone_cellars | Dancing Coyote 2015 White (Clarksburg) | White Blend | Dancing Coyote |
112919 | 112919 | Spain | Nice on the nose, this has a leafy note and a ... | Estate Bottled | 84 | 4.0 | Levante | Yecla | NaN | Michael Schachner | @wineschach | Terrenal 2010 Estate Bottled Tempranillo (Yecla) | Tempranillo | Terrenal |
59507 | 59507 | US | Sweet and fruity, this canned wine feels soft ... | Unoaked | 83 | 4.0 | California | California | California Other | Jim Gordon | @gordone_cellars | Pam's Cuties NV Unoaked Chardonnay (California) | Chardonnay | Pam's Cuties |
31530 | 31530 | US | Packaged in a cute yellow recyclable Tetrapak,... | NaN | 84 | 4.0 | California | California | California Other | NaN | NaN | Bandit NV Chardonnay (California) | Chardonnay | Bandit |
61768 | 61768 | Spain | This opens with standard cherry and berry arom... | NaN | 84 | 4.0 | Levante | Yecla | NaN | Michael Schachner | @wineschach | Terrenal 2010 Cabernet Sauvignon (Yecla) | Cabernet Sauvignon | Terrenal |
wine.country.value_counts()
#국가 단위
US 54504 France 22093 Italy 19540 Spain 6645 Portugal 5691 Chile 4472 Argentina 3800 Austria 3345 Australia 2329 Germany 2165 New Zealand 1419 South Africa 1401 Israel 505 Greece 466 Canada 257 Hungary 146 Bulgaria 141 Romania 120 Uruguay 109 Turkey 90 Slovenia 87 Georgia 86 England 74 Croatia 73 Mexico 70 Moldova 59 Brazil 52 Lebanon 35 Morocco 28 Peru 16 Ukraine 14 Serbia 12 Czech Republic 12 Macedonia 12 Cyprus 11 India 9 Switzerland 7 Luxembourg 6 Bosnia and Herzegovina 2 Armenia 2 Slovakia 1 China 1 Egypt 1 Name: country, dtype: int64
wine.province.value_counts()
#주 단위
California 36247 Washington 8639 Bordeaux 5941 Tuscany 5897 Oregon 5373 ... Messinia 1 Markopoulo 1 Paardeberg 1 Krania Olympus 1 Neuchâtel 1 Name: province, Length: 425, dtype: int64
와인의 가격을 좌지우지하는 것중, 몇년산 와인인지가 중요하다는데, 확인 해보자.
num_list=[]
for i in list(range(1800,2022)):
num_list.append(str(i))
##연도를 체크할 연도 리스트를 만든다.
title_list = wine.title.apply(lambda x: list(x.split()))
#apply함수로 wine.title의 값을 받아 띄어쓰기로 나누고 리스트로 전환,
#map함수를 안써도 될듯.
title_list
0 [Nicosia, 2013, Vulkà, Bianco, (Etna)] 1 [Quinta, dos, Avidagos, 2011, Avidagos, Red, (... 2 [Rainstorm, 2013, Pinot, Gris, (Willamette, Va... 3 [St., Julian, 2013, Reserve, Late, Harvest, Ri... 4 [Sweet, Cheeks, 2012, Vintner's, Reserve, Wild... ... 129966 [Dr., H., Thanisch, (Erben, Müller-Burggraef),... 129967 [Citation, 2004, Pinot, Noir, (Oregon)] 129968 [Domaine, Gresser, 2013, Kritt, Gewurztraminer... 129969 [Domaine, Marcel, Deiss, 2012, Pinot, Gris, (A... 129970 [Domaine, Schoffit, 2012, Lieu-dit, Harth, Cuv... Name: title, Length: 129971, dtype: object
year_list = []
for i in title_list:
flag=False
for j in i:
if j in num_list:
year_list.append(j)
flag= True
break
if flag==False:
year_list.append("Na")
#연도 적혀있으면 연도로, 없으면 Na로 값을 변경
len(year_list)
129971
len(wine.title)
129971
어찌 저찌 햇는데, 타이틀에서 연도를 뽑아낼 때 이상하게도 양이 증가되었다. 아무래도 title 내에 연도가 두번 이상 나오는 경우가 있는 것 같아 확인해보자. (break문 사용으로 해결하였다.)
year_title=[]
non_year_title=[]
for i in title_list:
flag = False
for j in i:
if j in num_list:
flag = True
year_title.append(i)
break#추가됨
if flag==False:
non_year_title.append(i)
len(year_title)
125360
len(non_year_title)
4611
len(year_title)+len(non_year_title)
129971
검색해보니 NV의 의미가 non-vintage 와인이라고 해서, 여러 연도의 와인을 섞어 만든 것이라고 한다. 연도가 표시되지 않은 데이터가 NV가 모두 적혀있는지 확인해보기로 하였다. 위의 연도리스트에 NV를 추가해서 NA 대신 NV로 다시 넣어보자.
num_list=[]
for i in list(range(1800,2022)):
num_list.append(str(i))
num_list.append('NV')
##연도를 체크할 연도 리스트를 만든다.
year_title=[]
non_year_title=[]
year_list = []
for i in title_list:
flag = False
for j in i:
if j in num_list:
flag = True
year_list.append(j)
year_title.append(i)
break#추가됨
if flag==False:
non_year_title.append(i)
len(year_title)
129971
len(non_year_title)
0
예상대로 NV와인만 연도가 기입되어 있지 않았다. 이제 와인 데이터 프레임에 연도를 추가해보자.
wine["year"] = year_list
wine.head()
Unnamed: 0 | country | description | designation | points | price | province | region_1 | region_2 | taster_name | taster_twitter_handle | title | variety | winery | year | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | Italy | Aromas include tropical fruit, broom, brimston... | Vulkà Bianco | 87 | NaN | Sicily & Sardinia | Etna | NaN | Kerin O’Keefe | @kerinokeefe | Nicosia 2013 Vulkà Bianco (Etna) | White Blend | Nicosia | 2013 |
1 | 1 | Portugal | This is ripe and fruity, a wine that is smooth... | Avidagos | 87 | 15.0 | Douro | NaN | NaN | Roger Voss | @vossroger | Quinta dos Avidagos 2011 Avidagos Red (Douro) | Portuguese Red | Quinta dos Avidagos | 2011 |
2 | 2 | US | Tart and snappy, the flavors of lime flesh and... | NaN | 87 | 14.0 | Oregon | Willamette Valley | Willamette Valley | Paul Gregutt | @paulgwine | Rainstorm 2013 Pinot Gris (Willamette Valley) | Pinot Gris | Rainstorm | 2013 |
3 | 3 | US | Pineapple rind, lemon pith and orange blossom ... | Reserve Late Harvest | 87 | 13.0 | Michigan | Lake Michigan Shore | NaN | Alexander Peartree | NaN | St. Julian 2013 Reserve Late Harvest Riesling ... | Riesling | St. Julian | 2013 |
4 | 4 | US | Much like the regular bottling from 2012, this... | Vintner's Reserve Wild Child Block | 87 | 65.0 | Oregon | Willamette Valley | Willamette Valley | Paul Gregutt | @paulgwine | Sweet Cheeks 2012 Vintner's Reserve Wild Child... | Pinot Noir | Sweet Cheeks | 2012 |
맨 마지막 줄에 연도가 추가된 것을 확인하였다.
이제 데이터 분석이 가능한 부분만 고려해서 몇가지를 체크해보자
wine.groupby('country').mean().price.sort_values()
country Ukraine 9.214286 Bosnia and Herzegovina 12.500000 India 13.333333 Armenia 14.500000 Bulgaria 14.645390 Romania 15.241667 Macedonia 15.583333 Slovakia 16.000000 Cyprus 16.272727 Moldova 16.745763 China 18.000000 Peru 18.062500 Georgia 19.321429 Morocco 19.500000 Chile 20.786458 Greece 22.364425 Luxembourg 23.333333 Brazil 23.765957 Czech Republic 24.250000 Serbia 24.500000 Argentina 24.510117 Turkey 24.633333 South Africa 24.668987 Slovenia 24.812500 Croatia 25.450704 Portugal 26.218256 Uruguay 26.403670 Mexico 26.785714 New Zealand 26.931785 Spain 28.215275 Lebanon 30.685714 Austria 30.762772 Israel 31.768916 Australia 35.437663 Canada 35.712598 US 36.573464 Italy 39.663770 Hungary 40.648276 France 41.139120 Germany 42.257547 England 51.681159 Switzerland 85.285714 Egypt NaN Name: price, dtype: float64
df = wine.groupby('year').mean().price.sort_values()
plt.bar(df.index, df.values)
plt.xticks(rotation=90)
plt.title('연도별 와인가격')
plt.show()
df2 = wine.groupby('country').mean().price.sort_values()
plt.bar(df2.index, df2.values)
plt.title("국가별 와인가격")
plt.xticks(rotation=90)
plt.xlabel('Country')
plt.show()
적당히 정렬했는데, 국가와 생산연도에 따라 가격 평균이 굉장히 높은 수준의 차이를 보여주었다. 대략적으로 영향이 있을것으로 보여짐
데이터가 너무 방대해 확실히 시각화하기 어려웠다. 프랑스가 와인이 유명하니 프랑스 와인으로 한정지어보자
wine_France = wine[wine.country == 'France']
df = wine_France.sort_values('price')
df = df[df.price.notna()]
df.price
5801 5.0 105918 5.0 5789 5.0 122407 5.0 67690 6.0 ... 113564 2000.0 65352 2000.0 98380 2500.0 15840 2500.0 80290 3300.0 Name: price, Length: 17776, dtype: float64
df2 = df.groupby('year').price.mean()
df2
year 1945 350.000000 1982 64.000000 1985 138.000000 1988 148.750000 1989 85.000000 1990 170.250000 1992 71.500000 1994 100.800000 1995 83.928571 1996 110.230769 1997 40.333333 1998 74.385965 1999 63.587302 2000 75.515152 2001 37.966667 2002 133.666667 2003 49.080000 2004 72.515789 2005 65.393189 2006 63.343458 2007 52.022099 2008 51.653226 2009 55.705434 2010 44.112755 2011 41.205517 2012 33.930590 2013 40.977522 2014 39.998404 2015 26.676296 2016 17.602140 NV 47.818705 Name: price, dtype: float64
plt.bar(df2.index, df2.values)
plt.title("프랑스 와인 연도별 가격 평균")
plt.xticks(rotation=90)
plt.show()
전체적으로 과거로 갈 수록 값어치가 올라가는 경향이 있으나, 1997년이나 2001년 등 그렇지 않은 경우도 존재. 당시의 포도가 흉작이었음을 짐작 할 수 있었다. 1945년이 너무 가치가 앞도적으로 높아 outlier 체크를 해보려고 한다.
df[df.year=='1945']
Unnamed: 0 | country | description | designation | points | price | province | region_1 | region_2 | taster_name | taster_twitter_handle | title | variety | winery | year | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
117205 | 117205 | France | For any serious fan of Rivesaltes, this is a m... | Legend Vintage | 95 | 350.0 | Languedoc-Roussillon | Rivesaltes | NaN | Lauren Buzzeo | @laurbuzz | Gérard Bertrand 1945 Legend Vintage Red (Rives... | Red Blend | Gérard Bertrand | 1945 |
확인해 보니 단 하나의 와인이 350으로 가격이 높게 책정되었음을 볼 수 있음
데이터 부족으로 이상치로 가정하고 다시 하면
df3 = df2[df2.index !='1945']
plt.bar(df3.index, df3.values, color='lightblue')
plt.plot(df3.index, df3.values, color='r')
plt.title("프랑스 와인 연도별 가격 평균")
plt.xticks(rotation=90)
plt.show()
이렇게 와인의 생산년도, 생산국가에 따라 와인의 가격이 천차만별임을 알 수 있었다. 이제 머신러닝을 이용해 어떠한 특징이 와인에 큰 영향을 주는지 알아보자.
'데이터 시각화 분석' 카테고리의 다른 글
취미로 하는 데이터 분석 시리즈05(이미지 분류/Dacon 공모전 CNN 클론 코딩) (0) | 2022.03.04 |
---|---|
취미로 하는 데이터 분석 시리즈04-2(기원후 1000년에 와인을 만들었다면 그 가격은 얼마일까?) (0) | 2022.03.01 |
취미로 하는 데이터 분석 시리즈03(Instagram 팔로워 수 데이터 분석) (0) | 2022.02.23 |
취미로 하는 데이터 분석 시리즈02(Covid 확진자 데이터 분석) (0) | 2022.02.22 |
취미로 하는 데이터 분석 시리즈01(reddit 에서 우수하다고 생각하는 대학 순위) (0) | 2022.02.22 |