suelte rápidamente las columnas de marcos de datos con un solo valor distinto

¿Existe una forma más rápida de eliminar columnas que solo contengan un valor distinto al código de abajo?

cols=df.columns.tolist() for col in cols: if len(set(df[col].tolist()))<2: df=df.drop(col, axis=1) 

Esto es realmente bastante lento para grandes marcos de datos. Lógicamente, esto cuenta el número de valores en cada columna cuando, de hecho, podría dejar de contar después de alcanzar 2 valores diferentes.

Puede usar el método Series.unique() para averiguar todos los elementos únicos en una columna, y para las columnas cuyo .unique() solo devuelve 1 elemento, puede eliminar eso. Ejemplo –

 for col in df.columns: if len(df[col].unique()) == 1: df.drop(col,inplace=True,axis=1) 

Un método que no hace caer in situ –

 res = df for col in df.columns: if len(df[col].unique()) == 1: res = res.drop(col,axis=1) 

Demo

 In [154]: df = pd.DataFrame([[1,2,3],[1,3,3],[1,2,3]]) In [155]: for col in df.columns: .....: if len(df[col].unique()) == 1: .....: df.drop(col,inplace=True,axis=1) .....: In [156]: df Out[156]: 1 0 2 1 3 2 2 

Resultados de tiempo –

 In [166]: %paste def func1(df): res = df for col in df.columns: if len(df[col].unique()) == 1: res = res.drop(col,axis=1) return res ## -- End pasted text -- In [172]: df = pd.DataFrame({'a':1, 'b':np.arange(5), 'c':[0,0,2,2,2]}) In [178]: %timeit func1(df) 1000 loops, best of 3: 1.05 ms per loop In [180]: %timeit df[df.apply(pd.Series.value_counts).dropna(thresh=2, axis=1).columns] 100 loops, best of 3: 8.81 ms per loop In [181]: %timeit df.apply(pd.Series.value_counts).dropna(thresh=2, axis=1) 100 loops, best of 3: 5.81 ms per loop 

El método más rápido todavía parece ser el método que utiliza un método unique y en bucle a través de las columnas.

Un paso:

 df = df[[c for c in list(df) if len(df[c].unique()) > 1]] 

Dos pasos:

Cree una lista de nombres de columna que tengan más de 1 valor distinto.

 keep = [c for c in list(df) if len(df[c].unique()) > 1] 

Suelte las columnas que no están en ‘mantener’

 df = df[keep] 

Puede crear una máscara de su df llamando a apply y call value_counts , esto producirá NaN para todas las filas excepto una, luego puede llamar a dropna columna y pasar param thresh=2 para que haya 2 o más que no sean NaN valores:

 In [329]: df = pd.DataFrame({'a':1, 'b':np.arange(5), 'c':[0,0,2,2,2]}) df Out[329]: abc 0 1 0 0 1 1 1 0 2 1 2 2 3 1 3 2 4 1 4 2 In [342]: df[df.apply(pd.Series.value_counts).dropna(thresh=2, axis=1).columns] Out[342]: bc 0 0 0 1 1 0 2 2 2 3 3 2 4 4 2 

Salida de las condiciones booleanas:

 In [344]: df.apply(pd.Series.value_counts) Out[344]: abc 0 NaN 1 2 1 5 1 NaN 2 NaN 1 3 3 NaN 1 NaN 4 NaN 1 NaN In [345]: df.apply(pd.Series.value_counts).dropna(thresh=2, axis=1) Out[345]: bc 0 1 2 1 1 NaN 2 1 3 3 1 NaN 4 1 NaN 
 df.loc[:,df.apply(pd.Series.nunique) != 1] 

Por ejemplo

 In: df = pd.DataFrame({'A': [10, 20, np.nan, 30], 'B': [10, np.nan, 10, 10]}) df.loc[:,df.apply(pd.Series.nunique) != 1] Out: A 0 10 1 20 2 NaN 3 30