Environnement - Packages¶

In [3]:
# activation de l'environnement
using Pkg
Pkg.activate("./env_julia_query")
  Activating project at `c:\Users\ricco\Desktop\demo\env_julia_query`

In [4]:
# lister les packages installés
Pkg.status()
Status `C:\Users\ricco\Desktop\demo\env_julia_query\Project.toml`
  [a93c6f00] DataFrames v1.8.2
  [7073ff75] IJulia v1.34.4
  [1a8c2f83] Query v1.1.0
  [fdbf4ff8] XLSX v0.11.3

Package "Query" - Getting started¶

Chargement du dataframe "Fournisseurs"¶

In [5]:
# chargement des données (DataFrame)
import DataFrames as DFR
import XLSX

# lecture -> DataFrame
dfFour = DFR.DataFrame(XLSX.readtable("./fournisseurs.xlsx"))
println(DFR.first(dfFour,10))
10×5 DataFrame
 Row │ Num_fournisseur  Societe                            Adresse                    Ville             Pays        
     │ Int64            String                             String                     String            String      
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1 │               1  Exotic Liquids                     49 Gilbert St.             London            Royaume-Uni
   2 │               2  Nouvelle-Orléans Cajun Delights    P.O. Box 78934             Nouvelle-Orléans  Etats-Unis
   3 │               3  Grandma Kelly's Homestead          707 Oxford Rd.             Ann Arbor         Etats-Unis
   4 │               4  Tokyo Traders                      9-8 Sekimai Musashino-shi  Tokyo             Japon
   5 │               5  Cooperativa de Quesos 'Las Cabra…  Calle del Rosal 4          Oviedo            Espagne
   6 │               6  Mayumi's                           92 Setsuko Chuo-ku         Osaka             Japon
   7 │               7  Pavlova, Ltd.                      74 Rose St. Moonie Ponds   Melbourne         Australie
   8 │               8  Specialty Biscuits, Ltd.           29 King's Way              Manchester        Royaume-Uni
   9 │               9  PB Knäckebröd AB                   Kaloadagatan 13            Göteborg          Suède
  10 │              10  Refrescos Americanas LTDA          Av. das Americanas 12.890  São Paulo         Brésil

Requêtes de type "dplyr" (mode "Standalone")¶

In [6]:
# importer le package
# utilisation de using pour accéder directement aux macros @...
using Query

# requête = enchaînement d'opérations sous forme de pipeline
# plutôt dans le style "dplyr" de R
# le résultat est typé en DataFrame
result = dfFour |>
            @filter(_.Pays == "France") |>
            @map({_.Societe,_.Ville}) |>
            DFR.DataFrame

# affichage
println(result)
3×2 DataFrame
 Row │ Societe                     Ville    
     │ String                      String   
─────┼──────────────────────────────────────
   1 │ Aux joyeux ecclésiastiques  Paris
   2 │ Escargots Nouveaux          Montceau
   3 │ Gai pâturage                Annecy

Requêtes de type "LINQ"¶

In [7]:
# une autre manière d'écrire la même requête
# avec le formalisme LINQ
# "i" est in itérateur qui symbolise les lignes
result = @from i in dfFour begin
         @where i.Pays == "France"
         @select {i.Societe, i.Ville}
         @collect DFR.DataFrame
end

# affichage
println(result)
3×2 DataFrame
 Row │ Societe                     Ville    
     │ String                      String   
─────┼──────────────────────────────────────
   1 │ Aux joyeux ecclésiastiques  Paris
   2 │ Escargots Nouveaux          Montceau
   3 │ Gai pâturage                Annecy
In [8]:
# ou mixée sous forme de pipeline
# attention, pas d'espace entre @query et la parenthèse !!!
# on se rapproche du SQL mais l'intérêt n'est pas ouf dans notre contexte
result = dfFour |>
            @query(i, begin
                @where i.Pays == "France"
                @select {i.Societe, i.Ville} 
            end) |> DFR.DataFrame

# affichage
println(result)
3×2 DataFrame
 Row │ Societe                     Ville    
     │ String                      String   
─────┼──────────────────────────────────────
   1 │ Aux joyeux ecclésiastiques  Paris
   2 │ Escargots Nouveaux          Montceau
   3 │ Gai pâturage                Annecy

Requêtes de type LINQ mono-table¶

Filtrage¶

In [9]:
# filtrage avec tous les champs
result = @from i in dfFour begin
         @where i.Pays == "Japon"
         @select i
         @collect DFR.DataFrame
end

# affichage
print(result)
2×5 DataFrame
 Row │ Num_fournisseur  Societe        Adresse                    Ville   Pays   
     │ Int64            String         String                     String  String 
─────┼───────────────────────────────────────────────────────────────────────────
   1 │               4  Tokyo Traders  9-8 Sekimai Musashino-shi  Tokyo   Japon
   2 │               6  Mayumi's       92 Setsuko Chuo-ku         Osaka   Japon

Projection¶

In [10]:
# projection sans filtrage
# avec renommage des champs
result = @from i in dfFour begin
    @select {Society = i.Societe, City = i.Ville}
    @collect DFR.DataFrame
end

# affichage
println(DFR.first(result,5))
5×2 DataFrame
 Row │ Society                            City             
     │ String                             String           
─────┼─────────────────────────────────────────────────────
   1 │ Exotic Liquids                     London
   2 │ Nouvelle-Orléans Cajun Delights    Nouvelle-Orléans
   3 │ Grandma Kelly's Homestead          Ann Arbor
   4 │ Tokyo Traders                      Tokyo
   5 │ Cooperativa de Quesos 'Las Cabra…  Oviedo

Champ calculé¶

In [11]:
# Requête avec champ calculé (via une concaténation)
result = @from i in dfFour begin
    @select {
        i.Societe,
        Endroit = i.Pays * "__" * i.Ville
    }
    @collect DFR.DataFrame
end

# affichage
println(DFR.first(result,5))
5×2 DataFrame
 Row │ Societe                            Endroit                      
     │ String                             String                       
─────┼─────────────────────────────────────────────────────────────────
   1 │ Exotic Liquids                     Royaume-Uni__London
   2 │ Nouvelle-Orléans Cajun Delights    Etats-Unis__Nouvelle-Orléans
   3 │ Grandma Kelly's Homestead          Etats-Unis__Ann Arbor
   4 │ Tokyo Traders                      Japon__Tokyo
   5 │ Cooperativa de Quesos 'Las Cabra…  Espagne__Oviedo

In [12]:
# ou bien, écriture à la mode Julia
result = @from i in dfFour begin
    @select {
        i.Societe,
        Endroit = "$(i.Pays)_et_$(i.Ville)"
    }
    @collect DFR.DataFrame
end

# affichage
println(DFR.first(result,5))
5×2 DataFrame
 Row │ Societe                            Endroit                        
     │ String                             String                         
─────┼───────────────────────────────────────────────────────────────────
   1 │ Exotic Liquids                     Royaume-Uni_et_London
   2 │ Nouvelle-Orléans Cajun Delights    Etats-Unis_et_Nouvelle-Orléans
   3 │ Grandma Kelly's Homestead          Etats-Unis_et_Ann Arbor
   4 │ Tokyo Traders                      Japon_et_Tokyo
   5 │ Cooperativa de Quesos 'Las Cabra…  Espagne_et_Oviedo
In [13]:
# on peut aussi créer en amont la nouvelle variable
# avec la macro @let
result = @from i in dfFour begin
    @let new_name = "$(i.Pays)_et_$(i.Ville)"
    @select {
        i.Societe,
        Endroit = new_name
    }
    @collect DFR.DataFrame
end

# affichage
println(DFR.first(result,5))
5×2 DataFrame
 Row │ Societe                            Endroit                        
     │ String                             String                         
─────┼───────────────────────────────────────────────────────────────────
   1 │ Exotic Liquids                     Royaume-Uni_et_London
   2 │ Nouvelle-Orléans Cajun Delights    Etats-Unis_et_Nouvelle-Orléans
   3 │ Grandma Kelly's Homestead          Etats-Unis_et_Ann Arbor
   4 │ Tokyo Traders                      Japon_et_Tokyo
   5 │ Cooperativa de Quesos 'Las Cabra…  Espagne_et_Oviedo

In [14]:
# nouveau champ que l'on peut utiliser dans le filtrage
result = @from i in dfFour begin
    @let new_name = "$(i.Pays)_et_$(i.Ville)"
    @where occursin("France",new_name)
    @select {
        i.Societe,
        Endroit = new_name
    }
    @collect DFR.DataFrame
end

# affichage
println(result)
3×2 DataFrame
 Row │ Societe                     Endroit            
     │ String                      String             
─────┼────────────────────────────────────────────────
   1 │ Aux joyeux ecclésiastiques  France_et_Paris
   2 │ Escargots Nouveaux          France_et_Montceau
   3 │ Gai pâturage                France_et_Annecy

Regroupement¶

In [15]:
# regroupement et comptage
# on a un equivalent de groupby
result = @from i in dfFour begin
    @group i by i.Pays into g
    @select {Country = key(g), Nombre = length(g)}
    @collect DFR.DataFrame
end

# affichage
println(result)
16×2 DataFrame
 Row │ Country      Nombre 
     │ String       Int64  
─────┼─────────────────────
   1 │ Royaume-Uni       2
   2 │ Etats-Unis        4
   3 │ Japon             2
   4 │ Espagne           1
   5 │ Australie         2
   6 │ Suède             2
   7 │ Brésil            1
   8 │ Allemagne         3
   9 │ Italie            2
  10 │ Norvège           1
  11 │ France            3
  12 │ Singapour         1
  13 │ Danemark          1
  14 │ Pays-Bas          1
  15 │ Finlande          1
  16 │ Canada            2
In [16]:
# regroupement et filtrage
result = @from i in dfFour begin
    @group i by i.Pays into g
    @where length(g) > 1
    @select {Country = key(g), Nombre = length(g)}
    @collect DFR.DataFrame
end

# affichage
println(result)
9×2 DataFrame
 Row │ Country      Nombre 
     │ String       Int64  
─────┼─────────────────────
   1 │ Royaume-Uni       2
   2 │ Etats-Unis        4
   3 │ Japon             2
   4 │ Australie         2
   5 │ Suède             2
   6 │ Allemagne         3
   7 │ Italie            2
   8 │ France            3
   9 │ Canada            2

In [17]:
# la requête n'a aucun sens, juste pour montrer la possibilité
# champ calculé = moyenne des numéros associés aux groupes
import Statistics as ST

result = @from i in dfFour begin
    @group i by i.Pays into g
    @where length(g) > 1
    @select {Country = key(g), Nombre = length(g), Moyenne = ST.mean(g.Num_fournisseur)}
    @collect DFR.DataFrame
end

# affichage
println(result)
9×3 DataFrame
 Row │ Country      Nombre  Moyenne 
     │ String       Int64   Float64 
─────┼──────────────────────────────
   1 │ Royaume-Uni       2   4.5
   2 │ Etats-Unis        4  10.0
   3 │ Japon             2   5.0
   4 │ Australie         2  15.5
   5 │ Suède             2  13.0
   6 │ Allemagne         3  12.0
   7 │ Italie            2  20.0
   8 │ France            3  24.3333
   9 │ Canada            2  27.0

Tri¶

In [18]:
# trier selon un champ (nom du Pays)
result = @from i in dfFour begin
    @orderby i.Pays
    @select {i.Societe,i.Pays}
    @collect DFR.DataFrame
end

# affichage
println(result)
29×2 DataFrame
 Row │ Societe                            Pays        
     │ String                             String      
─────┼────────────────────────────────────────────────
   1 │ Heli Süßwaren GmbH & Co. KG        Allemagne
   2 │ Plutzer Lebensmittelgroßmärkte AG  Allemagne
   3 │ Nord-Ost-Fisch Handelsgesellscha…  Allemagne
   4 │ Pavlova, Ltd.                      Australie
   5 │ G'day, Mate                        Australie
   6 │ Refrescos Americanas LTDA          Brésil
   7 │ Ma Maison                          Canada
   8 │ Forêts d'érables                   Canada
   9 │ Lyngbysild                         Danemark
  10 │ Cooperativa de Quesos 'Las Cabra…  Espagne
  11 │ Nouvelle-Orléans Cajun Delights    Etats-Unis
  12 │ Grandma Kelly's Homestead          Etats-Unis
  13 │ Bigfoot Breweries                  Etats-Unis
  14 │ New England Seafood Cannery        Etats-Unis
  15 │ Karkki Oy                          Finlande
  16 │ Aux joyeux ecclésiastiques         France
  17 │ Escargots Nouveaux                 France
  18 │ Gai pâturage                       France
  19 │ Formaggi Fortini s.r.l.            Italie
  20 │ Pasta Buttini s.r.l.               Italie
  21 │ Tokyo Traders                      Japon
  22 │ Mayumi's                           Japon
  23 │ Norske Meierier                    Norvège
  24 │ Zaanse Snoepfabriek                Pays-Bas
  25 │ Exotic Liquids                     Royaume-Uni
  26 │ Specialty Biscuits, Ltd.           Royaume-Uni
  27 │ Leka Trading                       Singapour
  28 │ PB Knäckebröd AB                   Suède
  29 │ Svensk Sjöföda AB                  Suède
In [19]:
# trier selon un champ calculé
# et filter
result = @from i in dfFour begin
    @group i by i.Pays into g
    @let moyenne = ST.mean(g.Num_fournisseur)
    @orderby descending(moyenne)
    @where length(g) > 1
    @select {Country = key(g), Nombre = length(g), Moyenne = moyenne}
    @collect DFR.DataFrame
end

# affichage
println(result)
9×3 DataFrame
 Row │ Country      Nombre  Moyenne 
     │ String       Int64   Float64 
─────┼──────────────────────────────
   1 │ Canada            2  27.0
   2 │ France            3  24.3333
   3 │ Italie            2  20.0
   4 │ Australie         2  15.5
   5 │ Suède             2  13.0
   6 │ Allemagne         3  12.0
   7 │ Etats-Unis        4  10.0
   8 │ Japon             2   5.0
   9 │ Royaume-Uni       2   4.5

Requêtes multi-tables (avec jointures)¶

In [20]:
# Chargement de la table Produits
dfProd = DFR.DataFrame(XLSX.readtable("./produits.xlsx"))
println(DFR.first(dfProd,10))
10×5 DataFrame
 Row │ Ref_produit  Nom_produit                      Num_fournisseur  Quantite_par_unite       Prix_unitaire 
     │ Int64        String                           Int64            String                   Float64       
─────┼───────────────────────────────────────────────────────────────────────────────────────────────────────
   1 │           1  Chai                                           1  10 boîtes x 20 sacs              18.0
   2 │           2  Chang                                          1  24 bouteilles (1 litre)          19.0
   3 │           3  Aniseed Syrup                                  1  12 bouteilles (550 ml)           10.0
   4 │           4  Chef Anton's Cajun Seasoning                   2  48 pots (6 onces)                22.0
   5 │           5  Chef Anton's Gumbo Mix                         2  36 boîtes                        21.35
   6 │           6  Grandma's Boysenberry Spread                   3  12 pots (8 onces)                25.0
   7 │           7  Uncle Bob's Organic Dried Pears                3  12 cartons (1 kg)                30.0
   8 │           8  Northwoods Cranberry Sauce                     3  12 pots (12 onces)               40.0
   9 │           9  Mishi Kobe Niku                                4  18 cartons (500 g)               97.0
  10 │          10  Ikura                                          4  12 pots (200 g)                  31.0

In [21]:
# nom de societe de fournisseur par produit
# avec une sorte de double boucle (pas optimal du tout)
# mais ça marche...
result = @from i in dfProd begin
            @from j in dfFour
                @where (i.Num_fournisseur == j.Num_fournisseur)
                @select {i.Nom_produit,i.Num_fournisseur, j.Societe}
                @collect DFR.DataFrame
end

# affichage
print(DFR.first(result,10))
10×3 DataFrame
 Row │ Nom_produit                      Num_fournisseur  Societe                         
     │ String                           Int64            String                          
─────┼───────────────────────────────────────────────────────────────────────────────────
   1 │ Chai                                           1  Exotic Liquids
   2 │ Chang                                          1  Exotic Liquids
   3 │ Aniseed Syrup                                  1  Exotic Liquids
   4 │ Chef Anton's Cajun Seasoning                   2  Nouvelle-Orléans Cajun Delights
   5 │ Chef Anton's Gumbo Mix                         2  Nouvelle-Orléans Cajun Delights
   6 │ Grandma's Boysenberry Spread                   3  Grandma Kelly's Homestead
   7 │ Uncle Bob's Organic Dried Pears                3  Grandma Kelly's Homestead
   8 │ Northwoods Cranberry Sauce                     3  Grandma Kelly's Homestead
   9 │ Mishi Kobe Niku                                4  Tokyo Traders
  10 │ Ikura                                          4  Tokyo Traders
In [22]:
# avec la macro @join pour jointure
# autrement plus indiqué
result = @from i in dfProd begin
         @left_outer_join j in dfFour on i.Num_fournisseur equals j.Num_fournisseur
         @select {i.Nom_produit,i.Num_fournisseur, j.Societe}
         @collect DFR.DataFrame
end

# affichage
print(DFR.first(result,10))
10×3 DataFrame
 Row │ Nom_produit                      Num_fournisseur  Societe                         
     │ String                           Int64            String?                         
─────┼───────────────────────────────────────────────────────────────────────────────────
   1 │ Chai                                           1  Exotic Liquids
   2 │ Chang                                          1  Exotic Liquids
   3 │ Aniseed Syrup                                  1  Exotic Liquids
   4 │ Chef Anton's Cajun Seasoning                   2  Nouvelle-Orléans Cajun Delights
   5 │ Chef Anton's Gumbo Mix                         2  Nouvelle-Orléans Cajun Delights
   6 │ Grandma's Boysenberry Spread                   3  Grandma Kelly's Homestead
   7 │ Uncle Bob's Organic Dried Pears                3  Grandma Kelly's Homestead
   8 │ Northwoods Cranberry Sauce                     3  Grandma Kelly's Homestead
   9 │ Mishi Kobe Niku                                4  Tokyo Traders
  10 │ Ikura                                          4  Tokyo Traders
In [23]:
# liste des produits, dont le prix est > 50, et leurs fournisseurs
result = @from i in dfProd begin
         @left_outer_join j in dfFour on i.Num_fournisseur equals j.Num_fournisseur
         @where i.Prix_unitaire > 50
         @select {i.Nom_produit, j.Societe, i.Prix_unitaire}
         @collect DFR.DataFrame
end

# affichage
print(result)
7×3 DataFrame
 Row │ Nom_produit              Societe                            Prix_unitaire 
     │ String                   String?                            Float64       
─────┼───────────────────────────────────────────────────────────────────────────
   1 │ Mishi Kobe Niku          Tokyo Traders                              97.0
   2 │ Carnarvon Tigers         Pavlova, Ltd.                              62.5
   3 │ Sir Rodney's Marmalade   Specialty Biscuits, Ltd.                   81.0
   4 │ Thüringer Rostbratwurst  Plutzer Lebensmittelgroßmärkte AG         123.79
   5 │ Côte de Blaye            Aux joyeux ecclésiastiques                263.5
   6 │ Manjimup Dried Apples    G'day, Mate                                53.0
   7 │ Raclette Courdavault     Gai pâturage                               55.0
In [24]:
# prix moyen par fournisseur
# trié par ordre décroissant
result = @from i in dfFour begin
         @join j in dfProd on i.Num_fournisseur equals j.Num_fournisseur
         @group j.Prix_unitaire by i.Societe into g
         @let avg_prix = ST.mean(g)
         @orderby descending(avg_prix)
         @select {Fournisseur = key(g), Prix_Moyen = avg_prix}
         @collect DFR.DataFrame
end

# affichage
print(result)
29×2 DataFrame
 Row │ Fournisseur                        Prix_Moyen 
     │ String                             Float64    
─────┼───────────────────────────────────────────────
   1 │ Aux joyeux ecclésiastiques           140.75
   2 │ Tokyo Traders                         46.0
   3 │ Plutzer Lebensmittelgroßmärkte AG     44.678
   4 │ Gai pâturage                          44.5
   5 │ Forêts d'érables                      38.9
   6 │ Pavlova, Ltd.                         35.57
   7 │ Grandma Kelly's Homestead             31.6667
   8 │ G'day, Mate                           30.9333
   9 │ Heli Süßwaren GmbH & Co. KG           29.71
  10 │ Cooperativa de Quesos 'Las Cabra…     29.5
  11 │ Pasta Buttini s.r.l.                  28.75
  12 │ Specialty Biscuits, Ltd.              28.175
  13 │ Leka Trading                          26.4833
  14 │ Formaggi Fortini s.r.l.               26.4333
  15 │ Nord-Ost-Fisch Handelsgesellscha…     25.89
  16 │ Nouvelle-Orléans Cajun Delights       20.35
  17 │ Norske Meierier                       20.0
  18 │ Svensk Sjöföda AB                     20.0
  19 │ Karkki Oy                             18.0833
  20 │ Ma Maison                             15.725
  21 │ Exotic Liquids                        15.6667
  22 │ Bigfoot Breweries                     15.3333
  23 │ PB Knäckebröd AB                      15.0
  24 │ Mayumi's                              14.9167
  25 │ New England Seafood Cannery           14.025
  26 │ Escargots Nouveaux                    13.25
  27 │ Zaanse Snoepfabriek                   11.125
  28 │ Lyngbysild                            10.75
  29 │ Refrescos Americanas LTDA              4.5