How to Test Data Normality in Python Using Pingouin

How to Test Data Normality in Python Using Pingouin

Checking whether your data follows a normal distribution is often the first step in statistical analysis. This initial assessment helps determine which statistical tests would be most appropriate for your data. For example, before running t-tests or ANOVA, understanding your data’s distribution can guide you toward either parametric or non-parametric approaches. Python’s Pingouin library makes this assessment straightforward by offering two complementary methods: numerical tests for objective measurement and visual plots for intuitive interpretation. In this article, we’ll explore both approaches using clear examples that demonstrate different types of distributions you might encounter in real data.

Creating Our Sample Data

To demonstrate how to assess normality, we’ll create three different datasets that represent common scenarios. First, we’ll generate a normally distributed dataset that could represent natural phenomena like height or test scores. Second, we’ll create a right-skewed distribution, common in data like reaction times or income levels. Finally, we’ll simulate a normal distribution with outliers, which often occurs when there are measurement errors or genuine extreme values in your data. By examining these three distinct cases, we’ll learn to identify different patterns and understand how they affect our normality assessment.

import numpy as np
import pingouin as pg

# Set random seed for reproducibility
np.random.seed(123)

# Generate sample data
normal_data = np.random.normal(loc=100, scale=15, size=50)  # Normal distribution
skewed_data = np.random.exponential(scale=20, size=50)      # Right-skewed
outlier_data = np.concatenate([                             # Normal with outliers
    np.random.normal(loc=100, scale=15, size=48),
    [200, 210]  # Two outliers
])

Visualizing the Distributions

Before testing for normality, it’s helpful to visualize our data distributions:

import matplotlib.pyplot as plt
import seaborn as sns

# Set style for better visualizations
sns.set_style("whitegrid")
plt.rcParams['figure.figsize'] = [15, 4]

# Create figure with three subplots
fig, (ax1, ax2, ax3) = plt.subplots(1, 3)

# Plot distributions using seaborn
sns.histplot(normal_data, kde=True, ax=ax1)
ax1.set_title('Normal Data', fontsize=20)

sns.histplot(skewed_data, kde=True, ax=ax2)
ax2.set_title('Skewed Data', fontsize=20)

sns.histplot(outlier_data, kde=True, ax=ax3)
ax3.set_title('Data with Outliers', fontsize=20)

plt.tight_layout()

These histograms with kernel density estimation curves show us that:

  • The normal data is approximately bell shaped
  • The skewed data is stretched toward higher values
  • The outlier data shows a bell shape with two extreme values

Testing Normality with Statistics

Now let’s use Pingouin’s normality() function, which performs the Shapiro-Wilk test:

# Test each dataset
print("Normal data:")
print(pg.normality(normal_data))

print("\nSkewed data:")
print(pg.normality(skewed_data))

print("\nData with outliers:")
print(pg.normality(outlier_data))

The results show:

  • Normal data: p-value = 0.774 (> 0.05) → Data is normal
  • Skewed data: p-value = 5.09e-08 (< 0.05) → Data is not normal
  • Outlier data: p-value = 4.63e-07 (< 0.05) → Data is not normal
Normal data:
          W     pval  normal
0  0.985059  0.77415    True

Skewed data:
          W          pval  normal
0  0.741924  5.086012e-08   False

Data with outliers:
          W          pval  normal
0  0.787766  4.634327e-07   False

The Shapiro-Wilk test uses the null hypothesis that the data is normally distributed. When interpreting results, a p-value greater than 0.05 suggests we fail to reject this hypothesis (indicating normality), while a p-value less than 0.05 suggests the data significantly deviates from a normal distribution. However, like all statistical tests, these results should be interpreted alongside visual methods for a more complete assessment.

Visual Assessment with Q-Q Plots

For a more detailed view, let’s create Q-Q (Quantile-Quantile) plots:

# Create Q-Q plots for each dataset
import matplotlib.pyplot as plt

# Set up the figure with three subplots
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 4))

# Generate Q-Q plots
pg.qqplot(normal_data, ax=ax1)
ax1.set_title('Normal Data', fontsize=20)

pg.qqplot(skewed_data, ax=ax2)
ax2.set_title('Skewed Data', fontsize=20)

pg.qqplot(outlier_data, ax=ax3)
ax3.set_title('Data with Outliers', fontsize=20)
plt.tight_layout()

The Q-Q plots reveal:

  • Normal data: Points follow the diagonal line closely (R² = 0.989)
  • Skewed data: Points curve away from the line (R² = 0.724)
  • Outlier data: Points deviate at the ends (R² = 0.774)

The R² values provide a quantitative measure of how well our data points follow the theoretical normal distribution line, with values closer to 1 indicating better alignment. While our normal data shows excellent alignment (R² = 0.989), both the skewed data and data with outliers show notable deviations (R² = 0.724 and 0.774 respectively). These visual patterns, combined with our earlier Shapiro-Wilk test results, give us strong confidence in identifying which dataset follows a normal distribution and which ones don’t.

Practical Guidelines and Conclusion

When assessing normality in your data, it’s recommended to follow a systematic approach. Start with visual inspection using histograms and Q-Q plots, as these can quickly reveal patterns and potential issues in your data. Then, confirm your visual assessment with statistical tests like Shapiro-Wilk, which provide objective measures of normality. Remember that sample size plays a crucial role – with larger samples (n > 30), minor deviations from normality are often acceptable due to the Central Limit Theorem, while smaller samples require more careful consideration.

The choice of whether to proceed with parametric tests (like t-tests or ANOVA) isn’t always straightforward. Some statistical tests are robust to violations of normality, particularly with larger sample sizes. If your data significantly deviates from normality, consider non-parametric alternatives such as the Mann-Whitney U test instead of an independent t-test, or the Kruskal-Wallis test instead of one-way ANOVA.

Through this tutorial, we’ve seen how Pingouin simplifies the process of normality testing by providing both visual and statistical tools in an accessible way. By combining histogram visualization, Q-Q plots, and the Shapiro-Wilk test, you can make well-informed decisions about your data’s distribution and choose the most appropriate statistical methods for your analysis. Remember that assessing normality is not about finding perfect normal distributions in your data, but rather about understanding your data’s characteristics and making informed analytical choices.

Leave a Reply

Your email address will not be published. Required fields are marked *