J'ai un dataframe qui peut ou peut ne pas avoir des colonnes qui ont la même valeur. Par exemple
row A B
1 9 0
2 7 0
3 5 0
4 2 0
J'aimerais revenir juste
row A
1 9
2 7
3 5
4 2
Existe-t-il un moyen simple d’identifier ces colonnes, puis de les supprimer?
Je crois que cette option sera plus rapide que les autres réponses ici, car elle ne parcourra le cadre de données qu'une fois pour la comparaison et court-circuitera si une valeur non unique est trouvée.
>>> df
0 1 2
0 1 9 0
1 2 7 0
2 3 7 0
>>> df.loc[:, (df != df.iloc[0]).any()]
0 1
0 1 9
1 2 7
2 3 7
En ignorant NaN
s comme d'habitude, une colonne est constante si nunique() == 1
. Alors:
>>> df
A B row
0 9 0 1
1 7 0 2
2 5 0 3
3 2 0 4
>>> df = df.loc[:,df.apply(pd.Series.nunique) != 1]
>>> df
A row
0 9 1
1 7 2
2 5 3
3 2 4
En supposant que le DataFrame soit complètement de type numeric:
tu peux essayer:
>>> df = df.loc[:, df.var() == 0.0]
qui supprimera les colonnes constantes (c'est-à-dire la variance = 0).
Si le DataFrame est de type numeric et object, alors vous devriez essayer:
>>> enum_df = df.select_dtypes(include=['object'])
>>> num_df = df.select_dtypes(exclude=['object'])
>>> num_df = num_df.loc[:, num_df.var() == 0.0]
>>> df = pd.concat([num_df, enum_df], axis=1)
qui supprimera uniquement les colonnes constantes de type numérique.
Si vous souhaitez également ignorer/supprimer les colonnes d’énumération constante, vous devez essayer:
>>> enum_df = df.select_dtypes(include=['object'])
>>> num_df = df.select_dtypes(exclude=['object'])
>>> enum_df = enum_df.loc[:, [True if y !=1 else False for y in [len(np.unique(x, return_counts=True)[-1]) for x in enum_df.T.as_matrix()]]]
>>> num_df = num_df.loc[:, num_df.var() == 0.0]
>>> df = pd.concat([num_df, enum_df], axis=1)
J'ai comparé diverses méthodes sur une trame de données de taille 120 * 10000. Et trouvé l'efficace est
def drop_constant_column(dataframe):
"""
Drops constant value columns of pandas dataframe.
"""
return dataframe.loc[:, (dataframe != dataframe.iloc[0]).any()]
1 boucle, meilleur de 3: 237 ms par boucle
Les autres prétendants sont
def drop_constant_columns(dataframe):
"""
Drops constant value columns of pandas dataframe.
"""
result = dataframe.copy()
for column in dataframe.columns:
if len(dataframe[column].unique()) == 1:
result = result.drop(column,axis=1)
return result
1 boucle, meilleur de 3: 19,2 s par boucle
def drop_constant_columns_2(dataframe):
"""
Drops constant value columns of pandas dataframe.
"""
for column in dataframe.columns:
if len(dataframe[column].unique()) == 1:
dataframe.drop(column,inplace=True,axis=1)
return dataframe
1 boucle, meilleur de 3: 317 ms par boucle
def drop_constant_columns_3(dataframe):
"""
Drops constant value columns of pandas dataframe.
"""
keep_columns = [col for col in dataframe.columns if len(dataframe[col].unique()) > 1]
return dataframe[keep_columns].copy()
1 boucle, meilleur de 3: 358 ms par boucle
def drop_constant_columns_4(dataframe):
"""
Drops constant value columns of pandas dataframe.
"""
keep_columns = dataframe.columns[dataframe.nunique()>1]
return dataframe.loc[:,keep_columns].copy()
1 boucle, meilleur de 3: 1,8 s par boucle
Voici ma solution car je devais faire les colonnes objet et numérique. Ne prétendant pas être super efficace ou quoi que ce soit mais il fait le travail.
def drop_constants(df):
"""iterate through columns and remove columns with constant values (all same)"""
columns = df.columns.values
for col in columns:
# drop col if unique values is 1
if df[col].nunique(dropna=False) == 1:
del df[col]
return df
Mise en garde supplémentaire, cela ne fonctionnera pas sur les colonnes de listes ou de tableaux car ils ne sont pas hashable.