{
"cells": [
{
"cell_type": "markdown",
"id": "455a3208",
"metadata": {},
"source": [
"# Detecting and filtering outliers\n",
"\n",
"Filtering or transforming outliers is largely a matter of applying array operations. Consider a DataFrame with some normally distributed data:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "35bb569f",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-22T13:31:04.568333Z",
"iopub.status.busy": "2026-05-22T13:31:04.568087Z",
"iopub.status.idle": "2026-05-22T13:31:04.799772Z",
"shell.execute_reply": "2026-05-22T13:31:04.799402Z",
"shell.execute_reply.started": "2026-05-22T13:31:04.568315Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
" 2 | \n",
" 3 | \n",
"
\n",
" \n",
" \n",
" \n",
" | count | \n",
" 1000.000000 | \n",
" 1000.000000 | \n",
" 1000.000000 | \n",
" 1000.000000 | \n",
"
\n",
" \n",
" | mean | \n",
" 0.023623 | \n",
" 0.029803 | \n",
" -0.028434 | \n",
" 0.005751 | \n",
"
\n",
" \n",
" | std | \n",
" 1.012689 | \n",
" 0.999117 | \n",
" 0.980014 | \n",
" 0.969842 | \n",
"
\n",
" \n",
" | min | \n",
" -3.240759 | \n",
" -2.757613 | \n",
" -3.372727 | \n",
" -2.697726 | \n",
"
\n",
" \n",
" | 25% | \n",
" -0.633097 | \n",
" -0.650075 | \n",
" -0.685945 | \n",
" -0.684345 | \n",
"
\n",
" \n",
" | 50% | \n",
" 0.001117 | \n",
" 0.022371 | \n",
" -0.009798 | \n",
" 0.002211 | \n",
"
\n",
" \n",
" | 75% | \n",
" 0.705048 | \n",
" 0.710901 | \n",
" 0.657235 | \n",
" 0.654270 | \n",
"
\n",
" \n",
" | max | \n",
" 3.262954 | \n",
" 3.302385 | \n",
" 2.956046 | \n",
" 2.634073 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1 2 3\n",
"count 1000.000000 1000.000000 1000.000000 1000.000000\n",
"mean 0.023623 0.029803 -0.028434 0.005751\n",
"std 1.012689 0.999117 0.980014 0.969842\n",
"min -3.240759 -2.757613 -3.372727 -2.697726\n",
"25% -0.633097 -0.650075 -0.685945 -0.684345\n",
"50% 0.001117 0.022371 -0.009798 0.002211\n",
"75% 0.705048 0.710901 0.657235 0.654270\n",
"max 3.262954 3.302385 2.956046 2.634073"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"\n",
"rng = np.random.default_rng()\n",
"df = pd.DataFrame(rng.normal(size=(1000, 4)))\n",
"\n",
"df.describe()"
]
},
{
"cell_type": "markdown",
"id": "9c159cc3",
"metadata": {},
"source": [
"Suppose you want to find values in one of the columns whose absolute value is greater than 3:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "89dfec83",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-22T13:31:04.800495Z",
"iopub.status.busy": "2026-05-22T13:31:04.800294Z",
"iopub.status.idle": "2026-05-22T13:31:04.802979Z",
"shell.execute_reply": "2026-05-22T13:31:04.802751Z",
"shell.execute_reply.started": "2026-05-22T13:31:04.800485Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"220 3.011150\n",
"640 3.201065\n",
"674 3.302385\n",
"Name: 1, dtype: float64"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"col = df[1]\n",
"\n",
"col[col.abs() > 3]"
]
},
{
"cell_type": "markdown",
"id": "0a411bdb",
"metadata": {},
"source": [
"To select all rows where value is greater than `3` or less than `-3` in one of the columns, you can apply [pandas.DataFrame.any](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.any.html) to a Boolean DataFrame, using `any(axis=1)` to check if a value is in a row:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "ca08a1c8",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-22T13:31:04.803480Z",
"iopub.status.busy": "2026-05-22T13:31:04.803354Z",
"iopub.status.idle": "2026-05-22T13:31:04.807356Z",
"shell.execute_reply": "2026-05-22T13:31:04.807062Z",
"shell.execute_reply.started": "2026-05-22T13:31:04.803468Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
" 2 | \n",
" 3 | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 3.073224 | \n",
" 0.392376 | \n",
" 0.464029 | \n",
" -1.086741 | \n",
"
\n",
" \n",
" | 50 | \n",
" 0.456746 | \n",
" 0.313551 | \n",
" -3.372727 | \n",
" 0.232789 | \n",
"
\n",
" \n",
" | 78 | \n",
" 3.262954 | \n",
" -1.511093 | \n",
" -0.243049 | \n",
" -0.424410 | \n",
"
\n",
" \n",
" | 220 | \n",
" 0.657494 | \n",
" 3.011150 | \n",
" -0.733968 | \n",
" 0.549828 | \n",
"
\n",
" \n",
" | 504 | \n",
" -3.240759 | \n",
" 0.202480 | \n",
" -0.181495 | \n",
" 0.088678 | \n",
"
\n",
" \n",
" | 640 | \n",
" 0.913886 | \n",
" 3.201065 | \n",
" -0.896181 | \n",
" 1.048140 | \n",
"
\n",
" \n",
" | 674 | \n",
" -0.283886 | \n",
" 3.302385 | \n",
" -0.541091 | \n",
" 0.524652 | \n",
"
\n",
" \n",
" | 833 | \n",
" 3.010898 | \n",
" -0.341878 | \n",
" -0.409523 | \n",
" 0.264089 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1 2 3\n",
"0 3.073224 0.392376 0.464029 -1.086741\n",
"50 0.456746 0.313551 -3.372727 0.232789\n",
"78 3.262954 -1.511093 -0.243049 -0.424410\n",
"220 0.657494 3.011150 -0.733968 0.549828\n",
"504 -3.240759 0.202480 -0.181495 0.088678\n",
"640 0.913886 3.201065 -0.896181 1.048140\n",
"674 -0.283886 3.302385 -0.541091 0.524652\n",
"833 3.010898 -0.341878 -0.409523 0.264089"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df[(df.abs() > 3).any(axis=1)]"
]
},
{
"cell_type": "markdown",
"id": "74382233",
"metadata": {},
"source": [
"On this basis, the values can be limited to an interval between -3 and 3. For this we use the instruction `np.sign(df)`, which generates values 1 and -1, depending on whether the values in `df` are positive or negative:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "6817f226",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-22T13:31:04.807718Z",
"iopub.status.busy": "2026-05-22T13:31:04.807640Z",
"iopub.status.idle": "2026-05-22T13:31:04.815314Z",
"shell.execute_reply": "2026-05-22T13:31:04.815016Z",
"shell.execute_reply.started": "2026-05-22T13:31:04.807710Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
" 2 | \n",
" 3 | \n",
"
\n",
" \n",
" \n",
" \n",
" | count | \n",
" 1000.000000 | \n",
" 1000.000000 | \n",
" 1000.000000 | \n",
" 1000.000000 | \n",
"
\n",
" \n",
" | mean | \n",
" 0.023276 | \n",
" 0.029288 | \n",
" -0.028434 | \n",
" 0.005751 | \n",
"
\n",
" \n",
" | std | \n",
" 1.011630 | \n",
" 0.997518 | \n",
" 0.980014 | \n",
" 0.969842 | \n",
"
\n",
" \n",
" | min | \n",
" -3.240759 | \n",
" -2.757613 | \n",
" -3.372727 | \n",
" -2.697726 | \n",
"
\n",
" \n",
" | 25% | \n",
" -0.633097 | \n",
" -0.650075 | \n",
" -0.685945 | \n",
" -0.684345 | \n",
"
\n",
" \n",
" | 50% | \n",
" 0.001117 | \n",
" 0.022371 | \n",
" -0.009798 | \n",
" 0.002211 | \n",
"
\n",
" \n",
" | 75% | \n",
" 0.705048 | \n",
" 0.710901 | \n",
" 0.657235 | \n",
" 0.654270 | \n",
"
\n",
" \n",
" | max | \n",
" 3.000000 | \n",
" 3.000000 | \n",
" 2.956046 | \n",
" 2.634073 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1 2 3\n",
"count 1000.000000 1000.000000 1000.000000 1000.000000\n",
"mean 0.023276 0.029288 -0.028434 0.005751\n",
"std 1.011630 0.997518 0.980014 0.969842\n",
"min -3.240759 -2.757613 -3.372727 -2.697726\n",
"25% -0.633097 -0.650075 -0.685945 -0.684345\n",
"50% 0.001117 0.022371 -0.009798 0.002211\n",
"75% 0.705048 0.710901 0.657235 0.654270\n",
"max 3.000000 3.000000 2.956046 2.634073"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df[df > 3] = np.sign(df) * 3\n",
"\n",
"df.describe()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.13 Kernel",
"language": "python",
"name": "python313"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.0"
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"state": {},
"version_major": 2,
"version_minor": 0
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}