Заменить пропущенные значения на наиболее частое число при условии

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

Я пытаюсь заменить недостающие значения в столбце “Age”, но с учетом других столбцов в этих данных Titanic – Машинное обучение на основе катастрофы

df.Age[(df['Sex'] == 0) & (df['Pclass'] == 1)]

Я пытался сделать это, используя SimpleImputer:

from sklearn.impute import SimpleImputer
Imputer = SimpleImputer(missing_values=np.nan, strategy='most_frequent')

Imputer.fit_transform( pd.DataFrame(df.Age[(df['Sex'] == 0) & (df['Pclass'] == 1)]) )

но это не сработало, и я пытался сохранить значения в столбце:

df.loc[(df.Age.isnull()) & (df.Age[(df['Sex'] == 0) & (df['Pclass'] == 1)]), 'Age'] = Imputer.fit_transform( pd.DataFrame(df.Age[(df['Sex'] == 0) & (df['Pclass'] == 1)]) )

но это тоже не работает.

Я пытался сделать это вручную, используя fillna()

df.loc[(df['Sex'] == 0) & (df['Pclass'] == 1), 'Age'].fillna(int(df.Age[(df['Sex'] == 0) & (df['Pclass'] == 1)].mode()), inplace=True)

Я пытался использовать индексы для доступа к строкам и обновления их значений:

mod = int(df.Age[(df['Sex'] == 0) & (df['Pclass'] == 1)].mode())
indices = df.loc[(df.Age.isnull()) & (df.Sex == 0) & (df.Pclass == 1), 'Age'].isnull().index
df.loc[ind, 'Age'] = mod
df[(df['Sex'] == 0) & (df['Pclass'] == 1)]['Age'].isnull().sum()

это сработало, и результатом было: 0, но когда я пытаюсь применить это в цикле for, это выдает ошибку

for i in range(1,3):
    for j in range(1,4):    
        indices = df.loc[(df.Sex == i) & (df.Pclass == j), 'Age'].isnull().index
        mod = int(df.Age[(df['Sex'] == i) & (df['Pclass'] == j)].mode())
        df.loc[ind, 'Age'] = mod

Я хочу знать, что неправильно в первых двух способах и почему третий не работает в цикле?

Это решение работает хорошо, но я не знаю, почему вышеуказанные не работают!

Imputer = SimpleImputer(missing_values=np.nan, strategy='most_frequent')
for i in range(2):
    for j in range(1,4):
        ls = np.array(df.Age[((df.Sex==i) & (df.Pclass==j))]).reshape(-1,1)
        df.Age[((df.Sex==i) & (df.Pclass==j))] = Imputer.fit_transform(ls)[:,0]
df.Age.isnull().sum()

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

Для замены пропущенных значений в столбце "Age" в зависимости от условий других столбцов (например, "Sex" и "Pclass") в наборе данных о Титанике, важно правильно использовать методы обработки данных и избегать распространённых ошибок.

1. Проблемы с первоначальными подходами

Ваши первые два подхода с использованием SimpleImputer не сработали из-за того, что метод fit_transform применялся к подмножеству данных, и результат не сохранялся в исходный DataFrame. SimpleImputer работает с полными массивами данных и не считает, что вы хотите обновить конкретные строки DataFrame. Давайте пробежимся по тем ошибкам, которые вы привели.

Проблема с SimpleImputer

Когда вы используете SimpleImputer.fit_transform, он создает новый массив, который не привязывается обратно к оригинальному DataFrame. Например, код:

Imputer.fit_transform(pd.DataFrame(df.Age[(df['Sex'] == 0) & (df['Pclass'] == 1)]))

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

2. Корректное использование fillna()

Используя fillna(), важно помнить о модификациях DataFrame. Метод fillna() возвращает новый объект, если он не выставляется в inplace=True. Например, ваш код:

df.loc[(df['Sex'] == 0) & (df['Pclass'] == 1), 'Age'].fillna(int(df.Age[(df['Sex'] == 0) & (df['Pclass'] == 1)].mode()), inplace=True)

этот код не изменяет исходный DataFrame. Вместо этого вы можете сделать следующее:

mode_value = int(df.Age[(df['Sex'] == 0) & (df['Pclass'] == 1)].mode())
df.loc[(df['Sex'] == 0) & (df['Pclass'] == 1) & (df['Age'].isnull()), 'Age'] = mode_value

3. Некорректное использование цикла

Что касается вашего цикла, ошибка возникает из-за неправильного использования переменной индексов в df.loc[ind, 'Age'] = mod, где переменная ind не определяется перед её использованием.

Правильное использование должно выглядеть так:

for i in range(1, 3):
    for j in range(1, 4):    
        indices = df.loc[(df.Sex == i) & (df.Pclass == j), 'Age'].isnull().index
        if not indices.empty:  # Проверяем, есть ли индексы
            mod = int(df.Age[(df['Sex'] == i) & (df['Pclass'] == j)].mode())
            df.loc[indices, 'Age'] = mod

Заключение

Ваше окончательное решение должно включать корректное сохранение результатов после использования SimpleImputer, четкое определение индексов при работе в циклах, и понимание, как работает fillna() с параметром inplace.

Таким образом, вы сможете заменить пропущенные значения в столбце "Age" в вашем DataFrame в зависимости от условий, учитывая пол и класс пассажиров. Настоятельно рекомендую протестировать ваше решение на различных подгруппах данных, чтобы убедиться в его гибкости и устойчивости к ошибкам.

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

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