pandas dataframe eliminar columna constante

Tengo un dataframe que puede o no tener columnas que tienen el mismo valor. Por ejemplo

row AB 1 9 0 2 7 0 3 5 0 4 2 0 

Me gustaría volver solo

  row A 1 9 2 7 3 5 4 2 

¿Hay una forma sencilla de identificar si alguna de estas columnas existe y luego eliminarlas?

Creo que esta opción será más rápida que las otras respuestas aquí, ya que atravesará el dataframe solo una vez para la comparación y cortocircuito si se encuentra un valor no único.

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

Ignorando los NaN como de costumbre, una columna es constante si nunique() == 1 . Asi que:

 >>> df AB 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 

Suponiendo que el DataFrame es completamente de tipo numérico:

puedes probar:

 >>> df = df.loc[:, df.var() == 0.0] 

que eliminará columnas constantes (es decir, varianza = 0).

Si el DataFrame es de tipo numérico y de objeto, entonces debe intentar:

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

el cual caerá columnas constantes de tipo numérico solamente.

Si también desea ignorar / eliminar columnas de enumeración constantes, debe intentar:

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

Comparé varios métodos en el dataframe de tamaño 120 * 10000. Y encontré que el eficiente es

 def drop_constant_column(dataframe): """ Drops constant value columns of pandas dataframe. """ return dataframe.loc[:, (dataframe != dataframe.iloc[0]).any()] 

1 bucle, el mejor de 3: 237 ms por bucle

Los otros contendientes son

 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 bucle, el mejor de 3: 19,2 s por bucle

 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 bucle, el mejor de 3: 317 ms por bucle

 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 bucle, el mejor de 3: 358 ms por bucle

 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 bucle, lo mejor de 3: 1.8 s por bucle

Aquí está mi solución, ya que necesitaba hacer columnas tanto de objetos como numéricas. No reclamando su súper eficiente ni nada, pero hace el trabajo.

 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 

Advertencia adicional, no funcionará en las columnas de listas o matrices, ya que no son hashable.