MLエンジニア見習いのスクラップブック

新米機械学習エンジニアによる技術ネタや備忘録

kaggle Datasetsのコーヒー生豆のデータ分析やってみた

はじめまして。あずペロ(@azupero_adolph)と申します。 このブログは機械学習統計学などの技術的アウトプットを残していきたいなーと思って開設してみました。
初投稿は趣味であるコーヒーに関するデータで(サクッと)分析やってみた系をアップします。 美味しいコーヒーなどを準備して時間つぶし程度に見ていただければ幸いです。
内容に関しては随時アップデートしていきます。

これはなに?
  • kaggle Datasets内のコーヒー生豆に関するデータを使って分析・可視化
  • コーヒー生豆のカッピング評価と生産国や品種の関係性を探る
使用したデータについて

コーヒーに関するデータで色々やりたいなーと思って探していくうちにkaggleのDatasets内にあるこちらのデータを今回は使用させていただきました。

www.kaggle.com

(僕も日々kaggleに取り組んではいるのですがいまだメダルもない雑魚contributorなので網膜コンペ頑張っていきたい・・・。)

データの内容について

今回はコーヒー生豆の生産情報(生産国, 品種, 精製法 etc.)とカッピングスコアがまとめられています。 まず、コーヒー生豆とは何ぞや?という感じですが、そもそもコーヒー豆の正体はコーヒーチェリーと呼ばれるサクランボのような赤い果実の種子です(下記画像参照)。その種を焙煎することで日頃僕たちが目にする茶色のコーヒー豆になります。

http://lightupcoffee.com/wp-content/uploads/2016/05/pngbase64f5fb45529900dfeb-1024x680.png lightupcoffee.com

収穫されたコーヒーチェリーは精製処理を通して生豆として各消費国に輸出されていきます。精製処理というのはコーヒーチェリーから種子を取り出してコーヒー生豆として出荷できるような状態にする前処理のことを指します。 サクランボを想像して頂くとイメージが湧きやすいと思いますが、コーヒーチェリーから種子を取り出すと種子の周りにはべとべとした粘着質が付着しています。この状態で発酵槽に漬けて水洗したのが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')

f:id:azupero_adolph:20190729232842p:plain このmisingnoというライブラリ、欠損値を可視化してくれるのでわかりやすいです。

ここからいろいろと前処理や今回の分析に使用しないカラムなどを除いていきました。
(Farm.Nameなどの欠損値は''UNK'''(Unknow)に置換するなど。)
(そんなに特別なことはやっていませんがまたあとでのっけます。) f:id:azupero_adolph:20190729233446p:plain

分析してみよう!

データ整形も済んだところでカッピングの各評価項目の分布を眺めてみます。

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();

f:id:azupero_adolph:20190729233908p:plain

当初の目論見では僕はコーヒーの持つ甘味と各生産情報との関係性を探ろうとしたのですが、甘味(ほかにもクリーンさとか均一性とか)がかなり満点に偏っている状態。実際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();

f:id:azupero_adolph:20190729234907p:plain

メジャーな生産国が集まる中南米が多いようです。

ではカッピングの総合得点と品種の関係性を見ていきましょう。

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)

f:id:azupero_adolph:20190729235146p:plain

  • 平均値で見るとSumatora Lintong(飲んだことない)が高いですね。
  • 全体のレンジで見るとコーヒーの起源でもあるエチオピアの原生種や、ケニアでよく栽培されている品種のSL34も目立ちます。
まとめ

かなり駆け足で進めてしまいました。
コーヒーの品種の説明などいろいろすっ飛ばしてしまいましたが初投稿故お許しください。(あとで追記します。
こういったコーヒーについてのデータ分析はあまり見たことがなかったのでこれから増えていけばいいなーと思っています。
今回のデータには生産者の名前だとか総重量だとか取引商社のカラムが目立つ一方で、コーヒーは農作物なのでコーヒーの甘味がどんな変数と相関があるのか?といった関係性を探るためにはもっと地質だとか乾燥日数だとかより細かい情報あるとより分析が面白くなると思いました。