在统计学中,有一种称为 中位数绝对偏差(Median Absolute Deviation,MAD) 的方法,可以用来识别异常值并将其排除在外。MAD是一种基于中位数的离散度量,它可以帮助识别数据集中的异常值。
具体步骤如下:
- 计算数据集的中位数。
- 计算每个数据点与中位数的绝对偏差。
- 计算这些绝对偏差的中位数,即MAD。
通过设置阈值,例如MAD的倍数,来判断哪些数据点被认为是异常值。
#include <stdio.h>
#include <stdlib.h>
// 计算中位数
float median(int arr[], int n) {
float median_val;
if (n % 2 == 0) {
median_val = (arr[n/2 - 1] + arr[n/2]) / 2.0;
} else {
median_val = arr[n/2];
}
return median_val;
}
// 计算绝对值
int abs_val(int x) {
return (x < 0) ? -x : x;
}
// 计算中位数绝对偏差(MAD)
float mad(int arr[], int n) {
float median_val = median(arr, n);
int deviations[n];
for (int i = 0; i < n; i++) {
deviations[i] = abs_val(arr[i] - median_val);
}
return median(deviations, n);
}
// 交换两个元素的值
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 快速排序函数(非递归)
void quickSort(int arr[], int low, int high) {
if (low >= high) return; // 添加基本情况处理
int stack[high - low + 1]; // 创建一个栈
int top = -1; // 栈顶指针
stack[++top] = low;
stack[++top] = high;
while (top >= 0) {
high = stack[top--];
low = stack[top--];
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
int pi = i + 1;
if (pi - 1 > low) {
stack[++top] = low;
stack[++top] = pi - 1;
}
if (pi + 1 < high) {
stack[++top] = pi + 1;
stack[++top] = high;
}
}
}
int main() {
// int data[] = {50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 40};
int data[] = {50, 50, 50, 50, 50, 50, 30, 20, 10, 5, 5, 5};
int n = sizeof(data) / sizeof(data[0]);
quickSort(data, 0, n - 1);
float threshold = 1.5; // 设置MAD的倍数阈值
float median_abs_dev = mad(data, n);
// 排除异常值
for (int i = 0; i < n; i++) {
if (abs_val(data[i] - median(data, n)) > threshold * median_abs_dev) {
data[i] = median(data, n);
}
}
// 计算剩余数值的平均值
int sum = 0;
for (int i = 0; i < n; i++) {
sum += data[i];
}
float average = (float)sum / n;
printf("剔除异常值后的平均值: %.2f\n", average);
return 0;
}
剔除异常值后的平均值: 50.00