f_classif and f_oneway produce the same results but differ in
implementation and use.
First, recall that 1-way ANOVA tests the null hypothesis that
samples in two or more classes have the same population mean. In your case,
I suppose y_train is an array-like categorical variable containing some
classes, and x_train is an array-like or dataframe containing features.
Then the right way to pass sample measurements for each class into
f_oneway is
f_oneway(x_train[y_train == 'class1'], x_train[y_train == 'class2'], # ...,
x_train[y_train == 'classk'])
or more conveniently
f_oneway(*[x_train[y_train == c] for c in np.unique(y_train)])
f_classif and other scoring functions from scikit-learn require both
features and labels:
f_classif(x_train, y_train)
Example:
>>> import numpy as np
>>> from scipy.stats import f_oneway
>>> from sklearn.datasets import make_classification
>>> from sklearn.feature_selection import f_classif
>>> n_samples, n_features, n_classes = 1000, 4, 3
>>> X, y = make_classification(n_samples=n_samples, n_features=n_features,
... n_classes=n_classes, n_informative=3, n_redundant=1,
... scale=0.2, random_state=0)
>>> f_tuple = f_oneway(*[X[y == k] for k in range(n_classes)])
>>> f_stat, f_prob = f_classif(X, y)
>>> np.allclose(f_tuple.statistic, f_stat), np.allclose(f_tuple.pvalue, f_prob)
(True, True)
>>> f_stat.shape[0] == n_features
True
Finally, SelectKBest produces exactly the same results as the score_func
function provided and stores them in the scores_ attribute. So,
your selector's scores are correct and will be equal to an f_oneway's
output if you pass the arguments properly.
If you rank features manually, it is up to you whether to rely on scores or
p-values. But If you apply scikit-learn's feature selection techniques, it
depends on the implementation. SelectKBest and SelectPercentile
rank by scores, while SelectFpr, SelectFwe, or SelectFdr
by p-values. If p-values are supported by a scoring function, then you can use
the latter three models with this function and some p-value (alpha, the
highest p-value for features to keep).
Example:
>>> from sklearn.feature_selection import SelectFpr
>>> s = SelectFpr(score_func=f_classif, alpha=0.01)
>>> X_t = s.fit_transform(X, y)
>>> X_t.shape
(1000, 3) # Recall that one feature was uninformative (redundant)