Forum Programmation.python CGI en python, problème avec pandas, plotly et export html

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
0
18
jan.
2020

Hello,

J'ai developpé il y a quelques temps une CGI en ksh/html qui permettait de créer des graph via Gnuplot à partir de data récoltées sur des serveurs Linux et AIX. Les datas sont de ce type :

2020-01-13-00-00,384.00,350.00
2020-01-13-06-00,384.00,350.00
2020-01-13-12-00,384.00,350.00
2020-01-13-18-00,384.00,350.00
2020-01-14-00-00,384.00,350.00
2020-01-14-06-00,384.00,350.00
2020-01-14-12-00,384.00,350.00

Aujourd'hui j'aimerai pouvoir faire évoluer cette CGI en la passant sous python et en utilisant les libraires pandas, ipywidget et plotly.express.

J'ai fait un premier script qui ressemble à cela :

    import pandas as pd
    import plotly.express as px


    df = pd.read_csv('Bureau/Test.txt')
    df.head()

    fig = px.line(df, x = 'Date', y ='Total Used', title='DF command graph')
    fig.add_scatter(x=df['Date'], y=df['Free'])

    fig.update_traces(mode='markers+lines')
    fig.write_html("/xxx/xxx/xxx/file.html")
    fig.show()

Ce script me permettait d'exporter au format html mon graph tout en gardant le côté " interactif ".

Mon objectif maintenant est de faire la même chose mais en ajoutant un bouton qui afficherait le graph et un autre bouton qui afficherait le graph avec la courbe de tendance. De ce fait, j'ai ce script :

import ipywidgets as widgets
import pandas as pd
import plotly.express as px
import os

####### Button 1 ########

button = widgets.Button(description="graph")
display(button)

def graph():
    df = pd.read_csv('/xxx/xxx/xxx/Test.txt')
    df.head()
    fig = px.line(df, x = 'Date', y ='Total Used', title='DF command graph')
    fig.update_traces(mode='markers')
    fig.show();

output = widgets.Output()

@output.capture()
def on_button_clicked(b):
    graph();

button.on_click(on_button_clicked)
display(output)


####### Button 2 #########

button2 = widgets.Button(description='trend')
display(button2)

def trend():
    df = pd.read_csv('/xxx/xxx/xxx/Test.txt')
    df.head()
    fig = px.scatter((df), x="Date", y="Total Used", trendline="ols")
    fig.show()

output2 = widgets.Output()

@output2.capture()
def on_button2_clicked(b):
    trend()

button2.on_click(on_button2_clicked)
display(output2)

graph()

Le bouton pour afficher le graph fonctionne super bien. Mais lorsque j'essaie d'utiliser le bouton trend, voici l'erreur qui s'affiche :

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~/.local/lib/python3.7/site-packages/ipywidgets/widgets/widget_output.py in inner(*args, **kwargs)
    101                     self.clear_output(*clear_args, **clear_kwargs)
    102                 with self:
--> 103                     return func(*args, **kwargs)
    104             return inner
    105         return capture_decorator

<ipython-input-14-bc7c0aeca03e> in on_button2_clicked(b)
     40 @output2.capture()
     41 def on_button2_clicked(b):
---> 42     trend()
     43 
     44 button2.on_click(on_button2_clicked)

<ipython-input-14-bc7c0aeca03e> in trend()
     33     df = pd.read_csv('/home/tim/Bureau/Test1.txt')
     34     df.head()
---> 35     fig = px.scatter(df, x="Date", y="Total Used", trendline="ols")
     36     fig.show()
     37 

~/.local/lib/python3.7/site-packages/plotly/express/_chart_types.py in scatter(data_frame, x, y, color, symbol, size, hover_name, hover_data, custom_data, text, facet_row, facet_col, facet_col_wrap, error_x, error_x_minus, error_y, error_y_minus, animation_frame, animation_group, category_orders, labels, color_discrete_sequence, color_discrete_map, color_continuous_scale, range_color, color_continuous_midpoint, symbol_sequence, symbol_map, opacity, size_max, marginal_x, marginal_y, trendline, trendline_color_override, log_x, log_y, range_x, range_y, render_mode, title, template, width, height)
     53     mark in 2D space.
     54     """
---> 55     return make_figure(args=locals(), constructor=go.Scatter)
     56 
     57 

~/.local/lib/python3.7/site-packages/plotly/express/_core.py in make_figure(args, constructor, trace_patch, layout_patch)
   1315 
   1316             patch, fit_results = make_trace_kwargs(
-> 1317                 args, trace_spec, group, mapping_labels.copy(), sizeref
   1318             )
   1319             trace.update(patch)

~/.local/lib/python3.7/site-packages/plotly/express/_core.py in make_trace_kwargs(args, trace_spec, g, mapping_labels, sizeref)
    234                         hover_header = "<b>LOWESS trendline</b><br><br>"
    235                     elif v == "ols":
--> 236                         fit_results = sm.OLS(y.values, sm.add_constant(x.values)).fit()
    237                         result["y"] = fit_results.predict()
    238                         hover_header = "<b>OLS trendline</b><br>"

~/.local/lib/python3.7/site-packages/statsmodels/tools/tools.py in add_constant(data, prepend, has_constant)
    303         raise ValueError('Only implementd 2-dimensional arrays')
    304 
--> 305     is_nonzero_const = np.ptp(x, axis=0) == 0
    306     is_nonzero_const &= np.all(x != 0.0, axis=0)
    307     if is_nonzero_const.any():

<__array_function__ internals> in ptp(*args, **kwargs)

~/.local/lib/python3.7/site-packages/numpy/core/fromnumeric.py in ptp(a, axis, out, keepdims)
   2541         else:
   2542             return ptp(axis=axis, out=out, **kwargs)
-> 2543     return _methods._ptp(a, axis=axis, out=out, **kwargs)
   2544 
   2545 

~/.local/lib/python3.7/site-packages/numpy/core/_methods.py in _ptp(a, axis, out, keepdims)
    230         umr_maximum(a, axis, None, out, keepdims),
    231         umr_minimum(a, axis, None, None, keepdims),
--> 232         out
    233     )
    234 

TypeError: unsupported operand type(s) for -: 'str' and 'str'

Je ne comprends pas la signification de cette erreur… Serait-ce parce que dans mes datas, le script ne comprendrait pas 2020-01-13-00-00, prenant le signe - comme un signe de soustraction ? Pourriez-vous me montrer comment corriger ça ?

Ensuite, deuxième problème, dans mon premier script j'ai réussi à créer un .html grâces a la ligne :

fig.write_html("/xxx/xxx/xxx/file.html")

Avec mon nouveau script, n'y a t-il pas un moyen de faire la même chose ? Sans passer par jupyer notebook ou quoi ?

  • # Mauvais type

    Posté par  . Évalué à 0.

    Ton code essaie de faire une soustraction entre deux string. Force le passage en int

    • [^] # Re: Mauvais type

      Posté par  . Évalué à 1.

      Si je comprends bien,
      OK :
      fig.add_scatter(x=df['Date'], y=df['Free'])
      Pas OK :
      fig = px.scatter((df), x="Date", y="Total Used", trendline="ols")

      L'erreur est peu parlante car elle est levée à assez bas niveau, lors de l'évaluation de la trendline.

      Est-ce que df['Date'] est bien reconnu comme de type Date (cf https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html par ex) et non comme simple String ? C'est un prérequis pour faire de l'arithmétique sur ces données…
      Pandas est en général assez intelligent sur la détection & interprétation des données, mais il faut un peu l'aider : l'argument dtype de read_csv devrait t'être utile.
      https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html?highlight=read_csv#pandas-read-csv

      Par ailleurs, je devine que tu as pondu deux instructions différentes pour la même fonctionnalité parce que tu n'as pas encore d'objet fig dans le second cas. De manière générale, dans une GUI avec affichage de graphes, tu peux préférer créer d'abord les structures type figure, axes, labels, légende, etc… pour ensuite les modifier/réutiliser en fonction des nouvelles données.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.