kaggle Datasetsのコーヒー生豆のデータ分析やってみた
はじめまして。あずペロ(@azupero_adolph)と申します。
このブログは機械学習や統計学などの技術的アウトプットを残していきたいなーと思って開設してみました。
初投稿は趣味であるコーヒーに関するデータで(サクッと)分析やってみた系をアップします。
美味しいコーヒーなどを準備して時間つぶし程度に見ていただければ幸いです。
内容に関しては随時アップデートしていきます。
これはなに?
- kaggle Datasets内のコーヒー生豆に関するデータを使って分析・可視化
- コーヒー生豆のカッピング評価と生産国や品種の関係性を探る
使用したデータについて
コーヒーに関するデータで色々やりたいなーと思って探していくうちにkaggleのDatasets内にあるこちらのデータを今回は使用させていただきました。
(僕も日々kaggleに取り組んではいるのですがいまだメダルもない雑魚contributorなので網膜コンペ頑張っていきたい・・・。)
データの内容について
今回はコーヒー生豆の生産情報(生産国, 品種, 精製法 etc.)とカッピングスコアがまとめられています。 まず、コーヒー生豆とは何ぞや?という感じですが、そもそもコーヒー豆の正体はコーヒーチェリーと呼ばれるサクランボのような赤い果実の種子です(下記画像参照)。その種を焙煎することで日頃僕たちが目にする茶色のコーヒー豆になります。
収穫されたコーヒーチェリーは精製処理を通して生豆として各消費国に輸出されていきます。精製処理というのはコーヒーチェリーから種子を取り出してコーヒー生豆として出荷できるような状態にする前処理のことを指します。
サクランボを想像して頂くとイメージが湧きやすいと思いますが、コーヒーチェリーから種子を取り出すと種子の周りにはべとべとした粘着質が付着しています。この状態で発酵槽に漬けて水洗したのがWashedと呼ばれる精製法でコーヒー生豆のもつ成分がクリアに現れます。
Washedとは別にコーヒーチェリーのまま乾燥させて脱穀させるというNaturalという精製処理があり、Washedに比べワイニーな芳香が印象的になります。
最後にHoneyも今回のデータで登場しますが、これはNaturalに似ているんですが果実の状態のままではなくて果肉を取り除いた状態で乾燥させる方法になり、一般的にはWashedとNaturalの中間のフレーバーに位置するとよく表現されます。
では、カッピングスコアとは何でしょうか?
簡単に言えばコーヒーの風味を総合的にスコアリングして評価することを指します。
評価項目としては
- アロマ
- フレーバー
- アフターテイスト
- 酸味
- ボディ
- バランス
- 均一性
- クリーン性
- 総合
- 欠点
でトータル100点満点でスコアリングしてきます。この得点が80点を超すといわゆるスペシャルティコーヒーと呼ばれる豆になります。
データ前処理
さて、前置きが長くなってしまいましたが早速データの中身を見ていきたいと思います。
まずはライブラリとデータのインプットから。
# import library import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import missingno as msno %matplotlib inline # input data df = pd.read_csv('Coffee-modified.csv')
データの形状をまずは見てみましょう。
# DataFrameの形状チェック print('Count of row : {} & Count of column : {}'.format(df.shape[0], df.shape[1]))
Count of row : 1319 & Count of column : 44
- レコード数としては比較的ミニマムなデータ
- もっといいスペシャルティコーヒーのデータがあればぜひ教えてください~
次に欠損値を含めたDataFrameの情報をチェックします。
# DataFrameの形状に加えてデータ型などを確認
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 1319 entries, 0 to 1318 Data columns (total 44 columns): ID 1312 non-null object Species 1319 non-null object Owner 1310 non-null object Country.of.Origin 1316 non-null object Farm.Name 961 non-null object Lot.Number 276 non-null object Mill 1007 non-null object ICO.Number 1169 non-null object Company 1105 non-null object Altitude 1092 non-null object Region 1257 non-null object Producer 1084 non-null object Number.of.Bags 1314 non-null object Bag.Weight 1314 non-null object In.Country.Partner 1314 non-null object Harvest.Year 1266 non-null object Grading.Date 1313 non-null object Owner.1 1305 non-null object Variety 1110 non-null object Processing.Method 1159 non-null object Aroma 1311 non-null object Flavor 1309 non-null object Aftertaste 1309 non-null object Acidity 1309 non-null object Body 1309 non-null float64 Balance 1309 non-null float64 Uniformity 1309 non-null float64 Clean.Cup 1307 non-null float64 Sweetness 1308 non-null float64 Cupper.Points 1308 non-null object Total.Cup.Points 1308 non-null object Moisture 1308 non-null object Category.One.Defects 1308 non-null object Quakers 1307 non-null object Color 1092 non-null object Category.Two.Defects 1307 non-null float64 Expiration 1307 non-null object Certification.Body 1307 non-null object Certification.Address 1307 non-null object Certification.Contact 1307 non-null object unit_of_measurement 1307 non-null object altitude_low_meters 1081 non-null float64 altitude_high_meters 1081 non-null float64 altitude_mean_meters 1081 non-null float64 dtypes: float64(9), object(35) memory usage: 453.5+ KB
- 多数の欠損値が存在する特徴量がある
- 欠損値が本当に欠損値なのかを見てみる必要がある(情報を持たないor欠損値自体が情報を持つ)
# ざっと欠損値の確認 ax = msno.matrix(df) ax.tick_params(color='w', labelcolor='w')
このmisingnoというライブラリ、欠損値を可視化してくれるのでわかりやすいです。
ここからいろいろと前処理や今回の分析に使用しないカラムなどを除いていきました。
(Farm.Nameなどの欠損値は''UNK'''(Unknow)に置換するなど。)
(そんなに特別なことはやっていませんがまたあとでのっけます。)
分析してみよう!
データ整形も済んだところでカッピングの各評価項目の分布を眺めてみます。
cupping_list = ['Aroma', 'Flavor', 'Aftertaste', 'Acidity', 'Body', 'Balance', 'Uniformity', 'Clean.Cup', 'Sweetness', 'Cupper.Points', 'Total.Cup.Points'] with plt.style.context('ggplot'): df[cupping_list].hist(bins=25, figsize=(20, 15), ec='k') plt.show();
当初の目論見では僕はコーヒーの持つ甘味と各生産情報との関係性を探ろうとしたのですが、甘味(ほかにもクリーンさとか均一性とか)がかなり満点に偏っている状態。実際25%タイルで満点になっていることもあり、扱いが難しいデータでした。
気を取り直して今回のデータの生産国について。どの国の情報が多いのでしょうか。
with plt.style.context('bmh'): fig = plt.figure(figsize=(15,10)) ax = fig.add_subplot(1,1,1) ax.set_xlabel(_, color='w') ax.set_ylabel(_, color='w') ax.tick_params(color='w', labelcolor='w') sns.countplot(data=df, y=df['Country.of.Origin'], order=list(df['Country.of.Origin'].value_counts().index)) plt.show();
メジャーな生産国が集まる中南米が多いようです。
ではカッピングの総合得点と品種の関係性を見ていきましょう。
with plt.style.context('bmh'): fig = plt.figure(figsize=(30,10)) ax = fig.add_subplot(1,1,1) ax.set_xlabel(_, color='w') ax.set_ylabel(_, color='w') ax.tick_params(color='w', labelcolor='w') sns.barplot(y='Variety', x='Total.Cup.Points', data=df) ax.set_xlim(80,88)
まとめ
かなり駆け足で進めてしまいました。
コーヒーの品種の説明などいろいろすっ飛ばしてしまいましたが初投稿故お許しください。(あとで追記します。
こういったコーヒーについてのデータ分析はあまり見たことがなかったのでこれから増えていけばいいなーと思っています。
今回のデータには生産者の名前だとか総重量だとか取引商社のカラムが目立つ一方で、コーヒーは農作物なのでコーヒーの甘味がどんな変数と相関があるのか?といった関係性を探るためにはもっと地質だとか乾燥日数だとかより細かい情報あるとより分析が面白くなると思いました。