Filtrer les données avec Envision

Filtrer les données










Accueil » Ressources » Ici

Toute analyse commerciale repose sur des données filtrées. Envision permet de filtrer vos données de façon approfondie, grâce aux conditions where et when, qui peuvent être utilisées pour filtrer les données manipulées par tout un bloc du script ou par une instruction individuelle. Cette section est une présentation pratique de ces concepts.


Un script d'illustration

Une fois encore, commençons avec l'échantillon de données qui devrait être accessible à l'adresse /sample dans votre compte Lokad. Le script ci-dessous est modérément complexe et illustre certaines possibilités de filtre disponibles dans Envision. Si vous ne l'avez encore fait, nous vous recommandons de tout d'abord lire Faire des calculs avec Envision, avant de consulter les informations de cette section.
read "/sample/Lokad_Items.tsv"
read "/sample/Lokad_Orders.tsv" as O

show label "Filtering data" a1f1 tomato

oend := max(O.Date)

when date > oend - 365
LastYearQty = sum(O.Quantity)
where StockOnHand + StockOnOrder > LastYearQty
show table "Overstocked items, +1 year of stock" a2f3 tomato with 
Id
Name
StockOnHand + StockOnOrder as "Stock"
LastYearQty

where O.NetAmount > 1000
show table "Large transactions over $1000" a4f5 tomato with 
Id
Name 
O.Date 
O.Quantity
O.NetAmount
O.Client

lastDay := monday(oend)
firstDay := lastDay - 52 * 7
when date >= firstDay & date < lastDay
Week.sold := sum(O.NetAmount)
show linechart "Sold by week" a6f7 tomato unit:"$" with
Week.sold

Nous recommandons de copier-coller ce script dans votre compte Lokad et de l'exécuter une fois afin de visualiser le tableau de bord qui en résulte. Si tout fonctionne correctement, vous devriez voir le tableau de bord suivant.

Image

Les blocs filtrés

Lorsque l'on souhaite travailler sur des données historiques qui ont moins d'un an, par exemple, beaucoup de calculs doivent être effectués. Dans une telle situation, le filtre « seulement de l'année passée » doit s'appliquer à tous les calculs. Pour cette raison, dans Envision, les filtres s'appliquent en général à toutes les données manipulées par un bloc de code. L'extrait de script ci-dessous illustre deux blocs filtrés imbriqués. Le premier commence à la ligne 1 avec une condition when et il est suivi d'un second bloc qui commence à la ligne 3 avec une condition where.
when date > oend - 365
LastYearQty = sum(O.Quantity)
where StockOnHand + StockOnOrder > LastYearQty
show table "Overstocked items, +1 year of stock" a2f3 tomato with
Id
Name
StockOnHand + StockOnOrder as "Stock"
LastYearQty
Envision est un langage qui prend en compte les espaces en début de ligne. Un ensemble de lignes qui commencent par le même nombre d'espaces est appelé un « bloc de code », ces blocs peuvent être imbriqués, c’est-à-dire qu'un bloc peut en contenir un autre.

Si c'est la première fois que vous rencontrez un tel modèle de programmation, cela peut vous paraître un peu déconcertant. Mais, dans la pratique, l'éditeur Envision vous aide beaucoup : lorsque vous appuyez sur Entrée à la fin d'une ligne qui contient une condition, la ligne suivante est automatiquement indentée avec deux espaces.

Note aux développeurs : la gestion des espaces est similaire à celle utilisée en Python. Cette approche est bien appropriée à Envision qui cherche à proposer une syntaxe concise pour manipuler des données. Puisqu'il n'y a pas de boucle ni de saut dans Envision, le niveau d'indentation est rarement supérieur à 3, ce qui reste raisonnable.

Un bloc filtré commence avec une condition — informations détaillées à ce sujet ci-dessous — qui peut être vraie ou fausse pour chaque ligne de chaque table. Au sein du bloc, seules les lignes qui remplissent la condition initiale sont manipulées, les autres en sont exclues. La condition when correspond à un filtre temporel et s'applique à toutes les tables indexées avec une colonne Date. La condition where est généralement utilisée pour filtrer les articles et s'applique aux tables indexées avec une colonne Id.

Une fois un bloc commencé, seules les lignes de données qui remplissent la condition sont gardées. Tout le reste fonctionne normalement, et toutes les commandes envisageables en dehors d'un bloc peuvent y être incluses. Il est notamment possible de définir un second filtre au sein d'un bloc. Il s'agit d'une « imbrication ». Dans l'exemple ci-dessus, le bloc where, qui commence à la ligne 3, est imbriqué dans le bloc when, qui lui commence à la ligne 1.

Créer une condition

Une condition est une expression qui peut être vraie ou fausse. La notion de filtre repose sur la composition des conditions qui sont évaluées avec les données d'entrée et éventuellement les résultats de calculs intermédiaires. Il est possible de créer des conditions évoluées dans Envision, comme le montre le script qui suit :
lastDay := monday(oend)
firstDay := lastDay - 52 * 7
when date >= firstDay & date < lastDay
Week.sold := sum(O.NetAmount)
show linechart "Sold by week" a6f7 tomato unit:"$" with
Week.sold

Dans cet extrait, l'opérateur and indique que les deux expressions à gauche et à droite de l'opérateur doivent être vraies. Les opérateurs logiques utilisables dans Envision sont : and, or and not. De plus, les nombres peuvent être comparés avec des opérateurs numériques : == (égalité), != (inégalité), <= (inférieur ou égal), >= (supérieur ou égal), < (inférieur), > (supérieur). L'extrait ci-dessous illustre comment ces opérateurs peuvent être combinés et évalués.
a := 1 > 10 // faux
b := not a // vrai
c := a | b // vrai
d := a & b // faux
e := 10 >= 3 | 5 > 7 // vrai
show table "Conditions" with a, b, c, d, e
Lorsqu'un filtre de bloc est imbriqué dans un autre, la logique d'un opérateur and s'applique entre les conditions des deux filtres.

Dans l'exemple ci-dessus, vous avez peut-être remarqué la syntaxe monday(end). C'est un appel de la fonction monday. Pour n'importe quelle date, cette fonction renvoie le dernier lundi avant la date indiquée en argument (incluse). Si l'argument est un lundi, la fonction renvoie la même date.

Cette fonction Monday() est utilisée pour définir une période composée de semaines complètes (et non partielles). Lorsque l'on effectue un regroupement à la semaine, seules les semaines complètes doivent être prises en compte sinon la première et la dernière valeur seraient très basses puisque calculées sur des semaines incomplètes.

Filtrer les tables par date

Envision permet de filtrer les tables avec des conditions temporelles de façon approfondie. Le script que nous venons de voir filtre toutes les lignes qui ont plus d'un an. Détaillons les commandes concernées.
oend := max(O.Date)
when date > oend - 365
  LastYearQty = sum(O.Quantity)
Envision traite les dates comme des nombres entiers de jours depuis le 1er janvier 2001. Ceci offre de nombreux avantages dont la possibilité d'effectuer des opérations arithmétiques sur les dates. Par exemple, en soustrayant 7 à une date, on atteint la semaine précédente, tandis qu'en soustrayant 365, on atteint (approximativement) la date de l'année précédente.

Le mot-clé date a aussi un fonctionnement spécial. De façon implicite, la variable date correspond à toutes les tables qui contiennent une colonne Date. Puisqu'une seule table est manipulée ici, la table O, c'est comme si nous écrivions O.Date > oend - 365. Cependant, la syntaxe date est non seulement plus précise mais elle s'applique à toutes les tables concernées en une fois. Si, au lieu de chercher les quantités vendues, nous nous étions intéressés aux quantités achetées, le script aurait été le suivant :
// chargement des commandes d'achat
read "/sample/Lokad_PurchaseOrders.tsv" as PO 

// coupure

when date > oend - 365
  LastYearQty = sum(PO.Quantity)

Filtrer les articles

Envision offre également la possibilité de filtrer les articles, ce qui est utilisé fréquemment pour exclure certains produits, certains sites, certaines catégories, etc. Le script vu au début de la section de la présente page illustre comment le périmètre peut être limité à des articles dont le stock peut être qualifié de mort. Les lignes de code concernées sont les suivantes :
where StockOnHand + StockOnOrder > LastYearQty
show table "Overstocked items, +1 year of stock" a2f3 tomato with
Id
Name
StockOnHand + StockOnOrder as "Stock"
LastYearQty
Le mot-clé where est suivi d'une condition. Celle-ci s'applique aux trois vecteurs qui appartiennent implicitement à la table Items. En effet, c'est la seule table à laquelle il est possible de faire référence sans indiquer son nom en préfixe du nom d'une variable. Par exemple, il faut écrire O.NetAmount et pas simplement NetAmount pour faire référence aux lignes de la table O. Ici, la condition doit être comprise ainsi : n'inclure que les articles pour lesquels la somme du stock disponible et du stock en commande est supérieure au nombre d'unités vendues l'année passée.

Une fois qu'une condition est définie pour la table Items, toutes les tables qui contiennent une colonne Id — un identifiant qui fait référence aux articles, conformément aux conventions Envision — sont filtrées de la même façon. Ce fonctionnement est identique pour les filtres temporels, dont nous avons parlé précédemment. En effet, une fois que les articles sont filtrés, il est inutile de garder des ventes ou des achats qui ne sont pas rattachés aux articles sélectionnés mais à des articles exclus du périmètre.

Les vecteurs nouvellement calculés sont impactés par le filtre qui s'applique aux articles, comme l'illustre ce petit script.
where StockOnHand > 5
GreaterThanFive = "yes"
show table "Hello" with
Name
GreaterThanFive // CORRECT!

// fin du bloc
show table "Hello" with
Name
GreaterThanFive // INCORRECT!
La ligne 10 est erronée parce que le vecteur GreaterThanFive n'est défini que pour les lignes pour lesquelles la condition StockOnHand > 5 est vraie. Donc, même si ce vecteur est correctement défini dans le bloc et peut être utilisé comme en ligne 5, il ne peut être utilisé en dehors du bloc car certaines de ses valeurs seraient indéfinies. Ces situation eut être corrigées en veillant à ce que le vecteur soit défini correctement pour toutes ses valeurs d'article, comme ci-dessous.
GreaterThanFive = "no"
where StockOnHand > 5
GreaterThanFive = "yes"
show table "Hello" with 
Name
GreaterThanFive // CORRECT!

// fin du bloc
show table "Hello" with
Name
GreaterThanFive // CORRECT!
Cet extrait commence, à la ligne 1, avec une définition correcte du vecteur GreaterThanFive pour tous les articles. Cette définition est modifiée en ligne 4 pour un sous-ensemble d'articles. Cependant, cette modification ne change rien au fait que le vecteur GreaterThanFive est défini explicitement pour tous les articles et, par conséquent, l'affiche en ligne 12 est maintenant correct.

Filtrer les tables arbitraires

Si les filtres sur les dates et les articles sont utiles, il est parfois nécessaire de filtrer de façon précise une table en particulier. C'est possible avec le mot-clé where, voyons un exemple.
where O.NetAmount > 1000
show table "Large transactions over $1000" a4f5 tomato with
Id
Name
O.Date
O.Quantity
O.NetAmount
O.Client
Avec ce script, la table O est filtrée pour exclure toutes les lignes où la commande est inférieure à 1 000 $. Les lignes de données conservées sont affichées avec show table aux lignes 2 et 3. L'exemple montre comment filtrer une seule table. Ce filtre n'impacte en effet que la table O et ne concerne pas les autres tables.

Si un vecteur associé à la table O est calculé dans le bloc du filtre, alors ce vecteur ne peut être manipulé qu'au sein du bloc. Nous avons déjà observé ce fonctionnement pour les articles, voyons maintenant comment cela s'applique également aux tables arbitraires.
where O.NetAmount > 1000
O.LargeTxn = "yes"
show table "Large transactions" with
Name
O.LargeTxn // CORRECT!
// fin du bloc
show table "Large transactions" with
Name
O.LargeTxn // INCORRECT!
Puisque le vecteur O.LargeTxn n'est pas défini pour toutes les lignes de la table O, seule la ligne 5 est correcte, la ligne 10 est incorrecte. Comme dans l'exemple précédent, la solution consiste à définir correctement une valeur LargeTxn pour l'ensemble de la table O, comme suit :
O.LargeTxn = "no"
where O.NetAmount > 1000
O.LargeTxn = "yes"
show table "Large transactions" with
Name
O.LargeTxn // CORRECT!
// fin du bloc
show table "Large transactions" with
Name
O.LargeTxn // CORRECT!
De manière générale, Envision permet les fuites en dehors de blocs autant que possible : un vecteur calculé dans un bloc peut être utilisé en dehors de ce bloc, tant que cet usage n'enfreint pas la règle selon laquelle toutes les valeurs du vecteur doivent être définies explicitement lorsque ce dernier est à droite dans une condition.

Sucres syntaxiques destinés aux filtres

Le modèle de syntaxe utilise par Envision « filtrer et indenter » est concis et facile à lire, mais lorsque plusieurs filtres entrent en jeu, l'indentation peut devenir plus difficile à déchiffrer. Ainsi, Envision offre quelques sucres syntaxiques, c’est-à-dire des syntaxes alternatives qui nécessitent moins d'indentation. Ces syntaxes sont présentées ci-dessous.

Éviter les indentations lorsque plusieurs filtres sont utilisés

Un seul niveau d'indentation supplémentaire est requis par filtre dans Envision, si les filtres sont censés être utilisés séparément. Si seul le périmètre le plus interne est concerné, un seul niveau d'indentation est nécessaire, comme illustré ci-dessous :
// chaque filtre 'where' implique 
// un niveau d'indentation
where O.Quantity > 10
where StockOnHand < 100
show table "Filtered orders" with
O.Quantity

// mais lorsque plusieurs filtres sont utilisés,
// une seule indentation est nécessaire
where O.Quantity > 10
where StockOnHand < 100 // pas d'indentation !
show table "Filtered orders" with O.Quantity
Le second bloque a la même syntaxe que le premier, mais ne nécessite qu'une seule indentation. Plus généralement la syntaxe est la suivante :
where A
when B
where C
show table "Filtered by A, B and C" with X
// identique à
where A
when B
where C
show table "Filtered by A, B and C" with X

Fusionner des filtres avec le mot clé and

Nous avons déjà vu que, dans Envision, l'opérateur booléen AND est représenté par le symbôle &. Cependant, Envision propose aussi un mot-clé and, dont la sémantique est légèrement différente :
// deux filtres 'where' imbriqués
where O.NetAmount > 1000 
where StockOnHand > 10
show table "Filtered transactions" with
Name
O.Quantity

// peuvent être réécrit avec 'and'
where O.NetAmount > 1000 and StockOnHand > 10
show table "Filtered transactions" with 
Name
O.Quantity
L'utilisation du mot-clé and est équivalente à l'imbrication de filtres where. Ce mot-clé permet d'utiliser plusieurs filtres l'un après l'autre, avec un seul niveau d'indentation. De façon générale, nous avons :
where A
where B
where C
// coupure

// equivalent à
where A and B and C
// coupure
En pratique, le mot-clé and offre la possibilité de fusionner plusieurs filtres qui sont censés être utilisés ensemble.

Aucune indentation avec le mot-clé keep

Il est fréquent d'utiliser des filtres au début d'un bloc de code dans le but de restreindre l'analyse de données à un périmètre donné. La syntaxe des filtres d'Envision fonctionne relativement bien dans ce cas, mais dès lors le script est écrit entièrement avec un ou deux niveaux d'indentation. Le mot-clé keep permet de les supprimer :
// le filtre 'where' amène un bloc indenté
where O.Quantity > 10
// début du bloc
show table "Inside the filter" with
sum(O.Quantity)
// fin du bloc
show table "Outside the filter" with
sum(O.Quantity)

// mais avec 'keep'
// le filter s'applique sans indentation
keep where O.Quantity > 10
show table "Inside the filter" with
sum(O.Quantity)
Le mot-clé keep doit être placé avant where ou when et indique que le filtre s'applique sans indentation. Le filtre est actif jusqu'à la fin du périmètre.
where A
keep where B
show table "Filtered by A and B" with X
// fin des filtres A et B 
show table "Not filtered" with X
Ainsi, si keep est placé sur une ligne de script non indentée, le filter s'applique jusqu'à la fin du script.

Filtres suffixes en ligne

Jusqu'à présent, toutes les conditions que nous avons observées étaient rédigées sous forme de bloc. Envision offre également une syntaxe alternative, plus compacte, que l'on appelle les suffixes de condition. Revenons au calcul des quantités vendues l'année passée.
when date > oend - 365
  LastYearQty = sum(O.Quantity)
Ce script peut être réécrit comme suit :
LastYearQty = sum(O.Quantity) when date > oend - 365
Le lecteur qui connait les bases de données relationnelles rapprochera cette syntaxe de la façon dont les conditions where sont rédigées en SQL. Dans Envision, c'est principalement un sucre syntaxique pour éviter des blocs d'une ligne lorsqu'une seule instruction est nécessaire après le filtre. where et when peuvent tous deux être ajoutés en tant que suffixes tout à droite d'une instruction.

Les agrégateurs peuvent être filtrés avec les conditions when ou where. Envision offre aussi la possibilité d'ajouter un modificateur else à la condition. L'exemple suivant est incorrect :
oend := max(O.Date)
lastDay := monday(oend)
Week.sold := sum(O.NetAmount) when date < lastDay
show linechart "Sold by week" with
Week.sold // WRONG
En effet, Week.sold n'est pas défini sur tout le périmètre car filtré à la deuxième ligne, mais, en ajoutant l'option else, nous définissons Week.sold pour tous les cas :
oend := max(O.Date)
lastDay := monday(oend)
Week.sold := sum(O.NetAmount) when date < lastDay else 0
show linechart "Sold by week" with
Week.sold // CORRECT