web-dev-qa-db-fra.com

cadre de données pandas supprimer la colonne constante

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?

21
user1802143

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
28
chthonicdaemon

En ignorant NaNs 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
19
DSM

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)
2
Hng

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

2
Yantraguru

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.

0
dreyco676