iloc example columns python pandas dataframe selection

python - example - pandas where



pandas: la mejor manera de seleccionar todas las columnas cuyos nombres comienzan con X (6)

Ahora que los índices de los pandas admiten operaciones de cadena, podría decirse que la forma más simple y mejor de seleccionar columnas que comienzan con ''foo'' es simplemente:

df.loc[:, df.columns.str.startswith(''foo'')]

Alternativamente, puede filtrar las etiquetas de columna (o fila) con df.filter() . Para especificar una expresión regular que coincida con los nombres que comienzan con foo. :

>>> df.filter(regex=r''^foo/.'', axis=1) foo.aa foo.bars foo.fighters foo.fox foo.manchu 0 1.0 0 0 2 NA 1 2.1 0 1 4 0 2 NaN 0 NaN 1 0 3 4.7 0 0 0 0 4 5.6 0 0 0 0 5 6.8 1 0 5 0

Para seleccionar solo las filas requeridas (que contienen un 1 ) y las columnas, puede usar loc , seleccionando las columnas con filter (o cualquier otro método) y las filas con any :

>>> df.loc[(df == 1).any(axis=1), df.filter(regex=r''^foo/.'', axis=1).columns] foo.aa foo.bars foo.fighters foo.fox foo.manchu 0 1.0 0 0 2 NA 1 2.1 0 1 4 0 2 NaN 0 NaN 1 0 5 6.8 1 0 5 0

Tengo un DataFrame:

import pandas as pd import numpy as np df = pd.DataFrame({''foo.aa'': [1, 2.1, np.nan, 4.7, 5.6, 6.8], ''foo.fighters'': [0, 1, np.nan, 0, 0, 0], ''foo.bars'': [0, 0, 0, 0, 0, 1], ''bar.baz'': [5, 5, 6, 5, 5.6, 6.8], ''foo.fox'': [2, 4, 1, 0, 0, 5], ''nas.foo'': [''NA'', 0, 1, 0, 0, 0], ''foo.manchu'': [''NA'', 0, 0, 0, 0, 0],})

Quiero seleccionar valores de 1 en columnas que comienzan con foo. . ¿Hay una mejor manera de hacerlo que no sea:

df2 = df[(df[''foo.aa''] == 1)| (df[''foo.fighters''] == 1)| (df[''foo.bars''] == 1)| (df[''foo.fox''] == 1)| (df[''foo.manchu''] == 1) ]

Algo similar a escribir algo como:

df2= df[df.STARTS_WITH_FOO == 1]

La respuesta debería imprimir un DataFrame como este:

bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo 0 5.0 1.0 0 0 2 NA NA 1 5.0 2.1 0 1 4 0 0 2 6.0 NaN 0 NaN 1 0 1 5 6.8 6.8 1 0 5 0 0 [4 rows x 7 columns]


La forma más simple es usar str directamente en los nombres de columna, no hay necesidad de pd.Series

df.loc[:,df.columns.str.startswith("foo")]


Mi solución. Puede ser más lento en rendimiento:

a = pd.concat(df[df[c] == 1] for c in df.columns if c.startswith(''foo'')) a.sort_index() bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo 0 5.0 1.0 0 0 2 NA NA 1 5.0 2.1 0 1 4 0 0 2 6.0 NaN 0 NaN 1 0 1 5 6.8 6.8 1 0 5 0 0


Otra opción para la selección de las entradas deseadas es utilizar el map :

df.loc[(df == 1).any(axis=1), df.columns.map(lambda x: x.startswith(''foo''))]

que le da todas las columnas para las filas que contienen un 1 :

foo.aa foo.bars foo.fighters foo.fox foo.manchu 0 1.0 0 0 2 NA 1 2.1 0 1 4 0 2 NaN 0 NaN 1 0 5 6.8 1 0 5 0

La selección de fila se realiza por

(df == 1).any(axis=1)

como en la respuesta de @ ajcr que te da:

0 True 1 True 2 True 3 False 4 False 5 True dtype: bool

lo que significa que las filas 3 y 4 no contienen un 1 y no se seleccionarán.

La selección de las columnas se realiza mediante una indexación booleana como esta:

df.columns.map(lambda x: x.startswith(''foo''))

En el ejemplo anterior, esto devuelve

array([False, True, True, True, True, True, False], dtype=bool)

Entonces, si una columna no comienza con foo , se devuelve False y, por lo tanto, la columna no se selecciona.

Si solo desea devolver todas las filas que contienen un 1 , como sugiere la salida deseada, simplemente puede hacer

df.loc[(df == 1).any(axis=1)]

que vuelve

bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo 0 5.0 1.0 0 0 2 NA NA 1 5.0 2.1 0 1 4 0 0 2 6.0 NaN 0 NaN 1 0 1 5 6.8 6.8 1 0 5 0 0


Según la respuesta de @ EdChum, puede probar la siguiente solución:

df[df.columns[pd.Series(df.columns).str.contains("foo")]]

Esto será realmente útil en caso de que no todas las columnas que desea seleccionar comiencen con foo . Este método selecciona todas las columnas que contienen la subcadena foo y se puede colocar en cualquier punto del nombre de una columna.

En esencia, reemplacé .startswith() con .contains() .


Simplemente realice una comprensión de la lista para crear sus columnas:

In [28]: filter_col = [col for col in df if col.startswith(''foo'')] filter_col Out[28]: [''foo.aa'', ''foo.bars'', ''foo.fighters'', ''foo.fox'', ''foo.manchu''] In [29]: df[filter_col] Out[29]: foo.aa foo.bars foo.fighters foo.fox foo.manchu 0 1.0 0 0 2 NA 1 2.1 0 1 4 0 2 NaN 0 NaN 1 0 3 4.7 0 0 0 0 4 5.6 0 0 0 0 5 6.8 1 0 5 0

Otro método es crear una serie a partir de las columnas y utilizar el método str startswith :

In [33]: df[df.columns[pd.Series(df.columns).str.startswith(''foo'')]] Out[33]: foo.aa foo.bars foo.fighters foo.fox foo.manchu 0 1.0 0 0 2 NA 1 2.1 0 1 4 0 2 NaN 0 NaN 1 0 3 4.7 0 0 0 0 4 5.6 0 0 0 0 5 6.8 1 0 5 0

Para lograr lo que desea, debe agregar lo siguiente para filtrar los valores que no cumplan con sus criterios ==1 :

In [36]: df[df[df.columns[pd.Series(df.columns).str.startswith(''foo'')]]==1] Out[36]: bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo 0 NaN 1 NaN NaN NaN NaN NaN 1 NaN NaN NaN 1 NaN NaN NaN 2 NaN NaN NaN NaN 1 NaN NaN 3 NaN NaN NaN NaN NaN NaN NaN 4 NaN NaN NaN NaN NaN NaN NaN 5 NaN NaN 1 NaN NaN NaN NaN

EDITAR

OK después de ver lo que quieres, la respuesta complicada es esta:

In [72]: df.loc[df[df[df.columns[pd.Series(df.columns).str.startswith(''foo'')]] == 1].dropna(how=''all'', axis=0).index] Out[72]: bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo 0 5.0 1.0 0 0 2 NA NA 1 5.0 2.1 0 1 4 0 0 2 6.0 NaN 0 NaN 1 0 1 5 6.8 6.8 1 0 5 0 0