Séparation de la conception et des données dans matplotlib

Aperçu

Tâche

Je dessine souvent des graphiques à partir de ** Python ** en utilisant ** matplotlib **. Les données sont générées par l'application ** Python **, formatées et générées par le graphique ** matplotlib **.

À ce moment-là, j'avais les problèmes suivants.

Cause

Le code que vous écrivez ** visualise les données ** et le code que vous écrivez ** gère la conception ** Je pensais que c'était parce qu'il était écrit dans une seule application.

Correspondance

J'ai essayé de séparer le code pour ** gérer la conception ** en tant que ** fichier de configuration **.

Détails

Parmi les trois problèmes répertoriés, la «conception graphique n'est pas unifiée» est Cela signifie que la ** taille de l'étiquette **, la ** légende **, les ** points tracés **, etc. affectés aux axes vertical et horizontal ne sont pas unifiés.

Ceci est également lié à la deuxième tâche, car j'ai fait une ** description similaire ** dans un autre fichier Python.

Le problème était qu'il n'était pas ** unifié **, et je faisais une ** copie ** en me référant aux anciens fichiers Python sur place.

La raison pour laquelle ** copier-coller ** est répété est que le ** design ** et le ** code ** que je recherche Je pense que c'est parce que ce n'est pas lié, du moins pas intuitif. Cela conduit au troisième défi.

Je pensais que la raison de ces trois défis était que ** les données ** et la ** conception ** n'étaient pas ** séparées **.

Si tel est le cas, l'histoire est simple: séparez le ** design ** dans un ** fichier de configuration **.

Exprimez votre conception en mots dans un fichier de paramètres

J'ai essayé de faire correspondre le design et le mot comme indiqué dans le tableau ci-dessous.

La signification de chaque élément est

est.

-** Position ** - subplot --Où placer le graphique - pyplot.figure.add_subplot(subplot) - legend_location

Comment exprimer un fichier de paramètres spécifique

Pour le fichier de paramètres, nous avons considéré plusieurs méthodes d'expression, telles que json et yaml.

En conséquence, j'ai décidé d'utiliser le standard ** [configparser] 1 ** pour Python.

Je pense que json et yaml sont bien, mais j'ai pensé qu'il serait préférable de ** utiliser intuitivement ** plutôt que de l'exprimer de manière hiérarchique.

Le fichier de configuration est représenté par ** configparser ** comme suit.

config.ini


[Size]
figure_x=8
figure_y=8
font_title=20
font_x_label=18
font_y_label=18
font_tick=10
font_legend=15
marker=10

[Position]
subplot=111
legend_location=upper right

[Markers]
0=D
1=>
2=.
3=+
4=|

[Color]
0=red
1=blue
2=green
3=black
4=yellow

Les éléments qui correspondent à la ** classification de conception ** sont placés entre ** crochets ** tels que ** [Taille] **. C'est ce qu'on appelle la ** section **. En dessous, écrivez ** paramètre = valeur ** du fichier de paramètres. C'est ce qu'on appelle la ** clé **.

En plus de ** Taille ** et ** Position **, le fichier de configuration ci-dessus comprend également ** Marqueurs (type de marqueurs à tracer) ** et ** Couleur (couleur des marqueurs et des lignes à tracer) **. C'est exprimé.

Utilisez les paramètres décrits dans le fichier de configuration à partir du code Python

Pour accéder aux paramètres du fichier de configuration, écrivez le code comme suit:


import configparser


rule_file = configparser.ConfigParser()
rule_file.read("chemin du fichier de configuration", "UTF-8")

hogehoge = rule_file["Nom de la section"]["Nom de la clé"]

Notez que la valeur lue sera une ** chaîne **.

Exemple d'utilisation réelle

Le code ci-dessous crée un graphique en lignes de pliage basé sur les ** données transmises ** et le ** fichier de configuration de conception **.

make_line_graph.py


"""Fonction de création de graphique linéaire

Dessinez un graphique linéaire en utilisant les données transmises et enregistrez-le comme données d'image.

"""


import configparser
import matplotlib.pyplot as plt


def make_line_graph(data, config="config.ini"):
    """Dessin graphique linéaire

Créez un graphique linéaire en utilisant les données transmises.
Lisez la conception à partir d'un autre fichier de configuration.

    Args:
        data(dict):Contient des données à tracer
        config(str):Le nom du fichier de configuration

    Returns:
        bool:Si True, la création est terminée, si False, la création échoue

    Note:
La clé et la valeur à inclure dans les données d'argument sont décrites ci-dessous.

        key         : value
        ------------------------
        title(str):Nom du titre du graphique
        label(list):Description de la légende
        x_data(list):données de l'axe des x
        y_data(list):données de l'axe y
        x_ticks(list):Valeur à afficher dans la mémoire de l'axe x
        y_ticks(list):Valeur à afficher dans la mémoire de l'axe y
        x_label(str):nom de l'axe des x
        y_label(str):nom de l'axe y
        save_dir(str):Enregistrer le chemin du fichier
        save_name(str):Enregistrer le nom du fichier
        file_type(str):Enregistrer le format de fichier
    """

    rule_file = configparser.ConfigParser()
    rule_file.read("./conf/{0}".format(config), "UTF-8")

    fig = plt.figure(figsize=(int(rule_file["Size"]["figure_x"]), int(rule_file["Size"]["figure_y"])))

    ax = fig.add_subplot(int(rule_file["Position"]["subplot"]))
    ax.set_xlabel(data["x_label"], fontsize=int(rule_file["Size"]["font_x_label"]))
    ax.set_ylabel(data["y_label"], fontsize=int(rule_file["Size"]["font_y_label"]))

    for index in range(len(data["x_data"])):
        ax.plot(data["x_data"][index],
                data["y_data"][index],
                label=data["label"][index],
                color=rule_file["Color"][str(index)],
                marker=rule_file["Markers"][str(index)],
                markersize=int(rule_file["Size"]["marker"]))

    plt.title(data["title"], fontsize=int(rule_file["Size"]["font_title"]))

    if "x_ticks" in data.keys():
        plt.xticks(data["x_ticks"][0], data["x_ticks"][1])

    if "y_ticks" in data.keys():
        plt.yticks(data["y_ticks"][0], data["y_ticks"][1])

    plt.tick_params(labelsize=int(rule_file["Size"]["font_tick"]))
    plt.legend(fontsize=rule_file["Size"]["font_legend"], loc=rule_file["Position"]["legend_location"])
    plt.savefig("".join([data["save_dir"], "/", data["save_name"], ".", data["file_type"]]))

Le fichier Python qui transmet les données ressemble à ceci:

main.py



from make_line_graph import make_line_graph

data = {
    "title": "hogehoge",
    "label": ["A", "B"],
    "x_data": [x_data1, x_data2],
    "y_data": [y_data1, y_data2],
    "x_ticks": [x_ticks1, x_ticks2],
    "y_ticks": [y_ticks1, y_ticks2],
    "x_label": "hogehoge",
    "y_label": "hogehoge",
    "save_dir": "Chemin du dossier que vous souhaitez enregistrer",
    "save_name": "Nom du fichier que vous souhaitez enregistrer",
    "file_type": "extension",
}

make_line_graph(data, config="config.ini")

Impressions que j'ai essayé d'utiliser

bon point

Le design est plus facile à changer. En particulier, différentes tailles de police varient en fonction des données à tracer et du nombre de caractères à inclure dans l'étiquette.

De plus, en dupliquant et en personnalisant le fichier de paramètres, la quantité de fichiers Python change lorsque vous souhaitez modifier la conception du graphique a été réduite. Il vous suffit de modifier le nom du fichier de paramètres à lire.

Étant donné que la conception du graphe et le fichier de paramètres sont liés, il est prudent d'oublier quelle conception correspond à quel code.

Mauvais point

Il est difficile de le rendre polyvalent.

Le ** make_line_graph.py ** que j'ai créé est une fonction de création de graphique linéaire, mais je ne veux pas avoir plus de fichiers Python similaires, donc je l'ai rendu aussi polyvalent que possible. Cependant, cela ne dessine pas bien le graphe, et si une autre fonction de création de graphe linéaire est encombrée pour y correspondre, il semble qu'elle reviendra au dessin.

Je me demande s'il n'y a pas de fin compte tenu de sa polyvalence.

Recommended Posts

Séparation de la conception et des données dans matplotlib
Implémentez "Data Visualization Design # 3" avec pandas et matplotlib
Traitement pleine largeur et demi-largeur des données CSV en Python
Graphique des données de séries chronologiques en Python à l'aide de pandas et matplotlib
Installer SciPy et matplotlib (Python)
Hashing de données en R et Python
Méthode de planification des expériences et optimisation des combinaisons
Implémentez "Data Visualization Design # 2" avec matplotlib
Sélection de l'interface graphique PyOpenGL et séparation du dessin et de l'interface graphique
Résumé des commandes fréquemment utilisées dans matplotlib
Représentez facilement des données graphiques dans le shell et Python
Captures d'écran de la pêche sur le Web avec du sélénium et Chrome.
Conversion des données de temps en notation 25 heures
Résumé des modules et des classes dans Python-TensorFlow2-
Projet Euler # 1 "Multiple de 3 et 5" en Python
Visualisation des données de coordonnées de latitude / longitude (en supposant des données météorologiques) à l'aide de cartopy et matplotlib
Rechercher le nom et les données d'une variable libre dans un objet fonction
Tracer CSV de données de séries temporelles avec une valeur unixtime en Python (matplotlib)
Résumé des distributions de probabilité qui apparaissent souvent dans les statistiques et l'analyse des données
Python: prétraitement en machine learning: gestion des données manquantes / aberrantes / déséquilibrées
Visualisez les données d'infection corona à Tokyo avec matplotlib
Résumé des outils et bibliothèques OSS créés en 2016
Variables Python et types de données appris avec la chimio-automatique
[Python] Permutation des lignes et des colonnes de données Numpy
Visualisation en temps réel des données thermographiques AMG8833 en Python
Lissage des séries temporelles et des données de forme d'onde 3 méthodes (lissage)
L'en-tête est mal aligné avec read_csv () et read_table () de Pandas
Lorsque l'axe et l'étiquette se chevauchent dans matplotlib
Charges de travail de science des données et RTVS dans Visual Studio 2017
L'histoire de la lecture des données HSPICE en Python
Coexistence d'Anaconda 2 et Anaconda 3 dans Jupyter + Bonus (Julia)
Nettoyage des données 3 Utilisation d'OpenCV et prétraitement des données d'image
Environnement enregistré pour l'analyse des données avec Python
Explication de la distance d'édition et de l'implémentation en Python
J'ai créé un graphique à barres empilées avec matplotlib de Python et ajouté une étiquette de données
"Régression linéaire" et "Version probabiliste de la régression linéaire" en Python "Régression linéaire de Bayes"
Analyse des données financières par pandas et leur visualisation (2)
À propos de l'erreur d'importation de numpy et scipy dans anaconda
Liste des bibliothèques Python pour les data scientists et les data ingénieurs
Analyse des données financières par pandas et leur visualisation (1)
Séparation du nom et du prénom japonais avec BERT
Omettre les graduations du graphique après la virgule décimale dans matplotlib
Différence entre Ruby et Python en termes de variables
Vue d'ensemble et astuces de Seaborn avec visualisation de données statistiques
[python] Calcul des mois et des années de différence de date / heure
Vérification des performances du prétraitement des données dans le traitement du langage naturel
Ne pas être conscient du contenu des données en python
Liste du code Python utilisé dans l'analyse de Big Data
Environ 200 données de latitude et de longitude pour les hôpitaux de Tokyo
Utilisons les données ouvertes de "Mamebus" en Python
Analyse des données de mesure (2) -Hydrobacter et raccord, recommandation lmfit-
Comment visualiser les données par variable explicative et variable objective
Exemple d'obtention du nom du module et du nom de la classe en Python
Vue d'ensemble du traitement du langage naturel et de son prétraitement des données
Récapitulatif du traitement de la date en Python (datetime et dateutil)
Mettez matplotlib dans Centos7.