Blog entries june 2022 [2]

Pandas, Plotly et Jupyter : De l’analyse de données à l’application en ligne (2/3)

27/06/2022 by Simon Chabot

Temps de lecture estimé 10 minutes.

Dans un article précédent nous vous proposions une analyse de données à l’aide de la bibliothèque Pandas. Nous y avions construit une série de graphiques simples pour réaliser cette analyse. Dans cet épisode, nous allons aborder les widgets qui vont nous permettre de rendre ces graphiques dynamiques.

Il est conseillé d’avoir lu l’article précédent qui détaille la structure des données utilisées.

Qu’est-ce qu’un widget ?

Dans un calepin jupyter, le code peut facilement être édité et rejoué. Il est donc assez simple d’effectuer des changements. Il est toutefois possible que les utilisateurs finaux de l’application ne sachent pas programmer ou simplement qu’on préfère avoir un moyen simple d'interagir (sans avoir à relire le code Python et à le modifier). Dans de tels cas, les widgets constituent une bonne solution.

Les widgets sont des objets qui sont rendus dynamiquement dans les calepins Jupyter, et avec lesquels il est possible d’interagir.

La bibliothèque de base pour construire ces widgets est ipywidgets.

Dans l’exemple ci-dessous, la bibliothèque est importée puis un curseur glissant est construit.

>>> import ipywidgets as ipw
>>> ipw.IntSlider(min=0, max=20, step=2)

À l’exécution de la cellule Jupyter, le widget est affiché.

La connexion entre le widget affiché dans la page Web et l’objet python a été automatiquement définie. Cela signifie que si l’objet python est modifié, le rendu du widget est modifié et vice-versa. Dans le cas présent, l’attribut value du widget vaut 6.

À titre d’exemple, on peut construire un curseur glissant comme ceci :

>>> slider = ipw.IntSlider(min=0, max=20, step=2)
>>> slider

puis modifier dynamiquement la valeur de cet objet. Le rendu sera alors mis à jour.

>>> from time import sleep
>>> for i in range(0, 22, 2):
...    sleep(1)
...    slider.value = i

Les widgets deviennent très intéressants dès lors que l’on associe des fonctions python à des évènements. Dans l’exemple ci-dessous, nous avons défini deux widgets de type “curseur glissant” et un widget d’affichage. Nous voulons afficher dans ce dernier widget la somme des deux curseurs.

On construit un widget de type Bouton, et on associe le clic sur ce bouton à l’appel de la fonction compute_add qui somme les valeurs des deux curseurs et met à jour l’affichage.

>>> from IPython.display import clear_output
>>> sld1 = ipw.IntSlider(min=0, max=20)
>>> sld2 = ipw.IntSlider(min=0, max=20)
>>>
>>> out = ipw.Output()
>>> with out:
...    print("0 + 0 = 0")
...
>>> def compute_add(evt):
...    with out:
...       clear_output()
...       res = sld1.value + sld2.value
...       print(f"{sld1.value} + {sld2.value} = {res}")
...
>>> btn = ipw.Button(description="Sum")
>>> btn.on_click(compute_add)
>>> ipw.HBox([ipw.VBox([sld1, sld2, btn]), out])

Le rendu est alors le suivant :

Utiliser un widget pour sélectionner les données à afficher

Dans l’épisode précédent, nous avions écrit une fonction pour charger toutes les données des licenciés inscrits dans les fédérations sportives pour les années 2012 à 2019. La fonction est la suivante :

>>> from pathlib import Path
>>> import pandas as pd
>>> DATA_DIR = Path().resolve() / "data"
>>> def load_data():
...    year_dfs = []
...    for year in range(2012, 2019):
...       fname = f"sport_license_holders_{year}.csv"
...       yr_df = pd.read_csv(
...          DATA_DIR / fname,
...          dtype={"dep_code": str},
...          index_col=["dep_code", "dep_name", "fed_code", "fed_name", "gender", "age"],
...       )
...       yr_df.rename(columns={"lic_holders": str(year)}, inplace=True)
...       year_dfs.append(yr_df)
...    data = pd.concat(year_dfs, axis=1)
...    return data
...
>>> d = load_data()

Le DataFrame résultant contient plus de 1.6 millions de lignes et 7 colonnes. Nous pouvons maintenant écrire une fonction très simple qui affiche l’évolution du nombre de licenciés de 2012 à 2019 pour les fédérations qui sont données en paramètre.

>>> pd.options.plotting.backend = "plotly"  # Choose Plotly as the plotting back-end
>>> def plot_license_holders_evolution_by_sport(data, fed_codes):
...    data_sports = data.groupby(level=["fed_code", "fed_name"]).sum()
...    sel_data_sports = data_sports.loc[list(fed_codes)]
...    sel_data_sports = sel_data_sports.droplevel(0)
...    sel_data_sports.index.name = "Federations"
...    fig = sel_data_sports.transpose().plot(title="Sport license holders")
...    fig.update_layout(xaxis_title="year", yaxis_title="number of license holders")
...    return fig
...
>>> plot_license_holders_evolution_by_sport(d, [109, 115, 242, 117])

Nous souhaitons utiliser un widget proposant de sélectionner une ou plusieurs disciplines, puis afficher le graphique correspondant lorsque la sélection est validée.

La première chose que nous réalisons est un dictionnaire contenant en clef le nom des fédérations sportives et en valeur leur numéro associé. Ce dictionnaire pourra être fourni à un widget de type SelectMultiple.

Nous utilisons le code suivant pour obtenir le dictionnaire de correspondance :

>>> def extract_federation_names_codes(data):
...    codes = data.index.get_level_values(
...        "fed_code"
...    )  # Extract all the values from the level ``fed_codes`` of the index
...    names = data.index.get_level_values(
...        "fed_name"
...    )  # Extract all the values from the level ``fed_names`` of the index
...    dic = {name: code for code, name in zip(codes, names)}
...    return dic
...

Et finalement, la fonction suivante permet de construire l’interface souhaitée :

>>> from IPython.display import display
>>> def build_gui(data):
...    fed_values = extract_federation_names_codes(data)
...    fed_wdg = ipw.SelectMultiple(
...        options=fed_values, description="Sport federations", rows=20
...    )
...    plt_btn = ipw.Button(description="Plot")
...    out_wdg = ipw.Output()
...    # Define the hook function that will be called each time the button is clicked
...    def refresh_plot(evt):
...        fed_codes = fed_wdg.value
...        with out_wdg:
...            clear_output()
...            display(plot_license_holders_evolution_by_sport(data, fed_codes))
...
...    plt_btn.on_click(refresh_plot)
...    gui_wdg = ipw.HBox([ipw.VBox([fed_wdg, plt_btn]), out_wdg])
...    return gui_wdg
...
>>> build_gui(d)

Nous venons ainsi de faire une fonction qui construit une interface utilisateur, composée d’un widget permettant de faire une sélection multiple. Lorsque la sélection est validée, la fonction d’affichage du graphique est rappelée, mettant ainsi le composant à jour. Le développement de cette interface utilisateur est bien plus simple que ce que nous aurions eu à faire avec d'autres solutions comme Qt, Tkinter ou même Flask + Javascript.

On voit que cela permet à tous les utilisateurs de faire leur propre analyse sans avoir à changer une seule ligne de code.

Dans le prochain épisode, nous présenterons Voila qui permet de transformer un calepin Jupyter en une petite application Web, utilisable sans aucune connaissance de Python. Nous utiliserons également jupyter-flex pour obtenir une jolie application Web dotée de bulles d’aides, d’onglets et d’un menu latéral.


Parrainage de SemWeb.Pro par l'AFIA

13/06/2022

Temps de lecture 2 min (350 mots)

Chaque année, Logilab organise la conférence SemWeb.Pro. Cette conférence regroupe plusieurs acteurs du monde des technologies du Web Sémantique pour discuter de leur application dans le cadre d'activités commerciales et industrielles. Pour cela des responsables de projets dans des entreprises, des universitaires, des étudiants et étudiantes, des indépendantes et indépendants, viennent présenter leurs derniers travaux devant la communauté de semweb.pro.

Ces présentations ont plusieurs objectifs : - démontrer des résultats obtenus avec des applications en production - faire connaitre et confronter des idées novatrices et de nouveaux projets - réfléchir et échanger collaborativement sur les évolutions du Web Sémantique dans le monde industriel - créer un réseau de personnes travaillant sur et avec ces sujets afin de créer de nouvelles opportunités pour chacun et chacune

Dans ce cadre, SemWeb.Pro est devenue une référence, et est attendue chaque année. Malgré les contraintes imposées par la pandémie de ces dernières années, la conférence a continué à avoir lieu à travers des outils de visio-conférence et la communauté a poursuivi les échanges et les discussions.

L'édition 2022 aura lieu le 8 novembre à Paris près de Denfert-Rochereau et nous nous réjouissons de pouvoir retrouver tout le monde en personne plutôt que par écran interposé. Nous vous tiendrons informés, via ce blog et les réseaux sociaux, de l'appel à communication.

Cette année, l'Association Française en Intelligence Artificielle) a décidé de soutenir la conférence. Ce parrainage va se concrétiser en deux actions:

  • les étudiants et les étudiantes pourront assister à la conférence gratuitement grâce à des subventions de l'AFIA (nous vous communiquerons les modalités pour obtenir ces subventions lorsqu'elles seront établies).
  • l'AFIA va communiquer sur différents canaux l'appel à communication et à participation à la conférence, pour accroître encore l'audience et la taille de la communauté.

Nous remercions chaleureusement l'AFIA et plus particulièrement Catherine Roussey et Sylvie Desprès (coordinatrices du collège Ingénierie des Connaissances de l'AFIA) pour avoir proposé ce parrainage. Nous sommes très fier que SemWeb.Pro soit reconnue comme participant au rayonnement de l'Intelligence Artificielle française.


Sponsonariat de PFIA 2022 par Logilab

08/06/2022

Temps de lecture 2 min (350 mots)

La Plateforme Française en Intelligence Artificielle a lieu tous les ans. Cette plateforme regroupe le fleuron de la recherche scientifique concernant l’intelligence artificielle en France. Elle regroupe sept conférences différentes, toutes concernant une branche de l’intelligence artificielle :

Conférence Nationale sur les Applications Pratiques de l’Intelligence Artificielle (APIA)
Conférence Nationale en Intelligence Artificielle (CNIA)
Journées Francophones d’Ingénierie des Connaissances (IC)
Journées Francophones sur la Planification, la Décision et l’Apprentissage pour la conduite de systèmes (JFPDA)
Journées Francophones sur les Systèmes Multi-Agents (JFSMA)
Journées d’Intelligence Artificielle Fondamentale (JIAF)
Rencontre des Jeunes Chercheurs en Intelligence Artificielle (RJCIA)

Logilab, qui s’est spécialisée dans les technologies du Web Sémantique, participe régulièrement, comme auditrice ou autrice, à la conférence IC, puisque c’est dans celle-ci que sont discutées les avancées concernant le Web Sémantique et le Web de données liées. On peut, par exemple, citer nos publications dans cette conférence en 2019, Un navigateur pour le Web des données liées, ou en 2020, CubicWeb : vers un outil pour des applications clé en main dans le Web Sémantique.

Nous apprécions les échanges que nous avons lors de cette conférence et c’est donc chaque année avec plaisir que nous y participons. De plus, la tenue au même moment et au même endroit des conférences connexes nous offre l’opportunité de découvrir de nouveaux sujets qui peuvent élargir notre horizon et nous donner des pistes à suivre lors de nos prochaines réalisations.

Après tous ces éloges pour la plateforme, il n’est pas surprenant que nous ayons décidé d’être sponsor de PFIA2022 qui se tiendra à l’École des Mines de St Etienne du 27 juin au 1er juillet. Il nous a paru naturel de soutenir une initiative qui nous semble centrale quant à l’évolution de la recherche scientifique française en intelligence artificielle.

Nous profitons de cet article pour annoncer que nous allons présenterons la suite de nos travaux de recherche lors de la session 9 de IC, le vendredi matin à 9h. Cette présentation s’intitule “OWL2YAMS : créer une application CubicWeb à partir d’une ontologie OWL”. Nous sommes impatients de pouvoir échanger sur ces sujets et de découvrir toutes les autres présentations.

On se donne rendez-vous à St Etienne ?