Report 3

by Kaitlyn Keil and Kevin Zhang

April 2017

UK Nutrient Databank

User Documentation


In [1]:
""" This file contains code used to analyze the
UK Food Nutrient Databank, the information for which can be found
at the above links.

The following packages are required to run this code.
"""

from __future__ import print_function, division
import pandas as pd

import sys
import numpy as np
import math
import matplotlib.pyplot as plt
from sklearn.feature_extraction import DictVectorizer
%matplotlib inline
import seaborn as sns

from collections import defaultdict, Counter
import statsmodels.formula.api as smf

In [2]:
def ReadProximates():
    """ Reads the correct sheet from the Excel Spreadsheet downloaded from the databank.
    Cleans the macronutrient data and replaces non-numerical entries with 0.
    
    Returns: cleaned DataFrame
    """
    df = pd.read_excel('dietary.xls', sheetname='Proximates')
    column_list = ['Water (g)', 'Protein (g)', 'Fat (g)', 'Carbohydrate (g)', 'Total sugars (g)']
    
    df['Water'] = pd.to_numeric(df['Water (g)'], errors='coerce')
    df['Protein'] = pd.to_numeric(df['Protein (g)'], errors='coerce')
    df['Fat'] = pd.to_numeric(df['Fat (g)'], errors='coerce')
    df['Carbohydrate'] = pd.to_numeric(df['Carbohydrate (g)'], errors='coerce')
    df['Sugars'] = pd.to_numeric(df['Total sugars (g)'], errors='coerce')
    
    df['Water'].replace([np.nan], 0, inplace=True)
    df['Protein'].replace([np.nan], 0, inplace=True)
    df['Fat'].replace([np.nan], 0, inplace=True)
    df['Carbohydrate'].replace([np.nan], 0, inplace=True)
    df['Sugars'].replace([np.nan], 0, inplace=True)
        
    return df

In [3]:
tester = ReadProximates()

In [4]:
# Plot clusters on a 2D log scale for first-glance. They do not appear to be particularly differentiated.
# Log coordinates are better for visualization in this instance.

x_vals = 'Protein'
y_vals = 'Carbohydrate'
z_vals = 'Fat'

food_group_dict = {'A':['Cereals','peru'], 'B':['Dairy','beige'], 'C':['Egg','paleturquoise'],
                  'D':['Vegetable','darkolivegreen'], 'F':['Fruit','firebrick'], 'G':['Nuts','saddlebrown'],
                  'J':['Fish','slategray'],'M':['Meat','indianred'], 'O':['Fat','khaki']}

In [5]:
ax = plt.subplot(111)
for key,val in food_group_dict.items():
    df = tester[tester.Group.str.startswith(key, na=False)]
    ax.scatter(df[x_vals],df[y_vals],df[z_vals],color=val[1],label = val[0])
plt.xscale('log')
plt.yscale('log')
ax.set_xlabel(x_vals+' (g)')  
ax.set_ylabel(y_vals+' (g)')
ax.legend()


Out[5]:
<matplotlib.legend.Legend at 0x7f1b949d4240>

In [6]:
from mpl_toolkits import mplot3d

ax = plt.subplot(projection='3d')
#ax.scatter3D(tester[x_vals], tester[y_vals], tester[z_vals])

for key,val in food_group_dict.items():
    df = tester[tester.Group.str.startswith(key, na=False)]
    ax.scatter3D(np.log(df[x_vals]),np.log(df[y_vals]),np.log(df[z_vals]),color=val[1],label = val[0])
#plt.xscale('log')
#plt.yscale('log')
ax.set_xlabel(x_vals+' (log g)')  
ax.set_ylabel(y_vals+' (log g)')
ax.set_zlabel(z_vals+' (log g)')
ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)


Out[6]:
<matplotlib.legend.Legend at 0x7f1b947a2f60>

In [7]:
def ThreeDPlot(pred_cat, actual_cat, ax, actual_label, colors = ['firebrick', 'peru']):
    """ Creates a 3D log log plot on the requested subplot.
    Arguments: 
    pred_cat = predicted dataframe for a category
    actual_cat = dataframe of the real category
    ax = plt axis instance
    actual_label = string with label for the actual category
    colors = list with two entries of strings for color names
    """
    ax.scatter3D(np.log(pred_cat.Protein),np.log(pred_cat.Carbs), np.log(pred_cat.Fat), c = colors[0], label = 'Predicted Group')
    ax.scatter3D(np.log(actual_cat.Protein),np.log(actual_cat.Carbohydrate), np.log(actual_cat.Fat), c = colors[1], label = actual_label, alpha= .5)
    ax.view_init(elev=10, azim=45)
    
    ax.set_xlabel('Protein (log g)')
    ax.set_ylabel('Carbohydrate (log g)')
    ax.set_zlabel('Fat (log g)')
    plt.legend()

In [8]:
#  Create the categories for the different food pyramid groups.
#   Labels were assigned by attempting to find the best match
#   with the generated groups.

cereals = tester[tester.Group.str.startswith('A', na=False)]
cereals['Label'] = cereals.Water*0+3

fruits = tester[tester.Group.str.startswith('F', na=False)]
fruits['Label'] = fruits.Water*0+4

veggies = tester[tester.Group.str.startswith('D', na=False)]
veggies['Label'] = veggies.Water*0+0

dairy = tester[tester.Group.str.startswith('B', na=False)]
dairy['Label'] = dairy.Water*0+2

oils = tester[tester.Group.str.startswith('O', na=False)]
oils['Label'] = oils.Water*0+5

m1 = tester[tester.Group.str.startswith('J', na=False)]
m2 = tester[tester.Group.str.startswith('M', na=False)]
meats = pd.concat([m1,m2])
meats['Label'] = meats.Water*0+1

# Create a dataframe using only these categories (drops nuts, eggs, soups/misc, etc)
all_these = pd.concat([cereals, fruits, veggies, dairy, oils, meats])


/home/kaitlyn/anaconda3/lib/python3.5/site-packages/ipykernel/__main__.py:6: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
/home/kaitlyn/anaconda3/lib/python3.5/site-packages/ipykernel/__main__.py:9: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
/home/kaitlyn/anaconda3/lib/python3.5/site-packages/ipykernel/__main__.py:12: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
/home/kaitlyn/anaconda3/lib/python3.5/site-packages/ipykernel/__main__.py:15: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
/home/kaitlyn/anaconda3/lib/python3.5/site-packages/ipykernel/__main__.py:18: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

In [9]:
from sklearn.cluster import KMeans

# Selects the appropriate macronutrient columns to feed to the kmeans algorithm
water = pd.Series(all_these.Water, name='Water')
protein = pd.Series(all_these.Protein, name='Protein')
fat = pd.Series(all_these.Fat, name='Fat')
carbs = pd.Series(all_these.Carbohydrate, name='Carbs')
sugars = pd.Series(all_these['Sugars'], name='Sugars')

# Create a new DataFrame using only the macronutrient columns
X = pd.concat([water, protein,fat,carbs,sugars], axis=1)
X.fillna(0)
kmeans = KMeans(n_clusters=6, random_state=0)
kmeans.fit(X.dropna())
y_kmeans = kmeans.predict(X)

In [10]:
# Created clusters from the kmeans algorithm

ax = plt.subplot(projection='3d')

ax.scatter3D(np.log(X.Protein),np.log(X.Carbs), np.log(X.Fat), c = y_kmeans)
ax.view_init(elev=10, azim=45)
    
ax.set_xlabel('Protein (log g)')
ax.set_ylabel('Carbohydrate (log g)')
ax.set_zlabel('Fat (log g)')


Out[10]:
<matplotlib.text.Text at 0x7f1b9011e198>

In [11]:
# Create a way to select the categories

predicted_labels = pd.DataFrame(y_kmeans, index=X.index).astype(float)
X['predictions'] = predicted_labels

In [12]:
# Separate out the categories for individual analysis

labeled0 = X[X.predictions == 0]
labeled1 = X[X.predictions == 1]
labeled2 = X[X.predictions == 2]
labeled3 = X[X.predictions == 3]
labeled4 = X[X.predictions == 4]
labeled5 = X[X.predictions == 5]

Following are two examples, plotted on the 3d log scale. For the rest of the comparisons, see the bottom of the journal.


In [13]:
ax = plt.subplot(projection='3d')
ThreeDPlot(labeled1, meats, ax, 'Meats', ['firebrick','slategray'])



In [14]:
ax = plt.subplot(projection='3d')
ThreeDPlot(labeled4, fruits, ax, 'Fruits', ['firebrick','purple'])



In [15]:
# Use this to generate an accuracy score. Ours was 53%

from sklearn.metrics import accuracy_score

accuracy_score(all_these.Label,predicted_labels)


Out[15]:
0.532258064516129

In [16]:
# Look at confusion matrix for some idea of accuracy. Meats has the highest rate of matching.

from sklearn.metrics import confusion_matrix
mat = confusion_matrix(all_these.Label, predicted_labels)
sns.heatmap(mat.T, square=True)
plt.xlabel('true label')
plt.ylabel('predicted label')

# Veggies are 0
# Meats are 1
# Dairy is 2
# Cereals are 3
# Fruits are 4
# Oils are 5


Out[16]:
<matplotlib.text.Text at 0x7f1b88560f60>

In [17]:
all_these['guess'] = predicted_labels[0]
all_these['correct_guess'] = np.where((all_these.Label == all_these.guess), True, False)

In [45]:
def HowMatched3D(df, label_int, actual_label):
    """ Creates a 3D log log plot on the requested subplot.
    Arguments: 
    pred_cat = predicted dataframe for a category
    actual_cat = dataframe of the real category
    ax = plt axis instance
    actual_label = string with label for the actual category
    colors = list with two entries of strings for color names
    """
    ax = plt.subplot(projection='3d')
    TP = df[(df.Label == label_int)&(df.correct_guess==True)]
    FP = df[(df.guess == label_int)&(df.correct_guess==False)]
    FN = df[(df.Label == label_int)&(df.correct_guess==False)]
    print('Matches:',len(TP), 'In Group, is not '+actual_label+':',len(FP), 'Not in Group, is '+actual_label+':',len(FN))
    ax.scatter3D(np.log(TP.Protein),np.log(TP.Carbohydrate), np.log(TP.Fat), c = 'purple', label = 'In Group, is '+actual_label)
    ax.scatter3D(np.log(FP.Protein),np.log(FP.Carbohydrate), np.log(FP.Fat), c = 'crimson', label = 'In Group, is not '+actual_label)
    ax.scatter3D(np.log(FN.Protein),np.log(FN.Carbohydrate), np.log(FN.Fat), c = 'darkgreen', label = 'Not in Group, is '+actual_label)
    ax.view_init(elev=10, azim=45)
    
    ax.set_xlabel('Protein (log g)')
    ax.set_ylabel('Carbohydrate (log g)')
    ax.set_zlabel('Fat (log g)')
    plt.legend()

In [46]:
HowMatched3D(all_these, 0, 'Vegetable')


Matches: 489 In Group, is not Vegetable: 587 Not in Group, is Vegetable: 297

In [47]:
HowMatched3D(all_these, 1, 'Meat')


Matches: 691 In Group, is not Meat: 97 Not in Group, is Meat: 376

In [48]:
HowMatched3D(all_these, 2, 'Dairy')


Matches: 23 In Group, is not Dairy: 131 Not in Group, is Dairy: 260

In [49]:
HowMatched3D(all_these, 3, 'Cereal')


Matches: 237 In Group, is not Cereal: 90 Not in Group, is Cereal: 146

In [50]:
HowMatched3D(all_these, 4, 'Fruit')


Matches: 32 In Group, is not Fruit: 414 Not in Group, is Fruit: 248

In [51]:
HowMatched3D(all_these, 5, 'Oil')


Matches: 46 In Group, is not Oil: 15 Not in Group, is Oil: 7

In [53]:
all_these.groupby('guess').mean()


Out[53]:
Constant Water Protein Fat Carbohydrate Sugars Label correct_guess
guess
0.0 11093.033206 80.851673 4.950836 2.789219 7.256413 4.175372 1.310409 0.454461
1.0 10090.759894 56.492893 21.071574 14.264467 1.826015 0.410406 1.069797 0.876904
2.0 10896.275862 6.546753 9.896104 11.070779 6.094156 1.262987 1.506494 0.149351
3.0 8033.645756 14.299083 8.587156 10.388379 61.921407 20.948930 2.657492 0.724771
4.0 12138.517442 53.703363 6.178924 10.539013 24.507848 5.895964 1.273543 0.071749
5.0 7208.725490 9.529508 2.578689 84.206557 0.670492 0.201639 4.016393 0.754098

In [25]:
# 1518 correct guesses, some examples of which follow
guessed_correctly = all_these[all_these.correct_guess == True]
print(guessed_correctly['Food Name'])


140                 Biscuits, homemade, rubbing-in method
141                                            Shortbread
142                         Crunch biscuits, cream filled
143                                   Semi-sweet biscuits
144                       Sandwich biscuits, cream filled
145                                    Oatcakes, homemade
146                                  Short sweet biscuits
147                                      Oatcakes, retail
148                                Wafer biscuits, filled
149                                             Flapjacks
150                                    Wholemeal crackers
151                          Gingernut biscuits, homemade
152                   Biscuits, homemade, creaming method
153                         Biscuits, homemade, wholemeal
154                   Biscuits, melting moments, homemade
155                                    Oat based biscuits
156         Chocolate biscuits, cream filled, full coated
157                               Brandy snaps, home made
159                Wafers, filled, chocolate, full coated
160                         Sandwich biscuits, jam filled
161                                                Matzos
167                             Digestive biscuits, plain
168                       Chocolate biscuits, full coated
169                                Chocolate chip cookies
170                                        Cream crackers
171                                       Crispbread, rye
172                         Digestive biscuits, chocolate
174                                        Water biscuits
175                                    Gingernut biscuits
176              White bread, 'with added fibre', toasted
                              ...                        
2001                            Rabbit, stewed, meat only
2002         Rabbit, stewed, meat only, weighed with bone
2003             Whole turkey, roasted, weighed with bone
2004                                Whole turkey, roasted
2005    Turkey, drumsticks, roasted, meat and skin, we...
2006           Turkey, drumsticks, roasted, meat and skin
2007               Turkey, drumsticks, roasted, meat only
2008                         Turkey, skin, moist, roasted
2009                           Turkey, skin, dry, roasted
2010                       Turkey, meat, average, roasted
2011                           Turkey, dark meat, roasted
2012                          Turkey, light meat, roasted
2014                           Turkey, strips, stir-fried
2015            Turkey, light meat, self-basting, roasted
2017                                    Turkey, skin, raw
2018                                    Whole turkey, raw
2019                 Whole turkey, raw, weighed with bone
2020                                Turkey, mince, stewed
2021         Turkey, thighs, diced, casseroled, meat only
2022           Turkey, breast, fillet, grilled, meat only
2024                                     Veal, mince, raw
2025                                  Veal, mince, stewed
2027                                Veal, escalope, fried
2029                                       Venison, roast
2032           Grillsteaks, beef, chilled/frozen, grilled
2037                     Beefburgers, chilled/frozen, raw
2038                     Economy burgers, frozen, grilled
2039                         Economy burgers, frozen, raw
2040                 Beefburgers, chilled/frozen, grilled
2041                   Beefburgers, chilled/frozen, fried
Name: Food Name, dtype: object

In [26]:
# 1334 incorrect guesses. Some examples follow.

guessed_wrong = all_these[all_these.correct_guess==False]
print(guessed_wrong['Food Name'])


158                                        Cornish wafers
162                              Cheese sandwich biscuits
163                                             Fig rolls
164                                        Fruit biscuits
165                                          Krackerwheat
166            Oat based biscuits, chocolate, half coated
173                     Shortcake, chocolate, half coated
177                       White bread, 'with added fibre'
179     White bread, farmhouse or split tin, freshly b...
181                                   White bread, sliced
182                             White bread, Danish style
184                                  White bread, premium
186                                       Wheatgerm bread
188                              Wholemeal bread, average
195                                   Pappadums, takeaway
197                                               Paratha
201                                             Rye bread
203                                  White bread, average
205                               White bread, large, tin
208                  White bread, Scottish batch, wrapped
212                                         Granary bread
214                            Chapatis, made without fat
217                                  Brown bread, average
218                              Bread, speciality, white
219                                      Bread, softgrain
230                             Porridge, made with water
232                    Porridge, made with milk and water
235                        Porridge, made with whole milk
243                                    Crunchy Oat Cereal
244                                                Muesli
                              ...                        
1902                                  Liver, chicken, raw
1903                                       Heart, ox, raw
1906      Pheasant, roasted, meat only, weighed with bone
1907                      Pheasant, casseroled, meat only
1909        Pigeon, roasted, meat only, weighed with bone
1932                              Pork, steaks, raw, lean
1945    Pork, spare rib slices, grilled, lean and fat,...
1947    Pork, spare rib slices, raw, lean and fat, wei...
1955                              Pork, trimmed lean, raw
1958                               Pork, diced, raw, lean
1970                                    Pork, fat, cooked
1971                         Pork, extra trimmed fat, raw
1972                               Pork, trimmed fat, raw
1981                              Pork, crackling, cooked
1986                           Pork, leg joint, raw, lean
1991                Pork, hand, shoulder joint, raw, lean
2000                         Rabbit, stewed, meat and fat
2013                           Turkey, meat, average, raw
2016                              Turkey, light meat, raw
2023                               Turkey, dark meat, raw
2026                                  Veal, escalope, raw
2028                                         Venison, raw
2030                       Venison, casseroled, meat only
2031                     Chicken tikka, chilled, reheated
2033                               Cheeseburger, takeaway
2034                                       Whopper burger
2035                 Quarterpounder with cheese, takeaway
2036                                  Hamburger, takeaway
2042                             Chicken burger, takeaway
2043                                              Big Mac
Name: Food Name, dtype: object

Beyond this point are pairs of 3D cluster plots, to compare each generated group with the food pyramid groups.


In [27]:
ax0 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled0, meats, ax0, 'Meats', ['firebrick','slategray'])

ax1 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled0, cereals, ax1, 'Cereals', ['firebrick','peru'])

plt.legend()


Out[27]:
<matplotlib.legend.Legend at 0x7f1b884c0ac8>

In [28]:
ax2 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled0, fruits, ax2, 'Fruits', ['firebrick','purple'])

ax3 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled0, veggies, ax3, 'Vegetables', ['firebrick','darkolivegreen'])
plt.legend()


Out[28]:
<matplotlib.legend.Legend at 0x7f1b88203160>

In [29]:
ax4 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled0, dairy, ax4, 'Dairy', ['firebrick','mintcream'])

ax5 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled0, oils, ax5, 'Oils', ['firebrick','paleturquoise'])
plt.legend()


Out[29]:
<matplotlib.legend.Legend at 0x7f1b881126d8>

In [30]:
ax0 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled1, meats, ax0, 'Meats', ['firebrick','slategray'])

ax1 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled1, cereals, ax1, 'Cereals', ['firebrick','peru'])

plt.legend()


Out[30]:
<matplotlib.legend.Legend at 0x7f1b8801aac8>

In [31]:
ax2 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled1, fruits, ax2, 'Fruits', ['firebrick','purple'])

ax3 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled1, veggies, ax3, 'Vegetables', ['firebrick','darkolivegreen'])
plt.legend()


Out[31]:
<matplotlib.legend.Legend at 0x7f1b885c6ba8>

In [32]:
ax4 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled1, dairy, ax4, 'Dairy', ['firebrick','mintcream'])

ax5 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled1, oils, ax5, 'Oils', ['firebrick','paleturquoise'])
plt.legend()


Out[32]:
<matplotlib.legend.Legend at 0x7f1b88390da0>

In [33]:
ax0 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled2, meats, ax0, 'Meats', ['firebrick','slategray'])

ax1 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled2, cereals, ax1, 'Cereals', ['firebrick','peru'])

plt.legend()


Out[33]:
<matplotlib.legend.Legend at 0x7f1b7be86cf8>

In [34]:
ax2 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled2, fruits, ax2, 'Fruits', ['firebrick','purple'])

ax3 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled2, veggies, ax3, 'Vegetables', ['firebrick','darkolivegreen'])
plt.legend()


Out[34]:
<matplotlib.legend.Legend at 0x7f1b7bd80588>

In [35]:
ax4 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled2, dairy, ax4, 'Dairy', ['firebrick','mintcream'])

ax5 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled2, oils, ax5, 'Oils', ['firebrick','paleturquoise'])
plt.legend()


Out[35]:
<matplotlib.legend.Legend at 0x7f1b7bc87a90>

In [36]:
ax0 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled3, meats, ax0, 'Meats', ['firebrick','slategray'])

ax1 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled3, cereals, ax1, 'Cereals', ['firebrick','peru'])

plt.legend()


Out[36]:
<matplotlib.legend.Legend at 0x7f1b7bb861d0>

In [37]:
ax2 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled3, fruits, ax2, 'Fruits', ['firebrick','purple'])

ax3 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled3, veggies, ax3, 'Vegetables', ['firebrick','darkolivegreen'])
plt.legend()


Out[37]:
<matplotlib.legend.Legend at 0x7f1b7badba90>

In [38]:
ax4 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled3, dairy, ax4, 'Dairy', ['firebrick','mintcream'])

ax5 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled3, oils, ax5, 'Oils', ['firebrick','paleturquoise'])
plt.legend()


Out[38]:
<matplotlib.legend.Legend at 0x7f1b7b9e7080>

In [39]:
ax0 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled4, meats, ax0, 'Meats', ['firebrick','slategray'])

ax1 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled4, cereals, ax1, 'Cereals', ['firebrick','peru'])

plt.legend()


Out[39]:
<matplotlib.legend.Legend at 0x7f1b7b8e5e80>

In [40]:
ax2 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled4, fruits, ax2, 'Fruits', ['firebrick','purple'])

ax3 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled4, veggies, ax3, 'Vegetables', ['firebrick','darkolivegreen'])
plt.legend()


Out[40]:
<matplotlib.legend.Legend at 0x7f1b7b7ee6d8>

In [41]:
ax4 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled4, dairy, ax4, 'Dairy', ['firebrick','mintcream'])

ax5 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled4, oils, ax5, 'Oils', ['firebrick','paleturquoise'])
plt.legend()


Out[41]:
<matplotlib.legend.Legend at 0x7f1b7b6eec88>

In [42]:
ax0 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled5, meats, ax0, 'Meats', ['firebrick','slategray'])

ax1 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled5, cereals, ax1, 'Cereals', ['firebrick','peru'])

plt.legend()


Out[42]:
<matplotlib.legend.Legend at 0x7f1b7b5ed0f0>

In [43]:
ax2 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled5, fruits, ax2, 'Fruits', ['firebrick','purple'])

ax3 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled5, veggies, ax3, 'Vegetables', ['firebrick','darkolivegreen'])
plt.legend()


Out[43]:
<matplotlib.legend.Legend at 0x7f1b7b4c8390>

In [44]:
ax4 = plt.subplot(121, projection='3d')
ThreeDPlot(labeled5, dairy, ax4, 'Dairy', ['firebrick','mintcream'])

ax5 = plt.subplot(122, projection='3d')
ThreeDPlot(labeled5, oils, ax5, 'Oils', ['firebrick','paleturquoise'])
plt.legend()


Out[44]:
<matplotlib.legend.Legend at 0x7f1b7b3cf908>

In [ ]: