genererTableau.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. from io import StringIO, BytesIO
  2. import pyexcel as pe
  3. import csv
  4. import math
  5. class genererTableau ():
  6. """
  7. ecrire_tableau :
  8. Permet de créer un tableau et l'exporter au format excel, ods ou csv à partir de données d'analyses.
  9. Input :
  10. data : données aggrégées généré par les méthodes de analyseStatistiques
  11. precision : nombre de décimales de précision
  12. quantitative_string_format : format d'écriture de la moyenne, écart type et taille d'échantillon des variables quantitatives
  13. qualitative_string_format : format d'écriture du n et de la proportion des variables qualitatives
  14. """
  15. def __init__ (self, data, precision = 2, quantitative_column_title = "{variable} mean +/- std (n)", quantitative_string_format = "{mean:.2f} +/- {std:.2f} ({n})", qualitative_column_title="{variable} no. (%)", qualitative_string_format = "{n} ({p:.2%})"):
  16. """
  17. Data : data contenant les données aggrégées, généré par analyseStatistiques.analyse_univarie
  18. """
  19. # Parametres
  20. self.quantitative_column_title = quantitative_column_title
  21. self.quantitative_string_format = quantitative_string_format
  22. self.qualitative_column_title = qualitative_column_title
  23. self.qualitative_string_format = qualitative_string_format
  24. self.absence_test = "Absence de test effectué (CI des tests conventionnels non remplis)"
  25. self.precision = precision
  26. self.data = data
  27. self.liste_variables = list(data.keys()) # Liste des variables analysables
  28. if "sous_groupes" in list(data.values())[0]:
  29. self.liste_axes = list(list(data.values())[0]["sous_groupes"].keys()) # Liste des axes d'analyses
  30. else:
  31. self.liste_axes = []
  32. # On récupère la liste des modalités de chaque axes
  33. self.liste_modalites = dict(zip(
  34. self.liste_axes,
  35. [self._obtenir_modalite_axe(x, True) for x in self.liste_axes]
  36. ))
  37. # On récupère la liste des modalités de chaque variable
  38. self.liste_modalites_variables = dict(zip(
  39. self.liste_variables,
  40. [self._obtenir_modalite_variable(x, True) for x in self.liste_variables]
  41. ))
  42. def _generer_texte_propre (self, texte):
  43. """
  44. Nettoie un texte
  45. Si il s'agit d'un flottant : le met en int
  46. """
  47. if type(texte) != type(str()):
  48. texte = str(int(texte))
  49. return(texte)
  50. def _generer_str_mean_std_n(self, mean, std, n):
  51. """
  52. Simple fonction qui écrit un string mélangeant moyenne, écart-type et taille de l'effectif
  53. Format par défault :
  54. {mean:.2f} +/- {std:.2f} ({n})
  55. Peut-être personalisé par le paramètre string_format.
  56. Input :
  57. mean, std et n
  58. """
  59. texte = self.quantitative_string_format.format(
  60. mean=round(mean, self.precision),
  61. std=round(std, self.precision),
  62. n=round(n, self.precision)
  63. )
  64. return(texte)
  65. def _generer_str_n_p(self, n, p):
  66. """
  67. Simple fonction qui écrit un string mélangeant moyenne, écart-type et taille de l'effectif
  68. Format par défault :
  69. {n} ({p:.0%})
  70. Peut-être personalisé par le paramètre string_format.
  71. Input :
  72. mean, std et n
  73. Sortie :
  74. texte
  75. """
  76. texte = self.qualitative_string_format.format(
  77. p = round(p, self.precision),
  78. n = round(n, self.precision)
  79. )
  80. return(texte)
  81. def _generer_str_valeur(self, valeur):
  82. """
  83. Simple fonction qui écrit un string à partir d'une valeur
  84. Input :
  85. valeur
  86. Sortie :
  87. texte
  88. """
  89. texte = "{}".format(
  90. round(valeur, self.precision)
  91. )
  92. return(texte)
  93. def _generer_str_ci(self, liste_ci):
  94. """
  95. Simple fonction qui écrit un string à partir d'une liste représentant un intervale de confiance
  96. Input :
  97. liste_ci : liste de 2 items décrivant un intervalle de confiance
  98. Sortie :
  99. texte
  100. """
  101. texte = "{}-{}".format(
  102. self._generer_str_valeur(liste_ci[0]),
  103. self._generer_str_valeur(liste_ci[1])
  104. )
  105. return(texte)
  106. def _generer_str_resultat_test(self, test):
  107. """
  108. Génère une liste avec formatage textuel du résultat d'un test
  109. Vérifie la bonne application du test avant.
  110. Input :
  111. test : liste contenant le résultat du test
  112. Sortie :
  113. liste de 3 éléments comprenant : Test, Paramètre et p
  114. """
  115. resultat = []
  116. if len(test[1].keys()) > 1:
  117. resultat.append(test[0]) # Nom du test
  118. resultat.append(self._generer_str_valeur(test[1]["statistic"])) # Paramètre de test
  119. resultat.append(self._formater_p_value(test[1]["p_value"])) # Petit p du test
  120. else:
  121. resultat.append(self.absence_test)
  122. resultat = resultat + ["", ""]
  123. return(resultat)
  124. def _formater_p_value(self, p_value):
  125. # Nombre de décimales concernées
  126. n_digit = len(str(p_value).split(".")[-1].split("0"))
  127. borne_basse = 5*math.pow(10, -n_digit)
  128. borne_sup = math.pow(10, -n_digit+1)
  129. estimation_p = borne_basse if p_value <= borne_basse else borne_sup
  130. # Affichage
  131. if p_value > 0.01:
  132. formated_p_value = str(round(p_value, 3))
  133. else:
  134. if p_value > 0.001:
  135. formated_p_value = "< "+str(estimation_p)
  136. else:
  137. formated_p_value = "< 10^"+str(n_digit-1)
  138. return(formated_p_value)
  139. def _verifier_existence_variables(self, variables):
  140. """
  141. Vérifie que les variables existent bien dans le jeu de données.
  142. Input : variables : liste des variables à tester
  143. Output : None
  144. """
  145. variables_manquantes = [x for x in variables if x not in self.liste_variables]
  146. if len(variables_manquantes) > 0:
  147. raise Exception("Erreur, les variables {} sont inexistantes des données aggrégées.".format(
  148. ", ".join(variables_manquantes)
  149. ))
  150. def _verifier_existence_axes(self, axes):
  151. """
  152. Vérifie que les axes existent bien dans le jeu de données.
  153. Input : variables : liste des axes à tester
  154. Output : None
  155. """
  156. if axes is not None:
  157. axes_manquants = [x for x in axes if x not in self.liste_axes]
  158. else:
  159. axes_manquants = []
  160. if len(axes_manquants) > 0:
  161. raise Exception("Erreur, les axes {} sont inexistantes des données aggrégées.".format(
  162. ", ".join(axes_manquants)
  163. ))
  164. def _obtenir_modalite_axe (self, axe, ajouter_nom = True):
  165. """
  166. Retourne une liste contenant toutes les modalités pour un axe donné
  167. Input :
  168. axe : nom de l'axe à analyse
  169. ajouter_nom : Si True, alors le nom de l'axe est ajouté à la modalité (concaténation)
  170. """
  171. # Liste des modalités
  172. modalites = list(self.data.values())[0]["sous_groupes"][axe].keys()
  173. # Post-traitement : on corrige les float et boolean pour les afficher en int
  174. modalites = [int(x) if type(x) != type(str()) else x for x in modalites]
  175. # On affiche le nom de l'axe avec si nécessaire
  176. modalites_avec_str = [axe+" "+str(x) for x in modalites]
  177. if ajouter_nom:
  178. return(modalites_avec_str)
  179. else:
  180. return(modalites)
  181. def _obtenir_modalite_variable (self, variable, ajouter_nom = True):
  182. """
  183. Retourne une liste contenant toutes les modalités pour une variable donnée
  184. Input :
  185. variable : nom de la variable à analyser
  186. ajouter_nom : Si True, alors le nom de l'axe est ajouté à la modalité (concaténation)
  187. """
  188. # Liste des modalités
  189. modalites = [x for x in list(self.data[variable]["global"].keys()) if x != "total"]
  190. # Post-traitement : on corrige les float et boolean pour les afficher en int
  191. modalites = [int(x) if type(x) != type(str()) else x for x in modalites]
  192. # On affiche le nom de l'axe avec si nécessaire
  193. modalites_avec_str = [variable+" "+str(x) for x in modalites]
  194. if ajouter_nom:
  195. return(modalites_avec_str)
  196. else:
  197. return(modalites)
  198. def _generer_en_tete_descriptif(self, axes):
  199. """
  200. Genere l'en-tête d'un tableau Descriptif
  201. Input :
  202. axes : liste des axes d'analyse
  203. Output : None
  204. """
  205. # Initialisation de l'en-tête
  206. en_tete = ["","",""]
  207. # Lecture des axes
  208. for axe in axes:
  209. en_tete = en_tete+self.liste_modalites[axe]+["Test","Paramètre", "p"]
  210. return en_tete
  211. def _generer_en_tete_detail(self, variable, iqr=False, extremes=False):
  212. """
  213. Genere l'en-tête d'un tableau Descriptif
  214. Input :
  215. axes : liste des axes d'analyse
  216. iqr, boolean: Si true, intègle les intervalles interquartiles
  217. extremes, boolean: Si true, intègle les valeurs extrêmes
  218. Output : None
  219. """
  220. # Type de variable
  221. type_variable = self.data[variable]["type"]
  222. # Initialisation de l'en-tête
  223. en_tete = []
  224. en_tete.append(variable) # Nom de la variable
  225. en_tete.append("") # Espace technique
  226. ## Pour les variables quantitatives
  227. if type_variable == "quantitative":
  228. en_tete = en_tete + ["n", "mean", "std", "IC 95%"]
  229. extremes_iqr = [
  230. ("min", extremes),
  231. ("Q25", iqr),
  232. ("median", iqr),
  233. ("Q75", iqr),
  234. ("max", extremes),
  235. ]
  236. for title, rule in extremes_iqr:
  237. if rule:
  238. en_tete.append(title)
  239. elif type_variable == "qualitative":
  240. en_tete.append("n")
  241. en_tete = en_tete + self.liste_modalites_variables[variable]
  242. en_tete = en_tete + ["Test", "Parameter", "p"]
  243. return en_tete
  244. def _generer_lignes_descriptif (self, variable, axes):
  245. """
  246. Genere des ligne d'analyse d'un tableau descriptif pour une variable
  247. Input :
  248. variable : nom de la variable
  249. axes : axes sur lesquels générer la ligne
  250. """
  251. lignes = []
  252. if self.data[variable]["type"] == "quantitative":
  253. # Ligne d'une variable quantitative : une seule ligne
  254. ligne = [] # On instancie la ligne
  255. ligne.append(self.quantitative_column_title.format(variable=variable)) # Ajout du nom de variable
  256. ligne.append("") # Espace vide, technique
  257. ligne.append(self._generer_str_mean_std_n(
  258. self.data[variable]["global"]["mean"],
  259. self.data[variable]["global"]["std"],
  260. self.data[variable]["global"]["n"]
  261. )) # Données globales
  262. # Données liées à chaque axe
  263. for axe in axes:
  264. donnees_axe = self.data[variable]["sous_groupes"][axe]
  265. # Pour chaque valeur de l'axe
  266. for valeur in donnees_axe.keys():
  267. ligne.append(self._generer_str_mean_std_n(
  268. donnees_axe[valeur]["mean"],
  269. donnees_axe[valeur]["std"],
  270. donnees_axe[valeur]["n"]
  271. )) # Données hors test
  272. ligne = ligne + self._generer_str_resultat_test(self.data[variable]["test"][axe]) # Données du test
  273. lignes.append(ligne)
  274. else:
  275. # Lignes d'un variable qualitative : une ligne par modalité
  276. ## On écrit la première ligne : nom de variable et test
  277. ligne = [] # On instancie la ligne
  278. ligne.append(self.qualitative_column_title.format(variable=variable)) # Nom de variable
  279. ligne = ligne + ["", ""] # Variable vides
  280. # Données liées à chaque axe
  281. for axe in axes:
  282. blank_list = ["" for x in range(len(self.liste_modalites[axe]))]
  283. ligne = ligne + blank_list # Blanc lié aux tests
  284. ligne = ligne + self._generer_str_resultat_test(self.data[variable]["test"][axe]) # Données du test
  285. lignes.append(ligne)
  286. ## On écrit les lignes propres à chaque variable
  287. liste_labels = self.data[variable]["global"].keys()
  288. for label in liste_labels:
  289. # On ignore le label total
  290. if label != "total":
  291. ligne = []
  292. ligne.append("") # Première ligne vide
  293. ligne.append(self._generer_texte_propre(label)) # Libelé analysé
  294. ligne.append(self._generer_str_n_p(
  295. n = self.data[variable]["global"][label]["n"],
  296. p = self.data[variable]["global"][label]["p"]
  297. )) # Données générales
  298. # Valeur par axe
  299. for axe in axes:
  300. liste_valeurs = list(self.data[variable]["sous_groupes"][axe].keys())
  301. # Pour chaque valeur de l'axe
  302. for valeur in liste_valeurs: # On met 0 si la valeur n'existe pas
  303. donnees_axe = self.data[variable]["sous_groupes"][axe][valeur]
  304. n = donnees_axe[label]["n"] if label in donnees_axe.keys() else 0
  305. p = donnees_axe[label]["p"] if label in donnees_axe.keys() else 0
  306. ligne.append(self._generer_str_n_p(
  307. n = n,
  308. p = p
  309. )) # Données spécifique à chaque axe
  310. ligne = ligne + ["", "", ""] # Espaces vides entre 2 axes
  311. lignes.append(ligne)
  312. return(lignes)
  313. def _generer_lignes_detail(self, variable, axe = None, extremes=False, iqr=False):
  314. """
  315. Genere des ligne d'analyse d'un tableau détaillé pour une variable
  316. Input :
  317. variable : nom de la variable
  318. axe : axe sur lesquels générer les ligne
  319. iqr, boolean: Si true, intègle les intervalles interquartiles
  320. extremes, boolean: Si true, intègle les valeurs extrêmes
  321. """
  322. lignes = []
  323. if self.data[variable]["type"] == "quantitative":
  324. # Génération de la ligne simple
  325. if axe is None:
  326. ligne = [] # On instancie la ligne
  327. ligne = ligne + ["", ""] # Blanc technique
  328. ligne.append(self._generer_str_valeur(self.data[variable]["global"]["n"])) # Taille d'échantillon
  329. ligne.append(self._generer_str_valeur(self.data[variable]["global"]["mean"])) # Moyenne
  330. ligne.append(self._generer_str_valeur(self.data[variable]["global"]["std"])) # Ecart type
  331. ligne.append(self._generer_str_ci(self.data[variable]["global"]["ci_95"])) # IC à 95%
  332. extremes_iqr = [
  333. ("min", extremes),
  334. ("Q25", iqr),
  335. ("median", iqr),
  336. ("Q75", iqr),
  337. ("max", extremes),
  338. ]
  339. for value, rule in extremes_iqr:
  340. if rule:
  341. ligne.append(
  342. self._generer_str_valeur(
  343. self.data[variable]["global"][value]
  344. )
  345. )
  346. ligne = ligne + ["", "", ""] # Blanc technique
  347. lignes.append(ligne)
  348. else:
  349. # On vérifie l'axe
  350. self._verifier_existence_axes([axe])
  351. # Données sur l'axe
  352. donnees_axe = self.data[variable]["sous_groupes"][axe]
  353. # On écrit le nom de l'axe
  354. ligne = []
  355. ligne.append(axe) # Nom de l'axe
  356. ligne = ligne + ["","","","",""]
  357. # Résultat du test
  358. ligne = ligne + self._generer_str_resultat_test(self.data[variable]["test"][axe])
  359. lignes.append(ligne)
  360. # On parcours toutes les modalités de l'axe
  361. for valeur_axe in donnees_axe.keys():
  362. ligne = []
  363. ligne.append("") # Ligne blanche technique
  364. ligne.append(self._generer_texte_propre(valeur_axe)) # Valeur sur l'axe
  365. ligne.append(self._generer_str_valeur(donnees_axe[valeur_axe]["n"])) # Taille d'échantillon
  366. ligne.append(self._generer_str_valeur(donnees_axe[valeur_axe]["mean"])) # Moyenne
  367. ligne.append(self._generer_str_valeur(donnees_axe[valeur_axe]["std"])) # Ecart type
  368. ligne.append(self._generer_str_ci(donnees_axe[valeur_axe]["ci_95"])) # IC à 95%
  369. extremes_iqr = [
  370. ("min", extremes),
  371. ("Q25", iqr),
  372. ("median", iqr),
  373. ("Q75", iqr),
  374. ("max", extremes),
  375. ]
  376. for value, rule in extremes_iqr:
  377. if rule:
  378. ligne.append(
  379. self._generer_str_valeur(
  380. self.data[variable]["global"][value]
  381. )
  382. )
  383. ligne = ligne + ["", "", ""] # Blanc technique
  384. lignes.append(ligne)
  385. else:
  386. # Génération de la ligne simple
  387. if axe is None:
  388. ligne = [] # On instancie la ligne
  389. ligne = ligne + ["", ""] # Blanc technique
  390. ligne.append(self._generer_str_valeur(self.data[variable]["global"]["total"])) # Taille d'échantillon
  391. for variable_valeur in self.data[variable]["global"].keys():
  392. if variable_valeur != "total":
  393. ligne.append(self._generer_str_n_p(
  394. n = self.data[variable]["global"][variable_valeur]["n"],
  395. p = self.data[variable]["global"][variable_valeur]["p"]
  396. ))
  397. ligne = ligne + ["", "", ""] # Blanc technique
  398. lignes.append(ligne)
  399. else:
  400. # On vérifie l'axe
  401. self._verifier_existence_axes([axe])
  402. # Données sur l'axe
  403. donnees_axe = self.data[variable]["sous_groupes"][axe]
  404. # On écrit le nom de l'axe
  405. ligne = []
  406. ligne.append(axe) # Nom de l'axe
  407. ligne = ligne + ["",""] + ["" for x in range(len(self.liste_modalites_variables[variable]))] # Blanc technique
  408. # Résultat du test
  409. ligne = ligne + self._generer_str_resultat_test(self.data[variable]["test"][axe])
  410. lignes.append(ligne)
  411. # On parcours toutes les modalités de l'axe
  412. for valeur_axe in donnees_axe.keys():
  413. ligne = []
  414. ligne.append("") # Ligne blanche technique
  415. ligne.append(self._generer_texte_propre(valeur_axe)) # Valeur sur l'axe
  416. ligne.append(self._generer_str_valeur(donnees_axe[valeur_axe]["total"])) # Taille d'échantillon
  417. for variable_valeur in donnees_axe[valeur_axe].keys():
  418. if variable_valeur != "total":
  419. ligne.append(self._generer_str_n_p(
  420. n = donnees_axe[valeur_axe][variable_valeur]["n"],
  421. p = donnees_axe[valeur_axe][variable_valeur]["p"]
  422. ))
  423. ligne = ligne + ["", "", ""] # Blanc technique
  424. lignes.append(ligne)
  425. return lignes
  426. def _generer_sortie (self, chemin, tableau, format_fichier):
  427. """
  428. Génère le fichier de sortie
  429. input :
  430. chemin : chemin du fichier de sortie
  431. tableau : liste contenant les lignes à écrire
  432. format_fichier : format du fichier de sortie
  433. output :
  434. si chemin textuel : aucune sortie, écriture du fichier
  435. si chemin du fichier vaut None : retour du stream
  436. """
  437. # Création du fichier
  438. if format_fichier in ["csv", "tsv"]:
  439. f = StringIO()
  440. elif format_fichier in ["ods", "xlsx"]:
  441. f = BytesIO()
  442. # Ecriture du fichier en stream
  443. if format_fichier == 'csv':
  444. csv.writer(f, delimiter = ",").writerows(tableau)
  445. elif format_fichier == 'tsv':
  446. csv.writer(f, delimiter = "\t").writerows(tableau)
  447. elif format_fichier in ['ods','xlsx']:
  448. sheet = pe.Sheet(tableau)
  449. f = sheet.save_to_memory(format_fichier, f)
  450. elif format_fichier == 'raw':
  451. f = tableau
  452. else:
  453. raise Exception("Format de sortie non supporté.")
  454. if type(chemin) == type(str()):
  455. # On écrit le fichier
  456. if format_fichier in ["csv", "tsv"]:
  457. fichier_sortie = open(chemin, "w")
  458. else:
  459. fichier_sortie = open(chemin, "wb")
  460. fichier_sortie.write(f.getvalue())
  461. else:
  462. # On renvoie le buffer
  463. return (f)
  464. def tableau_descriptif (self, chemin, variables, axes = None, format_sortie = "csv"):
  465. """
  466. Décrit le contenu de plusieurs variables selon un axe ou plusieurs axes donnés.
  467. L'axe correspond forcément à une variable qualitative.
  468. Input :
  469. chemin : chemin du fichier de sortie
  470. variables : liste des variables à traiter
  471. axes : liste des axes d'analyse
  472. format_sortie :
  473. 'tsv' pour un tableau séparé par une tabulation
  474. 'csv' pour un tableau séparé par une virgule
  475. 'ods' pour un fichier ods
  476. 'xlsx' pour un fichier xlsx
  477. 'raw' pour un envoie brut des données (liste python)
  478. Output :
  479. si chemin textuel : aucune sortie, écriture du fichier
  480. si chemin du fichier vaut None : retour du stream
  481. """
  482. # Vérification que toutes les variables et axes existent
  483. self._verifier_existence_variables(variables)
  484. self._verifier_existence_axes(axes)
  485. # Récupération des donnée
  486. # Génération de l'en-tête
  487. en_tete = self._generer_en_tete_descriptif(axes)
  488. # Création du tableau
  489. tableau = []
  490. tableau.append(en_tete)
  491. # Traitement des variables une à une
  492. for variable in variables:
  493. lignes = self._generer_lignes_descriptif(variable, axes)
  494. tableau = tableau+lignes
  495. # Generation de la sortie
  496. sortie = self._generer_sortie(chemin, tableau, format_sortie)
  497. return(sortie)
  498. def tableau_detail_variable (self, chemin, variable, axes = None, iqr=False, extremes=False, format_sortie = "csv"):
  499. """
  500. Décrit le contenu d'une variable selon un axe ou plusieurs axes donnés.
  501. Les axes correspondent forcément à des variable qualitatives.
  502. Input :
  503. chemin : chemin du fichier de sortie
  504. variable : nom de la variable à traiter
  505. axes : liste des axes d'analyse
  506. iqr, boolean: Si True, inclus les intervalles interquartiles
  507. extremes, boolean: Si True, inclus les extremes (min, max)
  508. format_sortie :
  509. 'tsv' pour un tableau séparé par une tabulation
  510. 'csv' pour un tableau séparé par une virgule
  511. 'ods' pour un fichier ods
  512. 'xlsx' pour un fichier xlsx
  513. 'raw' pour un envoi brut des données pythons
  514. Output :
  515. si chemin textuel : aucune sortie, écriture du fichier
  516. si chemin du fichier vaut None : retour du stream
  517. """
  518. # Vérification que toutes les variables et axes existent
  519. self._verifier_existence_variables([variable])
  520. self._verifier_existence_axes(axes)
  521. # Récupération des donnée
  522. # Génération de l'en-tête
  523. en_tete = self._generer_en_tete_detail(variable, extremes=extremes, iqr=iqr)
  524. # Création du tableau
  525. tableau = []
  526. tableau.append(en_tete)
  527. # On génère la première ligne d'analyse
  528. tableau = tableau + self._generer_lignes_detail(variable, None, extremes=extremes, iqr=iqr)
  529. # Ligne vide
  530. tableau.append(["" for x in range(len(tableau[-1]))])
  531. # Ajout des axes
  532. if axes is not None:
  533. for axe in axes:
  534. tableau = tableau + self._generer_lignes_detail(variable, axe, extremes=extremes, iqr=iqr)
  535. # Generation de la sortie
  536. sortie = self._generer_sortie(chemin, tableau, format_sortie)
  537. return(sortie)