Почему средняя токсичность расовых подгрупп ниже, чем средняя токсичность всей расовой категории?

Вопрос или проблема

Я работаю с набором данных, который измеряет показатели токсичности для разных расовых подгрупп. Я агрегировал данные, чтобы проанализировать среднюю токсичность для каждой расовой подгруппы и сравнил ее со средней токсичностью для всей категории «Раса». Код сейчас выглядит ужасно, и у меня нет сил в данный момент полностью объяснить проект. Моя основная проблема в том, что средняя токсичность для выборок отдельных подгрупп (например, «Черные», «Белые», «Азиаты») значительно ниже средней токсичности для всей популяции этих рас.

Например,

среднее для белых (всего): 0.5366622949663186

среднее для белых (выборка 10%): 0.021136063408190225

среднее для белых (выборка 60%): 0.020211360634081903

Эти средние значения выборок слишком низкие по сравнению с общим средним. Я просто не знаю, почему.


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

categories = {
    "Сексуальная ориентация": ["лесбиянка", "гей", "бисексуал", "трансгендер", "транс", "квир", "лгбт", "лгбтк", "гомосексуал", "гетеросексуал", "гетеросексуальный"],
    "Гендерная идентичность": ["мужчина", "женщина", "небинарный"],
    "Раса": ["африканец", "афроамериканец", "черный", "белый", "европеец", "испанец", "латино", "латина", "латинкс", "мексиканец", "азиат", "индиец", "ближневосточный", "китаец", "японец"],
    "Национальность": ["канадец", "американец"],
    "Религия": ["христианин", "мусульманин", "еврей", "буддист", "католик", "протестант", "сикх", "даосист"],
    "Возраст": ["старый", "старше", "молодой", "моложе", "подросток", "миллениал", "средний возраст", "пожилой"],
    "Недуг": ["слепой", "глухой", "парализованный"]
}

# Корректная загрузка набора данных
df = pd.read_csv("toxity_per_attribute.csv", dtype=str)  # Сначала читаем все как строки

# Преобразование TOXICITY в формат float
df["TOXICITY"] = pd.to_numeric(df["TOXICITY"], errors="coerce")

# Удаление строк, где TOXICITY больше 1 (для исправления проблем с несовпадением)
df = df[df["TOXICITY"] <= 1]

# Преобразование столбцов подгрупп из строк "TRUE"/"FALSE" в фактические булевые значения
subgroup_cols = df.columns[2:]  # Все столбцы, кроме Wiki_ID и TOXICITY
df[subgroup_cols] = df[subgroup_cols].replace({"TRUE": True, "FALSE": False})

# Шаг 3.1: Удаление строк, в которых все значения подгрупп равны False
df_filtered = df.copy()
df_filtered["subgroup_sum"] = df_filtered[subgroup_cols].sum(axis=1)  # Обеспечиваем числовую сумму
df_filtered = df_filtered[df_filtered["subgroup_sum"] > 0]  # Оставляем строки, где хотя бы одна подгруппа равна True
df_filtered.drop(columns=["subgroup_sum"], inplace=True)

# Шаг 2: Классификация подгрупп в Защищенные классы
protected_classes = categories

def combine_subgroups(df, class_dict):
    for class_name, subgroups in class_dict.items():
        df[class_name] = df[subgroups].max(axis=1)  # Обеспечение присутствия
combine_subgroups(df_filtered, protected_classes)

# Шаг 3: Убедитесь, что значения подгрупп остаются 0 или 1
df_filtered[subgroup_cols] = df_filtered[subgroup_cols].replace({True: 1, False: 0})

# Шаг 4: Вычисление корреляции между Защищенными классами и токсичностью
correlations = {}
for class_name in protected_classes.keys():
    filtered_df = df_filtered[[class_name, "TOXICITY"]].dropna()
    if filtered_df[class_name].nunique() > 1:
        correlations[class_name] = filtered_df[class_name].corr(filtered_df['TOXICITY'])
    else:
        correlations[class_name] = 0

correlation_table = pd.DataFrame({
    'Защищенный класс': correlations.keys(),
    'Корреляция': correlations.values()
})
print("Обновленная таблица корреляций:")
print(correlation_table)

# Шаг 5: Статистический анализ
mean_toxicity = df_filtered['TOXICITY'].mean()
std_toxicity = df_filtered['TOXICITY'].std()
confidence_interval = (
    max(0, mean_toxicity - 1.96 * std_toxicity),
    min(1, mean_toxicity + 1.96 * std_toxicity)
)
print(f"Средняя токсичность: {mean_toxicity}, Стандартное отклонение: {std_toxicity}, 95%-ный интервал: {confidence_interval}")

# Шаг 6: Анализ подгрупп для выбранного защищенного класса
chosen_class = "Раса"
subgroup_means = {}
for subgroup in categories[chosen_class]:
    if subgroup in df_filtered.columns:
        mean_value = df_filtered[df_filtered[subgroup] > 0]["TOXICITY"].mean()
        print(f"Средняя токсичность для {subgroup}: {mean_value}")
        subgroup_means[subgroup] = mean_value
    else:
        print(f"Предупреждение: {subgroup} не найден в df_filtered")
        subgroup_means[subgroup] = None
print(f"Средние значения токсичности для подгрупп {chosen_class}:", subgroup_means)

# Шаг 7: Визуализация Boxplot для 3 лучших корреляций
top_correlations = correlation_table.nlargest(3, 'Корреляция')
for class_name in top_correlations["Защищенный класс"]:
    plt.figure(figsize=(8, 6))
    sns.boxplot(x=df_filtered[class_name], y=df_filtered["TOXICITY"])
    plt.xlabel(class_name)
    plt.ylabel("Токсичность")
    plt.title(f"Распределение токсичности по {class_name}")
    plt.show()

# Шаг 8: Анализ случайной выборки для выбранного защищенного класса
def random_sample_analysis(df, sample_size, column):
    sample = df.sample(frac=sample_size, random_state=42)
    mean_sample = sample[column].mean()
    std_sample = sample[column].std()
    margin_of_error = 1.96 * (std_sample / np.sqrt(len(sample)))
    return mean_sample, std_sample, margin_of_error

sample_10 = random_sample_analysis(df_filtered, 0.1, "Раса")
sample_60 = random_sample_analysis(df_filtered, 0.6, "Раса")
print(f"10% Выборка (Раса): Среднее = {sample_10[0]}, Станд. отклонение = {sample_10[1]}, Погрешность = {sample_10[2]}")
print(f"60% Выборка (Раса): Среднее = {sample_60[0]}, Станд. отклонение = {sample_60[1]}, Погрешность = {sample_60[2]}")

# Шаг 8.1: Случайная выборка для подгрупп в выбранном защищенном классе
for subgroup in categories[chosen_class]:
    if subgroup in df_filtered.columns:
        sample_10 = random_sample_analysis(df_filtered, 0.1, subgroup)
        sample_60 = random_sample_analysis(df_filtered, 0.6, subgroup)
        print(f"10% Выборка ({subgroup}): Среднее = {sample_10[0]}, Станд. отклонение = {sample_10[1]}, Погрешность = {sample_10[2]}")
        print(f"60% Выборка ({subgroup}): Среднее = {sample_60[0]}, Станд. отклонение = {sample_60[1]}, Погрешность = {sample_60[2]}")

sns.histplot(df_filtered["TOXICITY"], bins=20, kde=True)
plt.xlabel("Токсичность")
plt.ylabel("Частота")
plt.title("Распределение токсичности в полном наборе данных")
plt.show()

for subgroup in categories["Раса"]:
    if subgroup in df_filtered.columns:
        sample_10 = df_filtered.sample(frac=0.1, random_state=42)
        sample_60 = df_filtered.sample(frac=0.6, random_state=42)

        # Проверьте, сколько строк действительно имеют для подгруппы значение True
        print(f"{subgroup}: {sample_10[sample_10[subgroup] > 0].shape[0]} / {sample_10.shape[0]} строк в выборке 10%")
        print(f"{subgroup}: {sample_60[sample_60[subgroup] > 0].shape[0]} / {sample_60.shape[0]} строк в выборке 60%")

Я попробовал это:

for subgroup in categories[chosen_class]:
    if subgroup in df_filtered.columns:
        sample_10 = random_sample_analysis(df_filtered, 0.1, subgroup)
        sample_60 = random_sample_analysis(df_filtered, 0.6, subgroup)
        print(f"10% Выборка ({subgroup}): Среднее = {sample_10[0]}, Станд. отклонение = {sample_10[1]}, Погрешность = {sample_10[2]}")
        print(f"60% Выборка ({subgroup}): Среднее = {sample_60[0]}, Станд. отклонение = {sample_60[1]}, Погрешность = {sample_60[2]}")

Которое, как я думал, сработает, но оно все еще дает мне средние значения выборок, которые слишком низки по сравнению с средними значениями всей популяции.

Ответ или решение

Понимание того, почему средняя токсичность отдельных расовых подгрупп ниже средней токсичности для всей категории "Расы", требует комплексного подхода, связанного как с теоретическими аспектами статистического анализа, так и с практическими примерами и их приложением.

Теория

Первоначально рассмотрим теоретический аспект проблемы. Когда мы анализируем набор данных с точки зрения подгрупп, мы фактически применяем процесс выборки, который может привести к различиям в статистических показателях. Основная причина такой разницы может заключаться в смещении выборки. Смещение выборки происходит, когда выбранная выборка не является репрезентативной для всей генеральной совокупности. В случае вашего набора данных, среднее значение токсичности для подгрупп может быть искажено из-за меньшей величины выборки или из-за специфического распределения значений, характерного для этой подгруппы.

Другой аспект — это влияние редких событий. Если в генеральной совокупности наблюдается большое количество высокотоксичных случаев, а в подгруппе — нет, это также может привести к ниже средней токсичности в подгруппе по сравнению с общей категорией.

Пример

Для иллюстрации этого предположим, что в вашей выборке для категории "Белые" содержится несколько записей с очень высоким уровнем токсичности, таких как 0.9 или даже выше. Эти значения могут существенно влиять на общее среднее в то время как при случайной выборке из подгруппы такие значения могут и не попасть в выборку.

Приложение

Практически вы можете изучить следующие подходы, чтобы понять и, возможно, исправить эту диспропорцию:

  1. Проверка репрезентативности. Убедитесь, что выборка из подгруппы действительно репрезентативна для всей подгруппы. Это может включать применение стратифицированной выборки, где учитывается распределение ключевых показателей в подгруппе.

  2. Анализ редких событий. Проверьте распределение токсичности в генеральной совокупности и выясните, возможно ли наличие экстремальных значений, которые вносят вклад в увеличение общей средней.

  3. Исключение аномалий. Рассмотрите возможность исключения аномальных значений или применения методов стабилизации, таких как логарифмическое преобразование.

  4. Проверка на полноту и качество данных. Проверьте, нет ли в данных ошибок или пропущенных значений, которые могут повлиять на анализ.

  5. Увеличение размера выборки. Попробуйте увеличить размер выборки, чтобы исследовать, приводит ли это к изменению средней токсичности для подгруппы ближе к общей средней.

  6. Глубокий анализ данных. Выполните более детальный анализ подгрупп, включая проверку корреляций и взаимосвязей разных подкатегорий и токсичности.

Заключение

Ваш анализ средних показателей токсичности подсказывает существование потенциальных проблем с выборкой и распределением данных. Эти проблемы часто встречаются в аналитике данных и требуют тщательной проверки и анализа. Применение перечисленных выше стратегий может помочь улучшить понимание вашего набора данных и предоставить более точные результаты, соответствующие различным демографическим характеристикам анализируемых подгрупп.

Оцените материал
Добавить комментарий

Капча загружается...