python pandas dataframe

python - Seleccionar columnas si alguna de sus filas contiene una cadena determinada



pandas dataframe (5)

stack con any

df.columns[df.stack().str.contains(''%'').any(level=1)] Index([''C'', ''D''], dtype=''object'')

comprensión

[c for c in df if df[c].str.contains(''%'').any()] [''C'', ''D'']

filter

[*filter(lambda c: df[c].str.contains(''%'').any(), df)] [''C'', ''D'']

Hallazgo de numpy

from numpy.core.defchararray import find df.columns[(find(df.to_numpy().astype(str), ''%'') >= 0).any(0)] Index([''C'', ''D''], dtype=''object'')

Estoy intentando obtener una lista de columnas en un DataFrame si algún valor en una columna contiene una cadena. Por ejemplo, en el siguiente marco de datos, me gustaría una lista de columnas que tengan el% en la cadena. Puedo lograr esto usando un método for y el método series.str.contains pero no parece óptimo, especialmente con un conjunto de datos más grande. ¿Hay una manera más eficiente de hacer esto?

import pandas as pd df = pd.DataFrame({''A'': {0: ''2019-06-01'', 1: ''2019-06-01'', 2: ''2019-06-01''}, ''B'': {0: ''10'', 1: ''20'', 2: ''30''}, ''C'': {0: ''10'', 1: ''20%'', 2: ''30%''}, ''D'': {0: ''10%'', 1: ''20%'', 2: ''30''}, })

Marco de datos

A B C D 0 2019-06-01 10 10 10% 1 2019-06-01 20 20% 20% 2 2019-06-01 30 30% 30

Método actual

col_list = [] for col in df.columns: if (True in list(df[col].str.contains(''%''))) is True: col_list.append(col)

Salida

[''C'', ''D'']


Compare con replace y cree una máscara para indexar las columnas en consecuencia:

df.loc[:,(df != df.replace(''%'', '''', regex=True)).any()] C D 0 10 10% 1 20% 20% 2 30% 30 df.columns[(df != df.replace(''%'', '''', regex=True)).any()] # Index([''C'', ''D''], dtype=''object'')

Esto evita la necesidad de un bucle, una apply o un applymap .


Primero use DataFrame.select_dtypes para filtrar solo columnas de objetos, obviamente cadenas de cadenas.

Luego use DataFrame.applymap para los valores de verificación elementales con DataFrame.any para devolver True si hay al menos una por columna, por lo que es posible filtrar columnas:

c = df.columns[df.select_dtypes(object).applymap(lambda x: ''%'' in str(x)).any()].tolist() print (c) [''C'', ''D'']

O use Series.str.contains por columnas, el parámetro na debe omitirse si todas las columnas de cadenas:

f = lambda x: x.str.contains(''%'', na=False) c = df.columns[df.select_dtypes(object).apply(f).any()].tolist() print (c) [''C'', ''D'']


Prueba esto:

df.columns[df.apply(lambda x: x.str.contains("/%")).any()]


Vamos a melt

df.melt().loc[lambda x :x.value.str.contains(''%''),''variable''].unique() Out[556]: array([''C'', ''D''], dtype=object)