Analyse du panier avec Spark (1)

Qu'est-ce que l'analyse du panier de marché?

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.

Définition

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}

Exemple de données

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

Calcul du support

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

Résultats du soutien

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

Calcul de la confiance

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



Résultat de confiance

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))]

Calcul de l'ascenseur

Évaporation du code source. Je le posterai dès qu'il sera trouvé.

Résultat de l'élévation

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)]

Résumé

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

Analyse du panier avec Spark (1)
Analyse des composants principaux avec Spark ML
Analyse de données avec python 2
Analyse de dépendance avec CaboCha
Analyse vocale par python
Premiers pas avec Spark
Analyse vocale par python
Analyse dynamique par Valgrind
Effectuer une analyse de régression avec NumPy
Analyse de données avec Python
[Analyse de co-occurrence] Analyse de co-occurrence facile avec Python! [Python]
Apprentissage d'ensemble et analyse de paniers
Analyse de régression multiple avec Keras
Analyse des émotions par Python (word2vec)
Analyse de texture apprise avec la pyradiomique
Analyse de squelette planaire avec Python
Analyse morphologique japonaise avec Python
Analyse des secousses musculaires avec Python
[PowerShell] Analyse morphologique avec SudachiPy
Analyse des émotions par SMS avec ML-Ask
Analyse de la structure du squelette en trois dimensions avec Python
Analyse d'impédance (EIS) avec python [impedance.py]
Text mining avec Python ① Analyse morphologique
Premiers pas avec Cisco Spark REST-API
Analyse pratique avec Pandas + notebook Jupyter
J'ai joué avec Mecab (analyse morphologique)!
Résumé de Kaggle: Analyse du panier de marché Instacart
Spark play avec WSL anaconda jupyter (2)
Analyse de données à partir de python (visualisation de données 1)
Analyse de régression logistique Self-made avec python
Analyse de données à partir de python (visualisation de données 2)
J'ai essayé l'analyse de régression multiple avec régression polypoly
L'analyse de clustering la plus basique avec scikit-learn
Analyse des composants principaux avec le corpus d'actualités Livedoor - Pratique--
[Didacticiel d'analyse Python en base de données avec SQL Server 2017]
Utilisation d'Apache Spark avec le notebook Jupyter (notebook IPython)
Analyse bidimensionnelle du flux de perméation saturée-insaturée avec Python
Apprentissage automatique avec python (2) Analyse de régression simple
Programme d'analyse des contraintes FEM 2D par Python
J'ai essayé l'analyse factorielle avec des données Titanic!
[Analyse vocale] Trouvez une similitude croisée avec Librosa
Analyse des conversations en ligne avec Janome (OSS publié)
Analyse émotionnelle des tweets avec apprentissage en profondeur
Analyse des tweets avec Python, Mecab et CaboCha
Visualisons le fil 2ch avec WordCloud-analyse morphologique / édition WordCloud-
Analyse de données à partir de python (pré-traitement des données-apprentissage automatique)
Analyse de conduction thermique bidimensionnelle non stationnaire avec Python
Analyse de réseau avec NetworkX --- Volume de détection de la communauté
Python: analyse morphologique simplifiée avec des expressions régulières
Que diriez-vous de l'analyse de polarité avec "ordre" ajouté?