добавь в этот код shap для того чтоб оценить каждый признак 
# Функция для преобразования диапазона в среднее значение

def convert_range_to_float(s):
    if isinstance(s, str):
        # Заменяем запятые на точки для корректного преобразования в float
        s = s.replace(',', '.')
        if '+' in s:
            # Если в строке есть '+', берем первое число до '+'
            match = re.search(r"[-+]?\d*.\d+|\d+", s)
            if match:
                return float(match.group(0))
        elif '-' in s:
            # Если в строке есть '-', используем диапазон
            numbers = s.split('-')
            try:
                # Преобразуем оба числа в float и возвращаем их среднее значение
                return np.mean([float(num) for num in numbers])
            except ValueError:
                return 0
        else:
            # Если нет ни '+', ни '-', просто преобразуем строку в float
            try:
                return float(s)
            except ValueError:
                return 0
    return 0

# Применение функции к нужным столбцам (укажите те столбцы, у которых есть диапазоны)
range_columns = ['nitrogen', 'potassium', 'phosphorus', 'molybdenum']

for col in range_columns:
    data[col] = data[col].apply(convert_range_to_float)

# Определение целевой переменной и признаков
target = 'germination_ability'
features = [col for col in data.columns if col != target]

# Проверка наличия всех категориальных признаков в данных
categorical_features = ['soil_type', 'soil_texture', 'location_of_production',
                        'harverster_model', 'sunflower_variety', 'farmer',
                        'suflower_seeds_gender', 'year']

for feature in categorical_features:
    if feature not in data.columns:
        print(f"Feature '{feature}' is not found in data columns")

# Преобразование датовых переменных
data['sowing_start_date'] = pd.to_datetime(data['sowing_start_date'])
data['sowing_start_day_of_year'] = data['sowing_start_date'].dt.dayofyear
data = data.drop(columns=['sowing_start_date'])

# Разделение целевой переменной и признаков
X = data.drop(columns=['germination_ability'])
y = data['germination_ability']

# Определение категориальных и числовых признаков
categorical_features = ['nitrogen', 'potassium', 'phosphorus', 'molybdenum', 'soil_type', 'soil_texture', 'location_of_production', 'harverster_model', 'sunflower_variety', 'farmer', 'suflower_seeds_gender', 'year']
numerical_features = list(set(X.columns) - set(categorical_features))

# Преобразование категориальных переменных и масштабирование числовых
preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), numerical_features),
        ('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)])

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Конструирование и обучение модели
xgb_model = XGBRegressor(random_state=42)
model = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('regressor', xgb_model)
])

# Определение параметров для GridSearch
param_grid = {
    'regressor__n_estimators': [50, 100, 200, 300],
'regressor__max_depth': [3, 5, 7, 9],
'regressor__learning_rate': [0.001, 0.01, 0.1, 0.2, 0.3],
'regressor__alpha': [0, 0.1, 0.5, 1],
'regressor__lambda_': [0, 0.1, 0.5, 1]
}

# GridSearchCV для подбора гиперпараметров
grid_search = GridSearchCV(model, param_grid, cv=3, scoring='neg_mean_squared_error', n_jobs=-1)

# Обучение модели с использованием GridSearchCV
grid_search.fit(X_train, y_train)

# Лучшая модель
best_model = grid_search.best_estimator_

# Оценка улучшенной модели
y_pred_train = best_model.predict(X_train)
y_pred_test = best_model.predict(X_test)

print('Best Parameters:', grid_search.best_params_)
print('Train RMSE:', np.sqrt(mean_squared_error(y_train, y_pred_train)))
print('Test RMSE:', np.sqrt(mean_squared_error(y_test, y_pred_test)))

# Вывод значимости факторов для улучшенной модели
xgb_best_model = best_model.named_steps['regressor']
feature_importance = xgb_best_model.feature_importances_

# Преобразование OneHotEncoder обратно в метки
preprocessor = best_model.named_steps['preprocessor']
onehot_encoder = preprocessor.transformers_[1][1]
onehot_columns = onehot_encoder.get_feature_names_out(categorical_features)
all_columns = numerical_features + list(onehot_columns)

# Создание DataFrame с значимостями
feature_importance_df = pd.DataFrame({'Feature': all_columns, 'Importance': feature_importance})

# Агрегация значимостей для категориальных признаков
feature_importance_df['Original Feature'] = feature_importance_df['Feature'].str.extract(r'([^_]*)')[0]
aggregated_importance = feature_importance_df.groupby('Original Feature')['Importance'].sum().reset_index()
aggregated_importance = aggregated_importance.sort_values(by='Importance', ascending=False)

# Визуализация значимости факторов
plt.figure(figsize=(10, 8))
sns.barplot(x='Importance', y='Original Feature', data=aggregated_importance)
plt.title('Aggregated Feature Importance for Gradient Boosting')
plt.show()