test_quantitatif.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import pandas as pd
  2. import numpy as np
  3. from scipy.stats import chi2_contingency, fisher_exact
  4. from scipy.stats import normaltest, kstest, levene, ttest_ind, mannwhitneyu, f_oneway, kruskal
  5. import statsmodels.stats.weightstats as ws
  6. class testQuantitatif ():
  7. """
  8. Applique le test qualitatif le plus adapté à partir d'un jeu de données
  9. df : dataframe contenant les données
  10. y : variable à tester
  11. x : variable dont on souhaite mesurer l'impact
  12. """
  13. def __init__ (self, df, y, x):
  14. # Calcul du tableau de contingence
  15. self.df = df
  16. self.x = x
  17. self.y = y
  18. # On détermines les modalités de x
  19. self.x_shapes = self.df[x].drop_duplicates()
  20. # On détermine les valeurs de y pour chaque x
  21. self.y_values = {}
  22. for x_value in self.x_shapes:
  23. self.y_values[x_value] = df[
  24. df[x] == x_value
  25. ][y] \
  26. .values
  27. # On détermine les éléments de validités
  28. self.x_shape = self.x_shapes.shape[0]
  29. self.n_sup_30 = ((df.groupby(x).count()[y] >= 30).sum() == 2)
  30. def _check_all_group_normal(self):
  31. # Application du test de normalité
  32. normal_test_result = self.normal_distribution();
  33. # On vérifie que tous les groupes sont distribués normalement
  34. valid = len([False for x in normal_test_result.values() if x["p_value"] < 0.05]) == 0
  35. return valid
  36. def best_test (self, normal = None):
  37. """
  38. Selectionne le meilleur test possible
  39. Variable :
  40. normal : boolean, si True, on suppose une distribution normale sans faire de test de normalité
  41. """
  42. # Arbre decisionnel
  43. ## x_shape :
  44. ### 2 :
  45. #### N1, N2 >= 30 : Z-test
  46. #### N1, N2 <= 30 :
  47. ##### Distribution de chaque groupe normale ?
  48. ###### Egalite variance : t-test
  49. ###### Absence égalité variance : test de welch
  50. ##### Absence de distribution normale : MWWilcoxon
  51. ### > 2 :
  52. #### Egalite variance et distribution normal : ANOVA
  53. #### Autrement un test de Kruskal Wallis
  54. if self.x_shape == 2:
  55. if self.n_sup_30:
  56. # Application du Z-test
  57. result = self.z_test()
  58. test_applied = "z_test"
  59. else:
  60. # Vérification de la normalité
  61. if normal or self._check_all_group_normal():
  62. # Vérification de l'égalité des variance
  63. if self.variance_equity["p_value"] >= 0.05:
  64. # On suppose l'égalité de variance : t-test
  65. welch = False
  66. test_applied = "t_test"
  67. else:
  68. # On ne suppose pas l'égalité de variance : test de welch
  69. welch = True
  70. test_applied = "t_test Welch"
  71. result = self.t_test(welch)
  72. else:
  73. test_applied = "Mann-Whitney Wilcoxon"
  74. result = self.mwwilcoxon()
  75. else:
  76. # Vérification de la normalité et de l'égalité de variance
  77. if (normal or self._check_all_group_normal()) and (self.variance_equity["p_value"] >= 0.05):
  78. # Anova
  79. test_applied = "ANOVA_1W"
  80. result = self.anova_1w()
  81. else:
  82. test_applied = "Kurskal_Wallis"
  83. result = self.kruskal_wallis()
  84. return (test_applied, result)
  85. def _apply_test (self, test_function, params = {}):
  86. # Application du test
  87. test_result = test_function(*list(self.y_values.values()),
  88. **params)
  89. output_result = dict(zip(
  90. ["statistic","p_value"],
  91. [test_result.statistic, test_result.pvalue]
  92. ))
  93. return(output_result)
  94. def normal_distribution (self):
  95. # On applique le test de normalité à chaque catégorie
  96. norm_test_result = dict(zip(
  97. self.y_values.keys(),
  98. [ dict(zip(
  99. ["statistic", "p_value"],
  100. [x.statistic, x.pvalue]
  101. ))
  102. for x in
  103. [kstest(y_values, "norm") for y_values in self.y_values.values()]
  104. ]
  105. ))
  106. return (norm_test_result)
  107. def z_test (self):
  108. # Application du test
  109. test_result = ws.ztest(*list(self.y_values.values()))
  110. output_result = dict(zip(
  111. ["statistic","p_value"],
  112. list(test_result)
  113. ))
  114. return(output_result)
  115. def t_test (self, welch = False):
  116. # Application du test
  117. output_result = self._apply_test(ttest_ind, {"equal_var":welch})
  118. return(output_result)
  119. def mwwilcoxon (self):
  120. # Application du test
  121. output_result = self._apply_test(mannwhitneyu)
  122. return(output_result)
  123. def variance_equity (self):
  124. """
  125. Test de Levene mesuré sur la moyenne
  126. """
  127. # Application du test
  128. output_result = self._apply_test(levene,{"center":"mean"})
  129. return(output_result)
  130. def anova_1w (self):
  131. """
  132. ANOVA - One way : compare la variance de tous les groupes
  133. """
  134. # On applique le test
  135. output_result = self._apply_test(f_oneway)
  136. return(output_result)
  137. def kruskal_wallis (self):
  138. # On applique le test
  139. output_result = self._apply_test(kruskal)
  140. return(output_result)
  141. def _no_test (self):
  142. """
  143. Retourne l'absence de test
  144. """
  145. output_result = {"valid":True}
  146. return output_result