"A / B-test" em levantamentos geotécnicos em Python

1. Introdução

Ao realizar pesquisas de engenharia e geológicas, pode surgir uma tarefa relacionada à comparação de dados de estudos de campo e de laboratório nos mesmos solos, a fim de confirmar o transporte correto de amostras do objeto de pesquisa para o laboratório (as amostras não foram deformadas e / ou destruídas durante o transporte).





Com esta formulação do problema, você pode aplicar a técnica de teste A / B com os seguintes parâmetros:





  1. A métrica medida será o valor médio da densidade do esqueleto do solo (p d , g / cm 3 ), que caracteriza a adição das amostras. Este valor tem uma lei de distribuição normal;





  2. O critério para testar a hipótese será o teste t (teste de Student):  para duas amostras independentes , se os dados de campo (antes do transporte) e de laboratório (após o transporte) comparados foram realizados em amostras de solo diferentes; para duas amostras dependentes , se os estudos foram realizados nas mesmas amostras.





No âmbito deste tópico, iremos gerar duas amostras aleatórias, as quais iremos comparar, formular hipóteses estatísticas, testá-las e tirar conclusões.





2. Geração de amostras

2.1 Estimativa do tamanho da amostra

, ,   (ES - effect size) (power)   I (α) ( ).  statsmodels.





() – , , , . :





{ES = \ frac {{(\ bar {X} _1 - \ bar {X} _2)} _ {obs}} {{S} _ {agrupado}}} {ES = \ frac {{(\ bar {X} _1 - \ bar {X} _2)} _ {obs}} {{S} _ {agrupado}}}

 Spooled  c :





{S} _ {pooled} = {\ sqrt {\ frac {{S} _ {1} ^ 2 + {S} _ {2} ^ 2} {2}}}

(Cohen, 1988) ES = 0.2 - ; 0.5 - ; 0.8 - .





 – II ( 80%).





I II :





H0 





H1 





H0 





H0 





II (β)





H0 





I (α)





H0  (power  = 1-β)





:





  • α = 0.05 ( )





  • ES = 0.5 ( ).





  • Power = 0.8 ( ).





:





# 
import numpy as np
from statsmodels.stats.power import TTestIndPower

from matplotlib.pyplot import figure
import matplotlib.pyplot as plt

import scipy
from statsmodels.stats.weightstats import *
      
      



# 
effect = 0.5
alpha = 0.05
power = 0.8

analysis = TTestIndPower()

#  
size = analysis.solve_power(effect, power=power, alpha=alpha)

print(f' , .: {int(size)}')
      
      



, .: 63





,  63 .  65 .





.





plt.figure(figsize=(10, 7), dpi=80)

results = dict((i/10, analysis.solve_power(i/10, power=power, alpha=alpha)) 
               for i in range(2, 16, 1))

plt.plot(list(results.keys()), list(results.values()), 'bo-')

plt.grid()
plt.title('     \n   ')
plt.ylabel('  n, .')
plt.xlabel('  ES, ..')

for x,y in zip(list(results.keys()),list(results.values())):

    label = "{:.0f}".format(y)

    plt.annotate(label, 
                 (x,y), 
                 textcoords="offset points", 
                 xytext=(0,10), 
                 ha='center')

plt.show()
      
      



, ES. : 0,03 /3  0,1 /c3 (ES = 0,03 /3 / 0,1 /3 = 0,3 ..), 175 (power=0.80, α=0.05).





2.2

,  numpy.





( ) . (X̄) (S):





  • – X̄1= 1,65 /3, S1 = 0.15 /3;





  • – X̄2 = 1,60 /3, S2 = 0.15 /3.





loc_1 = 1.65
sigma_1 = 0.15

loc_2 = 1.60
sigma_2 = 0.15

sample_size = 65
#    
sample_1 = np.random.normal(loc=loc_1, scale=sigma_1, size=sample_size)
sample_2 = np.random.normal(loc=loc_2, scale=sigma_2, size=sample_size)
      
      



" " .





fig, axes = plt.subplots(ncols=2, figsize=(18, 5))

max_y = np.max(np.hstack([sample_1,sample_2]))
#   1
count_1, bins_1, ignored_1 = axes[0].hist(sample_1, 10, density=True, 
                                          label=" 1", edgecolor='black',
                                          linewidth=1.2)
axes[0].plot(bins_1, 1/(sigma_1 * np.sqrt(2 * np.pi)) *
               np.exp( - (bins_1 - loc_1)2 / (2 * sigma_12)),
         linewidth=2, color='r', label=' ')
axes[0].legend()
axes[0].set_xlabel(u' , ')
axes[0].set_ylabel(u' , .')
axes[0].set_ylim([0, 5])
axes[0].set_xlim([1.1, 2.2])

#   2
count_2, bins_2, ignored_2 = axes[1].hist(sample_2, 10, density=True, 
                                          label=" 2", edgecolor='black', 
                                          linewidth=1.2, color="green")
axes[1].plot(bins_2, 1/(sigma_2 * np.sqrt(2 * np.pi)) *
               np.exp( - (bins_2 - loc_2)2 / (2 * sigma_22)),
         linewidth=2, color='r', label=' ')
axes[1].legend()
axes[1].set_xlabel(u' , ')
axes[1].set_ylabel(u' , .')
axes[1].set_ylim([0, 5])
axes[1].set_xlim([1.1, 2.2])
plt.show()
      
      



#  
fig, ax = plt.subplots(figsize=(8, 8))
axis = ax.boxplot([sample_1, sample_2], labels=[' 1', ' 2'])

data = np.array([sample_1, sample_2])
means = np.mean(data, axis = 1)
stds = np.std(data, axis = 1)

for i, line in enumerate(axis['medians']):
    x, y = line.get_xydata()[1]
    text = ' μ={:.2f}\n σ={:.2f}'.format(means[i], stds[i])
    ax.annotate(text, xy=(x, y))

plt.ylabel('  , /3')
plt.show()
      
      



3.

. :





  • 1. , t- ;





  • 2. , t- .





.





1.

.





 H0:   μ1 = μ2.





 H1:   μ1≠μ2.





:





T ({{X_1} ^ {n_1}}, {{X_2} ^ {n_2}}) = \ frac {\ bar {X_1} - \ bar {X_2}} {\ sqrt {\ frac {S_1 ^ 2} { n_1} + \ frac {S_2 ^ 2} {n_2}}}

: T(X1n1,X2n2)≈~St(ν),  ν 





{\ nu = \ frac {({\ frac {S_1 ^ 2} {n_1} + \ frac {S_2 ^ 2} {n_2}}) ^ 2} {\ frac {S_1 ^ 4} {n_1 ^ 2 (n_1- 1)} + \ frac {S_2 ^ 4} {n_2 ^ 2 (n_2-1)}}}

 ttest_ind  stats.





t_st, p_val = scipy.stats.ttest_ind(sample_1, sample_2, equal_var = False)
print(f't-  {round(t_st, 2)}')
print(f' t-   \
  (p-value)  {round(p_val, 3)}')
      
      



t- 2.92





t- (p-value) 0.004





№ 1





 H0  , ,   0,05 (  p-value  0.004) .





.





c_m = CompareMeans(DescrStatsW(sample_1), DescrStatsW(sample_2))
print("95%%  : \
[%.4f, %.4f]" % c_m.tconfint_diff(usevar='unequal'))
      
      



95% : [0.0235, 0.1228]





95% , , 5%.





2.

, ( ) ( ) . , .





 H0:  μ1 = μ2.





 H1:   μ1≠μ2.





:





T ({{X_1} ^ {n}}, {{X_2} ^ {n}}) = \ frac {\ bar {X_1} - \ bar {X_2}} {\ frac {S} {\ sqrt {n} }} S ^ 2 = \ frac {1} {n-1} \ sum_ {i = 1} ^ n (D_i - \ bar {D}) ^ 2, D_i = X_ {1i} - X_ {2i}

: T(X1n, X2n) ~ St(n-1)





 ttest_rel  stats.





t_st, p_val = stats.ttest_rel(sample_1, sample_2)
print(f't-  {round(t_st, 2)}')
print(f' t-   \
  (p-value)  {round(p_val, 3)}')
      
      



t- 2.79





t- (p-value) 0.007





№ 2





 H0  , ,   0,05 (  p-value  0.007).





Para maior clareza, vamos também estimar o intervalo entre as médias dessas amostras.





print("95%% confidence interval: [%.4f, %.4f]"
      % DescrStatsW(sample_1 - sample_2).tconfint_mean())
      
      



Intervalo de confiança de 95%: [0,0208, 0,1255]





Como o zero não se enquadra no intervalo de confiança considerado de 95%, podemos concluir que os valores médios das amostras consideradas diferem.





5. Resultado

Neste artigo, examinamos a possibilidade de usar a linguagem Python na solução de um problema prático em geologia de engenharia, com um estudo complementar da questão do tamanho de amostra necessário para testar hipóteses.








All Articles