Group sizes

Get all unique size labels from the database.


In [98]:
%matplotlib inline
import numpy as np
import pandas as pd
from scipy.stats import entropy
from tabulate import tabulate
from pymongo import MongoClient
import matplotlib.pyplot as plt
plt.style.use('seaborn')
plt.rcParams["figure.figsize"] = (20,8)


db = MongoClient()['stores']

TOTAL_NUMBER_OF_PRODUCTS = db.data.count()

results = db.data.aggregate(
    [
        {
            "$group": {
                "_id": "$size",
                "count": {"$sum": 1},
            }
        },
        {
            "$sort": {
                "count": -1,
            }
        }
    ]
)

ALL_SIZES = [(str(x['_id']), x['count']) for x in list(results)]
print('Number of uniq. sizes: {}'.format(len(ALL_SIZES)))


Number of uniq. sizes: 1117

Sizes per distributor


In [99]:
DISTRIBUTORS = list(db.data.distinct("source"))
results = db.data.aggregate(
    [
        {
            "$group": {
                "_id": "$source",
                "sizes": {"$addToSet": "$size"},
            }
        },
        {
            "$project": {
                "_id": 1,
                "count": {"$size": "$sizes"}
            }
        },
        {
            "$sort": {
                "count": -1,
            }
        }
    ]
)
SIZES_PER_DISTRIBUTOR = [
    (str(x['_id']), x['count']) 
    for x in list(results)
]
print(tabulate(SIZES_PER_DISTRIBUTOR, 
               headers=['Distributor', 'Number of uniq. Sizes'], 
               tablefmt="simple"))

df_values_by_key = pd.DataFrame(SIZES_PER_DISTRIBUTOR, 
                                index=[x[0] for x in SIZES_PER_DISTRIBUTOR], 
                                columns=['Distributor', 'Sizes'])
df_values_by_key.iloc[::-1].plot.barh()


Distributor      Number of uniq. Sizes
-------------  -----------------------
jeneva                             491
shemeka                            286
marsha                             222
kina                               189
rubi                               186
larry                              107
ignacia                            106
wendell                             94
patti                               81
denisha                             74
evie                                64
allegra                             64
major                               63
titus                               50
carey                               35
ciara                               30
yolande                             28
rossana                             27
joanie                              17
zack                                14
Out[99]:
<matplotlib.axes._subplots.AxesSubplot at 0x10a167b38>

Print joint table with first 60 sizes.


In [100]:
import operator

all_sizes_table = []
number_of_sizes = 180
for sizes in zip(ALL_SIZES[0:number_of_sizes:3],
                 ALL_SIZES[1:number_of_sizes:3],
                 ALL_SIZES[2:number_of_sizes:3]):
    all_sizes_table.append(list(reduce(operator.add, sizes)))

print(
    tabulate(
        all_sizes_table[:60], 
        headers=3*['Size', 'Number of Products'], 
        tablefmt="simple"))


Size          Number of Products  Size         Number of Products  Size        Number of Products
----------  --------------------  ---------  --------------------  --------  --------------------
M                         202965  L                        202641  S                       202589
XL                        186166  2XL                      152014  3XL                     106966
XS                         71104  4XL                       50869  MEDIUM                   31645
LARGE                      31599  SMALL                     31506  EXTRA                    31098
2X                         20091  3X                        20085  5XL                      17541
ONE                        13786  XXL                       11288  OS                        7615
ONE SIZE                    7269  XX                         7184  6XL                       6993
4X                          6945  ALL                        4087  L/XL                      3901
XLT                         3819  OSFA                       3687  S/M                       3490
LT                          3355  2XLT                       3004  3XLT                      2782
4XLT                        2535  5X                         2448  YL                        2341
YM                          2305  YS                         2304  4T                        2185
2T                          2145  5/6                        2008  32                        1930
30                          1897  XXS                        1837  3T                        1817
12M                         1785  18M                        1785  4                         1780
6                           1779  6M                         1762  CONE                      1664
12                          1661  34                         1553  2                         1525
ADJUSTABLE                  1478  24M                        1464  O/S                       1393
8                           1275  NB                         1258  7                         1164
18                          1031  10                          995  37                         979
3                            925  ADULT                       866  2XT                        847
14-16                        845  6X                          794  39                         754
10-12                        751  6-8                         748  36                         686
36C                          672  38C                         669  A                          639
38D                          638  36D                         637  S(6-8)                     627
M(10-12)                     626  L(14-16)                    625  24                         573
3XT                          554  6MOS                        547  12MOS                      546
M/L                          540  18MOS                       538  36B                        526
38B                          524  38DD                        523  1 SIZ                      518
40C                          510  40D                         506  34C                        475
24MOS                        469  14/16                       465  36DD                       446
34D                          444  28                          441  5                          430
40DD                         423  38                          417  40                         413
42D                          406  42C                         403  42DD                       402
10/12                        397  5/6T                        382  XX-SMALL                   378
6/8                          376  16                          368  29                         358
14                           357  XL(18-20)                   356  2XS                        352
18/20                        344  34B                         341  SPOOL                      339
31                           329  2/4                         322  YXS                        320
XS(2-4)                      312  34DD                        310  2-4                        306
SM                           281  40B                         279  10-13                      278
42                           277  YXL                         267  4XT                        260
9                            260  LX                          258  44                         257
6T                           255  12MO                        252  18MO                       251
6MO                          251  1X                          245  7-9                        229
MT                           229  42B                         226  5T                         225
9-11                         224  31R                         224  24MO                       216
42DDD                        211  38DDD                       201  5XT                        200
46                           199  40DDD                       198  SS                         193
44D                          187  XT                          183  44DD                       181
44C                          181  48                          178  O                          174
8XL                          174  7XL                         172  2XL/3XL                    171
20                           167  9XL                         165  10XL                       165
36DDD                        145  34A                         137  18-20                      135
36A                          135  XS/S                        124  6-12                       118
33T                          117  34 32                       115  32 30                      115
38 32                        115  36 32                       115  36 34                      115
38 30                        115  34 30                       115  32 32                      115
36 30                        113  40 30                       113  38 34                      112
40 32                        112  34 34                       112  30 32                      112

Calculate entropy


In [101]:
# calculate probability vector
p = [x[1] for x in ALL_SIZES]
size_prob_vector = np.array(p) / TOTAL_NUMBER_OF_PRODUCTS

# calculate entropy
first_entropy = entropy(size_prob_vector)

print("Data entropy:", first_entropy)


Data entropy: 3.07781166841

Create new collection from data only with '_id', 'source' and 'size' fields


In [49]:
# create new collection
db.data.aggregate(
    [
        {
            "$project": {
                "_id": 1,
                "source": 1,
                "size": 1,
            },
        },
        {
            "$out": "size_mapping"
        }
        
    ]
)
print('Db "size_mapping" created')

# create indexes
db.size_mapping.create_index([("size", 1)])
db.size_mapping.create_index([("source", 1)])
print('Indexes "size", "source" for "size_mapping" created.')

print(list(db.size_mapping.find().limit(5)))


[{'_id': ObjectId('55fedba0c702283c66874a04'), 'source': 'shemeka', 'size': 'ONE'}, {'_id': ObjectId('55fedba0c702283c66874a05'), 'source': 'shemeka', 'size': 'ONE'}, {'_id': ObjectId('55fedba0c702283c66874a07'), 'source': 'shemeka', 'size': 'ONE'}, {'_id': ObjectId('55fedba0c702283c66874a08'), 'source': 'shemeka', 'size': 'ONE'}, {'_id': ObjectId('55fedba1c702283c66874a0a'), 'source': 'shemeka', 'size': 'M'}]

Sizes list per distributor


In [102]:
SIZES_LIST_PER_DISTRIBUTOR = db.size_mapping.aggregate(
    [
        {
            "$group": {
                "_id": "$source",
                "sizes": {"$addToSet": "$size"},
            },
        },
        {
            "$project": {
                "_id": 1,
                "sizes": 1,
                "number_of_sizes": {"$size": "$sizes"},
            }
        },
        {
            "$sort": {
                "number_of_sizes": -1
            }
        }
        
    ]
)

TABLE_SIZES_LIST_PER_DISTRIBUTOR = [
    (str(x['_id']), x['sizes'], x['number_of_sizes']) 
    for x in SIZES_LIST_PER_DISTRIBUTOR
]

In [103]:
for distr, sizes, num in TABLE_SIZES_LIST_PER_DISTRIBUTOR:
    print('Sizes for: "{}"'.format(distr))
    print(", ".join(sizes))
    print(80*"-")


Sizes for: "jeneva"
4XLT, L-XL, 28UL, XL-18/20, L-14/16, 50X30, 56UL, 58UL, 52UL, 50UL, 48UL, 46UL, 3330, 3836, 40UL, 3636, 3436, 3334, 3132, 29X30, 28X30, 31X32, 29 UL, 46 UL, 50 UL, 48 UL, 40 UL, 42 UL, 34 UL, 33 UL, 32 UL, 40 UU, 38 UU, 36 UU, 34 UU, 44 UL, 30 36, 48X34, 32XUU, 38XUU, 36XUU, 34XUU, 30XUU, 5630, 6032, 6030, 5832, 5632, 5232, 5230, 5032, 5030, 4830, 19.5 REG, 15.5 REG, 16.5 REG, 17.5 REG, 2XXT, 4432, 3032, 3030, 12S, 8H, 10S, LXT, 40X30, 5SL, 14SL, 8SL, 7SL, 54, 20.5, 18.5, 16.5, 21, 4234, 4XL, 4232, 4030, 3834, 3832, 3634, 42, 6SL, 14H, 3432, S-7/8, 3630, 3232, 28XUL, 34 28, 29XUL, 5XR, 4632, 2XS, 3-6 MTH, 4XT, 4XR, 34 32, 3XT, XLR, 36, 11, 5430, 18.5 REG, 3XR, 2XR, 33X34, 2XT, 54UL, 24W, 9-11, 34 31, XXS/XS, 7-9, 3XLT, 34 29, 15, 19, 6/8, 33X32, 50XUU, 52XUU, 54XUU, 46X34, 46X32, 2T, 46X30, 44XUU, 42XUU, 40XUU, XLS, 4032, 31 31, 5S, 56XUU, 38XUL, 4430, 32XUL, 30XUL, EACH, 44X30, 42 29, 12H, 56, 10H, XXL, UNDERTAPE/IN HOUSE, 20H, 32 36, RIP-N-ZIP, 18-24 MTH, 12SL, 32 31, 6-12 MTH, XS/S, 30X30, 10/12, 5830, 5T, 4 (26-28), 8S, 2 (18-20), XL (14/16), 31XUL, 52 30, 44X34, L (10/12), 20, PAIR, 5R, 10.5, 2/3T, S (6/8), 16, 2XL/3XL, 0-3M, 12-18M, 3130, 3-6M, YM, YS, XXS-L, YL, 12R, 16R, 18R, 3034, MS, 0, 10R, 58 32, 36X34, 42X30, 14.5, 6 MONTHS, 4034, 32X34, 40X34, 20W, 38X34, 38X30, 35XUL, 8, 4230, 34X32, 18W, M (10/12), 3434, 34X30, 12.5, 32X30, 30X32, 6-12M, 33 32, 60UL, 60 UL, 6, 46, 42 30, 58UU, 40 36, 36 UL, 56UU, 48 34, 30 30, 6XSL, 31 30, 6T, 3, 31 32, 44UU, 42 36, 36UL, 3X, 36 29, 35UL, 36X30, 34UL, 33UL, 52UU, 38, 30UL, 31UL, 17  WX11  HX7  O, 42UL, 28UU, 54UU, O, S (4/5), 48X32, 4R, XLT, LT, LS, 1, 5XL, 5/6T, NB, XL/2X, 24M, 26 28, XXT, 1 (14-16), 26 30, 4832, 2632, 44 30, LX, 40X32, 26X32, 4, 31, SM, 4630, 32X32, S/M, 33X30, XS (2/3), 46 34, OSFA, 38UL, 13-15, 58, 28 32, 50 34, 44 31, 34 30, 42 31, MR, 42 28, 40 31, 30 32, 6S, 54 UL, 16H, 36 31, 36 28, 33 31, 35, 34, 52 UL, 33 29, 42X34, 10SL, 31 34, 3632, 50W  X60  L, 58XUU, 42 34, 48UU, 32 30, 24, 60, 12 MONTHS, 42X32, 60 30, 32 29, 30 UL, 32 28, 30 31, 29 32, 50X32, XLXT, 46UU, 11-SEP, 18H, 60UU, 9, 29 30, 31 29, 34 34, 60 32, 14/16, O/S, 14S, ST, 36XUL, 40 30, 44 34, 20R, 54 32, 5432, 52 32, 28X32, 31 UL, 34X34, 42UU, 30, 33 34, 5, 22, 7, 48X30, 2XLT, 40 34, 56 UL, 3234, 40UU, 46XUU, 36X32, 2XL, 46 32, 10-13, 56 32, 56 30, 30 34, 50 32, 44 32, 14R, 29X32, 40 29, 48 32, XS, 48 30, 34XUL, 4SL, 38 36, 38 UL, 2832, 30X34, M (6/8), 29 29, 28 30, 33 30, 52, 48, 32 32, 3430, 14, 10, 38 32, 54 30, 3 (22-24), 58 30, 31X30, 38 31, MT, 33, 27 28, 36 36, 50 30, 3XS, 29UU, 6X, 29, 3T, 28, 42 32, 38 29, 9-JUL, 44UL, L/XL, 50UU, 27 30, 40 32, 4S, 7R, 32 UU, S, 46 30, 36 32, 38 30, 3332, 36 30, 12-18 MTH, S-M, 33XUL, 44 28, XXS, 18-24M, 4T, 12, 6XS, 28 UL, 34 36, 44 29, 38 34, OS, 6M, 44X32, 18, 5/6, 38X32, 12M, 50, 17, 3XL, 24 MONTHS, 3230, L (14/16), 32 34, 32, 58 UL, 6XL, SR, 14.5 REG, 8R, 36 34, 60XUU, ONE, 7S, BL, 2X, 2, 6R, L, M, 6XR, M/L, 40, 38 28, 13-OCT, 32UL, 4X, 13, 18 MONTHS, M-10/12, LR, 18M, OSFM, 3830, ONE SIZE, 5X, SEW-FOLD-SEW, 40 28, 48XUU, 30 29, 22W, XL, 44
--------------------------------------------------------------------------------
Sizes for: "shemeka"
2-3XL, YM, YL, 14-16, 26-28, 18-20, O/S, 30/36, 32/36, XLXT, LXT, 2R, 18R, 12R, 8UU, 36/31, 36/29, 34/31, 34/29, 32/29, 17.5, 16.5, 15.5, 18/UU, 20WRG, 40UL, 2-3X, 24W, 22W, 20W, 18W, 19.5, 18.5, 24WRG, 18WRG, 16R, 20R, 14R, 8R, 16P, 12P, 8P, 10P, 6P, 12T, 10T, 14T, 18T, 22R, 16T, 10UU, 18UU, 24UU, 4X, 3X, 5X, YTH, 2X, OS, S RG, ST, XL LN, 60/UU, 2X LN, 12, L LN, 5T, CODE ONE, 12M, 38/31, 40/29, 38/28, 38/UU, 6M, 33/29, 29/29, 32/31, 60, 58, 42/UL, 2XL RG, 36, L SH, YXL, XL SH, 3XL RG, 4XL/5XL, 2X TL, L RG, S LN, 8T, 42/28, M RG, 50/UU, 36/36, 34/36, LG, XXS, 24/UU, 16/UU, AM, 12/UU, XS/S, 06/UU, 22WRG, 6, 16W, 32/UL, 20, 31/29, 18, 16, 6R, 54/UU, 2XL/3XL, 44/UU, 56/UU, 18P, 38/36, 42/UU, 1, 5XL, 52/UU, M LN, 35/UL, 56, 46/34, 33/UL, 48/32, 46/32, 44/UL, 36/UL, 6UU, 34/UL, XL RG, 30/UL, 4UU, 54, 42/34, 2XL SH, 40/34, 50, 34, 31, 26/32, M SH, 22/UU, 4, 6X, LARGE, 29, 28, M/L, M, 31/UL, 3XT, 2XT, 2XL, ONE, 38/29, XLT, 38/UL, 3XLT, 15, 32/34, 29/32, 4R, 36/34, 33/32, 42/31, 35, 34/28, 31/32, 42/29, 6XL, 32, 33/30, MT, 33, 46, 20/UU, 31/34, 52, 48/34, 36/30, 44/32, 40/28, 42/30, 46/UL, XT, L/XL, 22-24, 42/32, 40/32, 3T, 36/32, 22UU, 4T, 44/30, 32/28, 14.5, 28/32, 33/34, 34/UU, 38/32, 40/31, 29/30, 38/30, 6T, 28/30, 34/32, 34/30, 18M, 31/30, 12UU, AXL, 32/32, 31/31, 40/30, 10/UU, 48/UU, 32/30, 4XL, 29/UU, 33/31, 08/UU, 14UU, 9, 30, YS, 04/UU, 42, 2T, 40/UL, 14/UU, 13, 10, 14, XS, 30/31, 5/6, 38/34, 3332, LT, S/M, 14P, 20UU, 5, 8, 44, 30/32, 11, 46/UU, 2XLT, 48/UL, 7, S, 36/UU, 48, AL, 16UU, 3X LN, 28/UU, 30/34, 44/34, 24M, 2, L, 40, 48/30, 17, 3XL, 38, 36/28, 24R, 40/UU, NB, 50/32, 58/UU, 34/34, XL, 10R, 0, 30/30, 3, 46/30
--------------------------------------------------------------------------------
Sizes for: "marsha"
18H, 10H, 16, 20, 46W, 44W, 42W, 38W, 32W, 14-16, 26-28, 18-20, T/C, C/Y, 7XL, 10XL, 9XL, 7T, 31, 35XT, 24, 33T, 5XL, 5/6T, 1, 31R, 26/28, 2T, +1, 14, S(6/8), 10, 5XT, 12MOS, 2T/3T, 6/6X, 48W, 5T, 7/8, 6Y, 09, 07, 05, 03, 58, M(10/12), +2, 56, 28, 31/34, 4/5, 29/30, 22/24, 44, 38, 34, 9, 30, 22-24, 42/32, 50/30, 46/32, 01, 52, 36/30, 44/32, ST, 44/30, 40/32, 18MOS, 40/36, 40/34, 40/30, SMALL, W46, 14Y, 38/36, 34/36, W36, 3XLL, 38/32, 38/30, 30/34, 24MOS, 3T, 36/32, 50/32, 36W, 34/30, 33/34, 36/34, 33/32, 3XLT, 15, 32/34, 6XL, 31/32, 46/30, 4XL/5XL, XL(18/24), 12-18MOS, 18, SMALL/MED, 6T, MT, 33, 46, L(14/16), W50, LARGE, LARGE/XLARGE, 29, 4, XLT, W38, W34, 3XL, 17, W32, W30, S, 2XLT, 7, 18-24MOS, 4XT, 40, M, M/L, 6MOS, 4T, 12, 39, 13, W44, 6, XS/S, 3, NB, 42/30, 48/32, 5/6, 29S, 31/30, 18M, 6M, 10Y, 48, 5XLR, 0, 10/12, 2XLL, 14/16, XL, 42, W48, 54, 42/34, 2X/4X, 34/32, 3-6, W42, L, 40W, 30/32, 11, 36, CHARCOAL/BLACK, 30/30, 32/32, 3XLR, 32/30, 12-18, 6-12, OS, W40, 3-6MOS, 2/3X, XX-SMALL, ADJUSTABLE, 60, 18/20, 2XL/3XL, 5, 36/36, 14H, MEDIUM, S/M, 34W, 2XL, ONE, 6/8, 32, 33/30, 32/36, 4XLT, 34/34, 06M, EXTRA, 48/30, 2XT, 50, 12M, 42/36, L/XL, 8XL, 37, 2X/, 8, XS, 44/34, 2, 24M, 28/30, 4XL, 2XLR, LT, 3XT, 4XLR, 38/34, 6XLR, 6-12MOS, 18-24
--------------------------------------------------------------------------------
Sizes for: "kina"
06M, 13, 0, 1, 34, 5236, W50, 18M, XL L, 2XLL, W38, W40, W36, W34, W30, W32, T/C, 7XL, 10XL, 9XL, 4209, 4609, 3809, 9, 3109, 3709, 3609, 6036, 3509, 3, 3409, 3309, 3209, 2809, 2909, 2830, 4809, 5030, 4830, 4432, 4430, 4231, 4040, 4033, 3840, W46, 3833, 3831, 4228, 3828, L L, C48, 3640, 4230, 3428, 6T, 3634, 8XL, 3829, 3632, 3631, 3432, 3630, 3629, 6XLR, 3433, 3430, 4431, 3T, 3337, 5, 2XLT, 3230, 3228, XS, 3032, 5836, 2936, 2737, 42, W48, 2T, 2832, 2937, 3633, 4034, 4XLR, C50, 2XLR, C62, 3429, XL R, 2X, L/XL, M R, 3431, 4032, S R, C/Y, 2/3X, 4037, 3028, 5T, 2836, 3628, 4030, 4T, 5036, 3XLR, 4836, 3231, M L, 3830, L R, 4436, 30, 4236, 3030, 5XLR, 5037, 3440, 3837, 4409, 4028, 4437, 3137, C46, 4237, 4XLT, 3637, 4637, W44, 3037, 4036, 28, C44, 11, 2837, C64, XLT, 3XLL, C52, 40, C38, M/L, XL, 1X, 3232, 12M, 4636, W42, 4232, 4031, OSFA, L, C42, 4837, LT, 3434, C56, C40, 32, 4630, 6XL, S/M, 3XL, 38, 5436, 3237, 4009, C60, 5XL, 36, 3XLT, 3834, C58, C54, 3234, 2XL, 3009, 3832, 3437, 5636, XXL, M, 4XL, 7, S, 3233
--------------------------------------------------------------------------------
Sizes for: "rubi"
L SHORT, M SHORT, XS SHORT, 3, 30A, 30, 3T, 5X, 42/44 D/DD, 42/44 C/D, 40/42D/DD, 40/42C/D, 38/40D/DD, 38/40C/D, 36/38D/DD, 34/36D/DD, 34/36C/D, 10/12, 4X, 4/5, 3X, 46G, 52DDD, 54C, 38, S/M, 1X/2X, 36/38C/D, ONESIZE, 44G, 8-12, 8/9, 6-12M, 4, 2/3, M/T, 6, 2/3T, 10-13, XXL, 14, 12-14, 4T, 12, 1X, 4XLT, 54D, 52D, 13, 52DD, L/XL, 2X, 2 PLUS, T, 32A, 46DD, 34A, 10, 8, XS, 32, 6XL, 38G, S SHORT, 36G, 40G, 5-9, 9-12, 5, 2XLT, 2T-3T, 32B, 46B, 38A, 2, 32DDD, 52C, 4T-5T, XLT, 48C, 54DDD, 50B, 3X/4X, 44DD, 34, P-S/M, 48D, 46C, 4/5T, 44C, 34D, 46D, 40DDD, 32C, 38DD, 34DDD, 42B, 10/11, 42DD, 32D, PT/ML, 40DD, 34DD, 42DDD, LT, 42D, 36A, 42C, 40D, 36, 3XLT, E, 38DDD, 34C, 50D, 40B, 2XL, 40C, 48DDD, 16, 34B, 38D, 36B, 42G, 48B, 9-11, 36D, 36C, 50DD, 36DD, 36DDD, 54DD, 1 PLUS, Q, XL, 38C, M, 6X, 7, S, 9, 4XL, GH, 11, 44D, D, PP, AB, 34G, 1 SIZE, CD, C, -, B, BLUE, Q+, 46DDD, 50C, 3P, 2XL SHORT, 10-15, 2P, 1P, 6/7, F, 44DDD, 2T, 38B, M/L, 50DDD, 6-12, IJ, 32DD, ONE SIZE, 12-24M, L, 3XL, PT/SM, 48DD, 5XL, 44B, EF, 4-5P, A, XL SHORT, 6P
--------------------------------------------------------------------------------
Sizes for: "larry"
50W, 28W, 32W, 48W, 42W, 34W, 30W, 44W, 5 - XS, 6T, 5T, 4XLT, 5 - 30/32, 20 - XXL, 46, 1 - 14/16, 3/6, NB, 18/24, 6/12, 52, 14, 4 - 26/28, 12M, 50, 20, 44, 46W, XS, 8, 20.5, 7 - S, 17.5, 15.5, 14.5, S, 7, 36W, LT, XL/2XL, 18.5, 16.5, 3XLT, 36, 34, 40W, 4T, 12, 6XL, 32, YOUTH, ADJUSTABLE, 2XL/3XL, 2XLT, 5, XXS, S/M, XLT, 2, 24M, 10, 5/6, 6 - S, 18M, 22, 6M, 54, 2T, 42, 3 - 22/24, 4XL, 18H, 10H, 48, 19.5, 18 - XXL, 8 - M, 5XL, 2 - 18/20, XS/S, 30, 18, 15, 12 - L, 6, ONE SIZE, XL, 24, 40, M/L, L/XL, 14H, 16, 2X/, 2XL, 2T/3T, 38, M, 38W, 4XL/5XL, 12/18, 4, L, 17, 3XL, 16 - XL, 3T
--------------------------------------------------------------------------------
Sizes for: "ignacia"
XXS/XS, 8XL, R, 4XL/5XL, 7XL, XL/2XL, 5T, 6T, 2, 5, 2XL/3XL, MT, 2XLT, 24MOS, 1XL, 6MOS, REG, NB, 4, 29, CONE, 28, 18-24MOS, 4XT, 7-9, 10-13, , ST, 31, 5XT, XL, SPOOL, 14, SLM, XS, 8, 37U, 3T, 5X, 3XLT, 36, 35XT, 7, S, 34T, 31R, 13, 39, 2XL, 37, 33T, 34, 20, 18, 30, 5/6, 10, 4T, 12, 6XL, 32, 22-24, 12MOS, 1, 15, 6, 4XL, 9, 29S, XS/S, 3, 3XL/4XL, 14-16, 40, M/L, 0, S/M, XXS, LT, 2XT, XLT, ONE, 18MOS, 6-12MOS, 28P, 2T, 42, L, 12-18MOS, 18-20, 6-8, 11, 9-11, 3-6MOS, M, 3XT, L/XL, 13-15, 16, 2T/3T, 38, 3XL, 5XL, 10-12, 26-28, OS
--------------------------------------------------------------------------------
Sizes for: "wendell"
14, 10, 6, 4, 50X32, 6X, 2XT, XLT, 3XT, LT, XL/XXL, 2X, 42X34, S/M, 42X32, 36X32, 42X36, 2X/3X, 44X32, L/XL, 44X30, 40X36, 32X30, 34, 33X34, 32X36, 46X30, 36X30, 12, 48X32, 46X32, 32, 30X30, 38X30, 28, 32X34, 36X34, 34X34, 30X32, YTH, 36X36, 3XL, 40, 34X32, 33, 48X30, 5X, 36, 31, 42, 40X32, 29, 48, 18, 30, 38X32, T3X, T2X, TXL, 30X34, TL, 34X30, 50, 5XL, 8, 44, 50X30, 4XT, 38X34, L, 44X34, 4X, XXL, M, ONE SIZE, 46, M/L, 38X36, XL, 16, 33X30, 2XL, 42X30, 40X30, S, XS/S, 32X32, 34X36, 33X32, 3X, 38, XS, 40X34, ALL
--------------------------------------------------------------------------------
Sizes for: "patti"
1X, 34, 6T, 4, INFANT, SMALL/MED, 3XL, 40, 17, 1, 19, 15, PLUS 2(14), PLUS 1(12), L(8), XL(10), A11, YXS, XS(0), S(2-4), M(6), PLUS 3(16), 4XT, O/S, 2, YL, 5/6, 2T/3T, YS, 2T, ALL, 24, 32, LG/XL, 12, 6, XL, M/L, 13-15, 2XLT, LT, MT, L, XLT, 2XT, 7-9, 10-13, 30, 18, ONE, XS/S, 4T, ONE SIZE, 2X/3X, 36, 5X, 3, 4X, 6X, S, 3T, YOUTH, 2X, YXL, XXS, S/M, 5T, Y, 7, 4X/5X, 3XT, 2XL, L/XL, M, NB, 38, XS, YM, XXS/XS, 9-11, 3X
--------------------------------------------------------------------------------
Sizes for: "denisha"
29, 28, 39, 37, , 34, 32, 30, MT, LT, 1XL, 3XT, 36, 5X, 18-24MOS, 2X, 6-12MOS, 4, 6, 8XL, 2, 2XLT, 3XLT, 2XT, XLT, 5T, 7, 3-6MOS, 9-11, 4XL, 2XL/3XL, M, 24 MOS, 18 MOS, 12 MOS, 12MOS, 7-9, 10-13, OSFS, 31, SPOOL, XS/S, 18MOS, 4T, CONE, 6-12, 3-9, 2T/3T, 2T, 24MOS, R, XXS, S/M, 6 MOS, 5XL, XL, M/L, 6T, 4XL/5XL, S, 3T, 9-2.5, L/XL, 2XL, NB, XS, 12-18MOS, L, 3XL, OS, 6XL, 6MOS, 5/6, XL/2XL
--------------------------------------------------------------------------------
Sizes for: "evie"
MT, 8, 22-24, 18-24M, 26-28, 12-18M, 5T, 8XL, 6T, 4XL/5XL, 6-12M, 33T, 3XL/4XL, 6XL, 42, 7, 10, 5/6, XS/S, 4T, 2XLT, 24M, 18M, XXS, S/M, 4XL, 2XL/3XL, 31R, 6M, 3XL, 40, 18-20, XS, 38, 12M, 5XL, S, 3T, 4XT, NEW BORN, L, XLT, 2XT, 30, OS, 3-6M, XL/2XL, LT, 12, 32, L/XL, 2XL, 3XT, 14-16, M/L, XL, 3XLT, M, ONE SIZE, 36, 34, 2T, ST, 5XT
--------------------------------------------------------------------------------
Sizes for: "allegra"
6T, 4T, 2T, 305, 156, 83, 28, 230, 195, NB, 50, 20, 14, 23X, L/X, OS, LXL, S/M, 8, 44, 45X, 46, XS, 38, 2XL, 16, 36, 12, 32, 18, 30, 6, 7, 42, 2, XL, 0, 3, 18M, L, 40, 3XL, 110, 4, 24M, 4XL, 2XS, 48, 3M, 10, 5/6, 34, 3T, S, 6XL, ONE, 1, 24, 0M, 6M, OSA, M, 5XL, 12M
--------------------------------------------------------------------------------
Sizes for: "major"
KX, L/XL, Y, MT, 2X, 1X, XS(4-5), XL(14/16), L(10/12), M(7/8), S(6/6X), XS(3/4), XS(4-6), 5XL, L(14-16), XS(2-4), ML, XL(18-20), F, S, 3T, 9, 4XL, M(10-12), SM, XT, 6XL, 5X, 6X, 3, 4X, 2, 1, S(6-8), XL, 0, 2XL, 8, L, ADULT, LX, 3XL, 4, M(8), S(6/7), SS, 4T, XX, 7, B, ONE SIZE, 3X, 6, A, M, 2T, XXL, LT, S/M, 5, XS, 3T/4T, H
--------------------------------------------------------------------------------
Sizes for: "titus"
8, 7, 18, 14, 12, 6, 6XL, ONE, 4XL, 2XL/3XL, XL, M/L, L/X, 10XL, 10, 7XL, S/M, 5, XXS, XS, XS/SM, 3XLT, XLT, XL/2XL, LT, 8XL, YOUTH, , 4XLT, OSFA, 4, L, 3XL, ADJ, NB, 18M, 9XL, 2XL, 16, ONE SIZE, ADJUSTABLE, S, 2XLT, 24M, L/XL, 6M, 5XL, 12M, XXL, M
--------------------------------------------------------------------------------
Sizes for: "carey"
24MO, 12MO, 5/6T, 6XL, 5X, 5XL, L, 2-4, 3XL, 4T, YXL, 2XL, NB, XS, 18MO, YXS, YM, 6MO, O/S, YL, 4XL, 3T, YS, 18-20, 3X, 6-8, 4X, M, 7T, 2T, XXL, 10-12, 14-16, XL, S
--------------------------------------------------------------------------------
Sizes for: "ciara"
STRAP, BLANKET, 18M, 12M, 5XL, 14-16, 6-8, XXL, 2T, 4T, 3T, 4XL, 24M, 10-12, M, 4, 2-4, 3XL, L, I SIZE, 2, TRI FOLD GROMMET, 5-6, 1 SIZE, S, CORNER GROMMET, 6M, XL, PLAIN, 1 SIZ
--------------------------------------------------------------------------------
Sizes for: "yolande"
XXL: 7⅜"- 8", SMALL/MEDIUM: 6¾"- 7¼", ONE SIZE, ADJUSTABLE, ONE SIZE FITS MOST, XS (2/4), M (10/12), S (6/6X), L (14/16), 4XL, XL (18/20), L, 3XL, M (8), S (6/7), XL (14/16), XS (4/5), 2XL, L (10/12), S (6/8), XS, M (7/8), ONE SIZE 6⅞"- 7½", 5XL, XS (5/4), S, M, LARGE/XLARGE: 7⅛"- 7⅝", XL
--------------------------------------------------------------------------------
Sizes for: "rossana"
S/M, NEW BORN, 6XL, 5/6T, 4T, 4XL, 3T, 18M, XLT, 3XLT, 2XLT, 24M, L/XL, 2XL, XS, 6M, 4XLT, XL, M, L, 3XL, 7, S, 2T, ONE SIZE, 5XL, 12M
--------------------------------------------------------------------------------
Sizes for: "joanie"
1XL, 6XL, 5XL, 18/20, L, 10/12, 8XL, 2/4, 4XL, 6/8, 3XL, 7XL, S, 2XL, XL, 14/16, M
--------------------------------------------------------------------------------
Sizes for: "zack"
3T, 4T, 5X, XS, M, 4X, 2X, 6X, NO SIZE, 2T, 3X, XL, L, S
--------------------------------------------------------------------------------

Tagging according to size

Since the number of sizes is low (1117 uniq sizes), the task could be resolved using tivial brute force, i.e. map sizes using mapping table.

During the observation of data i noticed that sizes are defined for adult, youth, toddler and baby:

  • Adult: 'S', 'M', 'L' etc.
  • Youth: 'YS', 'YL' etc.
  • Kid: '4', '6' etc.
  • Toddler: '2T', '3T' etc.
  • Baby: '3M', '6M', 'NB' (new born) etc.

kid, toddler, baby sizes chart youth sizes chart

I.e. could tag products accodring to the size.

TAG_FROM_SIZE = {
    'adult': ['XS', 'S', 'M', 'L', 'XL', '2XL', '3XL', '4XL', '5XL', '6XL'],
    'youth': ['YXS', 'YSM', 'YMD', 'YLG', 'YXL', '8H', '10H', '12H', '14H', '16H', '18H', '20H'],
    'kid': []
}

In [50]:
SIZES_MAPPING = {
    'ALL': [],
    'NO SIZE': ['PLAIN', 'CONE', 'BLANKET'],
    'ONE': ['OS', 'ONE SIZE', '1 SIZ', 'O/S'],
    'XS': ['XXS', 'XX-SMALL', '2XS'],
    'S': ['SMALL', 'S/M'],
    'M': ['MEDIUM', 'S/M', 'M/L'],
    'L': ['LARGE', 'L/XL', 'M/L'],
    'XL': ['EXTRA', 'XLT', 'XT', 'L/XL'],
    '2XL': ['2X', 'XXL', '2XT', '2XLL', '2X/', '2XLT'],
    '3XL': ['3X', '3XT', '3XLL', '3XLT'],
    '4XL': ['4X', '4XT', '4XLT'],
    '5XL': ['5X', '5XT', '5XLT'],
    '6XL': ['6X'],
}

def build_matching_table(matching_rules):
    """Build matching table from matching rules

    :param matching_rules: matching rules used to build matching table
    :type matching_rules: dict
    :return: matching table `{'S/M: ['S', 'M'], '2X': ['2XL'], ...}`
    :rtype: dict
    """
    matching_table = {}
    # transform matching rules to the "shortcut": "group_key" table
    for key, values in matching_rules.items():
        if not values:  # skip undefined rules i.e. "[]"
            continue

        # add rule for key
        if key not in matching_table:
            # NOTE: set('ab') would be {'a', 'b'}
            # so it's impossible to matching_table[key] = set(key)
            matching_table[key] = set()
            matching_table[key].add(key)
            
        for value in values:
            if value not in matching_table:
                matching_table[value] = set()
                matching_table[value].add(key)
            else:
                matching_table[value].add(key)
    return matching_table

 
MATCHING_RULES = build_matching_table(SIZES_MAPPING)
print(tabulate(MATCHING_TABLE.items(), headers=['From', 'To'], tablefmt="simple"))


From      To
--------  -----------
6X        {'6XL'}
MEDIUM    {'M'}
6XL       {'6XL'}
NO SIZE   {'NO SIZE'}
XLT       {'XL'}
XXS       {'XS'}
L         {'L'}
L/XL      {'L', 'XL'}
2XL       {'2XL'}
3XL       {'3XL'}
4XT       {'4XL'}
BLANKET   {'NO SIZE'}
XL        {'XL'}
4XL       {'4XL'}
5X        {'5XL'}
4XLT      {'4XL'}
M/L       {'M', 'L'}
5XLT      {'5XL'}
S         {'S'}
XX-SMALL  {'XS'}
S/M       {'S', 'M'}
XXL       {'2XL'}
PLAIN     {'NO SIZE'}
3XT       {'3XL'}
5XT       {'5XL'}
5XL       {'5XL'}
EXTRA     {'XL'}
3X        {'3XL'}
2XLT      {'2XL'}
SMALL     {'S'}
3XLL      {'3XL'}
ONE       {'ONE'}
2XS       {'XS'}
XT        {'XL'}
OS        {'ONE'}
3XLT      {'3XL'}
2XLL      {'2XL'}
4X        {'4XL'}
ONE SIZE  {'ONE'}
XS        {'XS'}
2X        {'2XL'}
2XT       {'2XL'}
1 SIZ     {'ONE'}
M         {'M'}
2X/       {'2XL'}
CONE      {'NO SIZE'}
LARGE     {'L'}

In [ ]:
# process data into the new table
# def get_groups(mtable, size):
#     """Get size groups for the given `size` according to matching table

#     :param size: size (case insensetive)
#     :type size: str
#     :return: list of strings i.e. size groups or ``['UNDEFINED']``
#     if not found
#     :rtype: list or ['UNDEFINED']
#     """
#     return list(mtable.get(size, default=size))


# for k, v in MATCHING_TABLE.items():
#     res = db.size_mapping.update_many(
#         {"size": k}, 
#         {"$set": {"size": get_groups(MATCHING_TABLE, k)}})
#     print(res.raw_result)

Let's calculate data entropy for results


In [27]:
results = db.size_mapping.aggregate(
    [
        {
            "$group": {
                "_id": "$size",
                "count": {"$sum": 1},
            }
        },
        {
            "$sort": {
                "count": -1,
            }
        }
    ]
)

NEW_SIZES = [(str(x['_id']), x['count']) for x in list(results)]

print(
    "\n" + 
    tabulate(NEW_SIZES[:20], headers=['Size', 'Number of Products'], tablefmt="orgtbl") +
    "\n"
)

# calculate probability vector
p = []
for _, count in NEW_SIZES:
    p.append(count)
size_prob_vector = np.array(p) / TOTAL_NUMBER_OF_PRODUCTS

# calculate entropy
first_entropy = entropy(size_prob_vector)

print("Data entropy: ", first_entropy)


| Size    |   Number of Products |
|---------+----------------------|
| ['M']   |               238640 |
| ['L']   |               234240 |
| ['S']   |               234095 |
| ['XL']  |               225167 |
| ['2XL'] |               187326 |
| ['3XL'] |               130454 |
| ['XS']  |                73671 |
| ['4XL'] |                60609 |
| ['ONE'] |                29188 |
| ['5XL'] |                20189 |
| ['6XL'] |                 7787 |
| XX      |                 7184 |
| ALL     |                 4087 |
| OSFA    |                 3687 |
| LT      |                 3355 |
| YL      |                 2341 |
| YM      |                 2305 |
| YS      |                 2304 |
| 4T      |                 2185 |
| 2T      |                 2145 |

Data entropy:  2.61658173526

In [36]:
from functools import reduce

total_matched_products = (sum([x[1] for x in NEW_SIZES[:11]]))
percent_from_db_total = round((total_matched_products / TOTAL_NUMBER_OF_PRODUCTS) * 100, 2)

print("Matched: {} Percent from total: {}".format(total_matched_products, percent_from_db_total))


Matched: 1441366 Percent from total: 92.33

In [ ]: