C'est l'exemple de «les omelettes du vendredi soir et la bière sont achetées ensemble». Dans l'analyse du panier, trois indicateurs, le support, la confiance et la remontée, sont calculés à partir des données de vente. Cet article est destiné à être implémenté à l'aide de PySpark. Voir d'autres articles pour la méthode d'analyse. Il y en a aussi à Qiita.
Soutien(A⇒B)=P(A∩B)=\frac{Nombre de paniers contenant A et B}{Nombre total de paniers}
Confiance(A⇒B) = \frac{P(A∩B)}{P(A)}=\frac{Nombre de paniers contenant A et B}{Nombre total de paniers contenant A}
Confiance attendue(A⇒B) = P(B)=\frac{Nombre de paniers contenant B}{Nombre total de paniers}
ascenseur(A⇒B) = \frac{P(A∩B)}{P(A)P(B)}=\frac{Confiance}{期待Confiance}
J'utiliserai Groceries utilisé dans l'exemple d'analyse d'association de langage R. Il existe de nombreux articles de commentaires et vidéos Youtube, il est donc facile de vérifier les résultats des calculs. Ce fichier comporte une ligne par panier et contient des données pour un total de 9835 paniers. Une ligne est parfois appelée une transaction. Les cinq premières lignes sont les suivantes.
groceries.csv
citrus fruit,semi-finished bread,margarine,ready soups
tropical fruit,yogurt,coffee
whole milk
pip fruit,yogurt,cream cheese ,meat spreads
other vegetables,whole milk,condensed milk,long life bakery product
support.py
# -*- coding: utf-8 -*-
import sys
from itertools import combinations
from pprint import pprint
from pyspark import SparkContext
#Données lues. Couper et normaliser en minuscules
sc = SparkContext()
baskets = (
sc.textFile(sys.argv[1])
.map(lambda row: set([word.strip().lower() for word in row.split(",")]))
).cache()
#Nombre total de paniers
total = float(baskets.count())
result = (
baskets
#Donnez la pièce d'identité au panier
.zipWithIndex()
#Faites une paire de marchandises. Le tri concerne les paires stables.
.flatMap(lambda (items, basket_id): ((tuple(sorted(c)), (basket_id,)) for c in combinations(items, 2)))
#Comptez le nombre de paniers en utilisant une paire de produits comme clé
.reduceByKey(lambda a, b: a + b)
.map(lambda pair_baskets: (pair_baskets[0], len(pair_baskets[1])))
#Ajouter un support
.map(lambda pair_count: (pair_count[0], (pair_count[1], pair_count[1] / total * 100)))
#Trier par ordre décroissant par support
.sortBy(lambda (pair, stats): -stats[1])
)
#Afficher les 10 meilleurs supports
pprint(result.take(10))
(Légumes, lait) arrive en tête avec une fréquence de 736 et un support de 7,48% sur un total de 9835. Ce qui suit sont des données occidentales telles que le pain et le lait, le lait et le yogourt, etc., donc des résultats raisonnables ont été obtenus.
$ spark-submit support.py groceries.csv
[((u'other vegetables', u'whole milk'), (736, 7.483477376715811)),
((u'rolls/buns', u'whole milk'), (557, 5.663446873411286)),
((u'whole milk', u'yogurt'), (551, 5.602440264361973)),
((u'root vegetables', u'whole milk'), (481, 4.89069649211998)),
((u'other vegetables', u'root vegetables'), (466, 4.738179969496695)),
((u'other vegetables', u'yogurt'), (427, 4.341637010676156)),
((u'other vegetables', u'rolls/buns'), (419, 4.260294865277071)),
((u'tropical fruit', u'whole milk'), (416, 4.229791560752415)),
((u'soda', u'whole milk'), (394, 4.006100660904932)),
((u'rolls/buns', u'soda'), (377, 3.833248601931876))]
Ensuite, faisons un petit détour pour voir quel est le pire 10. Ce n'est pas grave si vous définissez l'ordre de sortBy sur stats [1]
. La mayonnaise et le vin blanc, le brandy et les bonbons, la gomme et le vin rouge, les édulcorants artificiels et la nourriture pour chiens, l'ampoule et la confiture, etc. ont été des résultats amusants.
[((u'mayonnaise', u'white wine'), (1, 0.010167768174885612)),
((u'chewing gum', u'red/blush wine'), (1, 0.010167768174885612)),
((u'chicken', u'potato products'), (1, 0.010167768174885612)),
((u'brandy', u'candy'), (1, 0.010167768174885612)),
((u'chewing gum', u'instant coffee'), (1, 0.010167768174885612)),
((u'artif. sweetener', u'dog food'), (1, 0.010167768174885612)),
((u'meat spreads', u'uht-milk'), (1, 0.010167768174885612)),
((u'baby food', u'rolls/buns'), (1, 0.010167768174885612)),
((u'baking powder', u'frozen fruits'), (1, 0.010167768174885612)),
((u'jam', u'light bulbs'), (1, 0.010167768174885612))]
Puisque (X⇒Y) et (Y⇒X) sont des niveaux de confiance différents, j'ai utilisé des permutations au lieu de combinaisons pour lister tous les cas.
confidence.py
# -*- coding: utf-8 -*-
import sys
from itertools import permutations, combinations
from pprint import pprint
from pyspark import SparkContext
#Données lues. Couper et normaliser en minuscules
sc = SparkContext()
baskets = (
sc.textFile(sys.argv[1])
.map(lambda row: set([word.strip().lower() for word in row.split(",")]))
).cache()
#Nombre total de paniers
total = float(baskets.count())
#Donnez la pièce d'identité au panier
baskets_with_id = baskets.zipWithIndex()
# (Une paire de marchandises,Nombre de paniers qu'il contient)faire.
pair_count = (
baskets_with_id
.flatMap(lambda (items, basket_id): [(pair, (basket_id,)) for pair in permutations(items, 2)])
#Faites une liste de paniers contenant une paire de produits comme clé
.reduceByKey(lambda a, b: a + b)
#Comptez le nombre de paniers et ajoutez(pair, count)
.map(lambda pair_baskets: (pair_baskets[0], len(pair_baskets[1])))
)
#Nombre de paniers contenant le produit X
x_count = (
baskets_with_id
.flatMap(lambda (items, basket_id): [(x, (basket_id,)) for x in items])
#Faites une liste des ID de panier contenant le produit X
.reduceByKey(lambda a, b: a + b)
#Comptez le nombre de paniers et ajoutez(x, count)
.map(lambda x_baskets: (x_baskets[0], len(x_baskets[1])))
)
#Calculer la confiance pour X
confidence = (
pair_count
#Transformé pour que X puisse être utilisé comme clé pour JOIN
.map(lambda (pair, count): (pair[0], (pair, count)))
.join(x_count)
#Ajoutez de la confiance
.map(lambda (x, ((pair, xy_count), x_count)): (pair, (xy_count, x_count, float(xy_count) / x_count * 100)))
#Trier par confiance dans l'ordre décroissant
.sortBy(lambda (pair, stats): -stats[2])
)
pprint(confidence.take(10))
Le résultat est un tuple de ((Produit X, Produit Y), (Nombre de paniers contenant XY, Nombre de paniers contenant X,% de confiance)). Trié par certitude, c'est une certitude à 100%, mais ce n'est qu'un exemple d'une combinaison rare qui n'apparaît qu'une seule fois.
$ spark-submit confidence.py groceries.csv
[((u'baby food', u'waffles'), (1, 1, 100.0)),
((u'baby food', u'cake bar'), (1, 1, 100.0)),
((u'baby food', u'dessert'), (1, 1, 100.0)),
((u'baby food', u'brown bread'), (1, 1, 100.0)),
((u'baby food', u'rolls/buns'), (1, 1, 100.0)),
((u'baby food', u'soups'), (1, 1, 100.0)),
((u'baby food', u'chocolate'), (1, 1, 100.0)),
((u'baby food', u'whipped/sour cream'), (1, 1, 100.0)),
((u'baby food', u'fruit/vegetable juice'), (1, 1, 100.0)),
((u'baby food', u'pastry'), (1, 1, 100.0))]
Ainsi, lorsque j'ai trié par [le nombre de paniers contenant X, le nombre de paniers contenant XY], les résultats suivants ont été obtenus. Le lait est le plus acheté, et la confiance que les légumes, le pain, le yogourt, etc. seront achetés ensemble est de 11% à 29%.
[((u'whole milk', u'other vegetables'), (736, 2513, 29.287703939514525)),
((u'whole milk', u'rolls/buns'), (557, 2513, 22.16474333465977)),
((u'whole milk', u'yogurt'), (551, 2513, 21.92598487863112)),
((u'whole milk', u'root vegetables'), (481, 2513, 19.140469558296857)),
((u'whole milk', u'tropical fruit'), (416, 2513, 16.55391961798647)),
((u'whole milk', u'soda'), (394, 2513, 15.678471945881418)),
((u'whole milk', u'bottled water'), (338, 2513, 13.450059689614008)),
((u'whole milk', u'pastry'), (327, 2513, 13.01233585356148)),
((u'whole milk', u'whipped/sour cream'), (317, 2513, 12.614405093513728)),
((u'whole milk', u'citrus fruit'), (300, 2513, 11.937922801432551))]
Évaporation du code source. Je le posterai dès qu'il sera trouvé.
Quoi qu'il en soit, les gens qui achètent quelque chose qui ressemble à un bouton sont plus susceptibles de l'acheter avec du saké que de l'acheter seul (rires).
[((u'cocoa drinks', u'preservation products'), 22352.27272727273),
((u'preservation products', u'cocoa drinks'), 22352.272727272728),
((u'finished products', u'baby food'), 15367.1875),
((u'baby food', u'finished products'), 15367.1875),
((u'baby food', u'soups'), 14679.104477611942),
((u'soups', u'baby food'), 14679.10447761194),
((u'abrasive cleaner', u'preservation products'), 14050.000000000002),
((u'preservation products', u'abrasive cleaner'), 14050.0),
((u'cream', u'baby cosmetics'), 12608.97435897436),
((u'baby cosmetics', u'cream'), 12608.974358974358)]
L'analyse du panier de marché a été réalisée avec PySpark.
Cet article a été écrit il y a longtemps et a été laissé sous forme de brouillon, il peut donc ne pas fonctionner dans le pyspark actuel.
Recommended Posts