Tengo un DataFrame de pandas y quiero eliminar filas de él donde la longitud de la cadena en una columna particular es mayor que 2.
Espero poder hacer esto (según esta respuesta ):
df[(len(df['column name']) < 2)]
pero acabo de recibir el error:
KeyError: u'no item named False'
¿Qué estoy haciendo mal?
(Nota: sé que puedo usar df.dropna()
para deshacerme de las filas que contienen alguna NaN
, pero no vi cómo eliminar filas en función de una expresión condicional).
df[[(len(x) < 2) for x in df['column name']]]
pero la tuya es mucho más agradable. ¡Gracias por tu ayuda!df[df['column name'].map(lambda x: str(x)!=".")]
pandas 0.23.4
Python 3.6.copy()
Agregaría un al final, en caso de que luego desee editar este marco de datos (por ejemplo, la asignación de nuevas columnas generaría la advertencia "Un valor está tratando de establecerse en una copia de un segmento de un Marco de datos"Para responder directamente al título original de esta pregunta "Cómo eliminar filas de un DataFrame de pandas basado en una expresión condicional" (lo que entiendo no es necesariamente el problema del OP pero podría ayudar a otros usuarios a encontrar esta pregunta) una forma de hacerlo es usar El método de caída :
df = df.drop(some labels)
df = df.drop(df[<some boolean condition>].index)
Ejemplo
Para eliminar todas las filas donde la columna 'puntuación' es <50:
df = df.drop(df[df.score < 50].index)
Versión en el lugar (como se señala en los comentarios)
df.drop(df[df.score < 50].index, inplace=True)
Condiciones múltiples
(ver Indización booleana )
Para eliminar todas las filas donde la columna 'puntuación' es <50 y> 20
df = df.drop(df[(df.score < 50) & (df.score > 20)].index)
fuente
reset_index()
). Descubrí esto de la manera difícil cuando se eliminaron muchas filas de mi marco de datos.test = df.drop(df[df['col1'].dtype == str].index)
pero recibo el errorKeyError: False
que también he intentadodf.drop(df[df.col1.dtype == str].index)
ydf.drop(df[type(df.cleaned_norm_email) == str].index)
parece que nada funciona. ¿Alguien puede aconsejar? ¡Gracias! @Usuariodf[(df.score < 50) & (df.score > 20)]
como parte de su respuesta. Si invierte estodf = df[(df.score >= 50) | (df.score <= 20)]
, obtendrá su respuesta mucho más rápido.Puede asignar el
DataFrame
a una versión filtrada de sí mismo:Esto es más rápido que
drop
:fuente
Expandiré la solución genérica de @ User para proporcionar una
drop
alternativa gratuita. Esto es para las personas que se dirigen aquí según el título de la pregunta (no el problema de OP)Digamos que desea eliminar todas las filas con valores negativos. Una solución de revestimiento es: -
Paso a paso Explicación: -
Generemos un marco de datos de distribución normal aleatorio de 5x5
Deje que la condición elimine negativos. Un df booleano que satisface la condición: -
Una serie booleana para todas las filas que satisfacen la condición Tenga en cuenta que si algún elemento de la fila falla la condición, la fila se marca como falsa
Finalmente, filtre las filas del marco de datos según la condición
Puede asignarlo de nuevo a df para eliminar realmente vs filtrar hecho anteriormente
df = df[(df > 0).all(axis=1)]
Esto se puede ampliar fácilmente para filtrar las filas que contienen NaN s (entradas no numéricas):
df = df[(~df.isnull()).all(axis=1)]
Esto también se puede simplificar para casos como: Eliminar todas las filas donde la columna E es negativa
Me gustaría terminar con algunas estadísticas de perfiles sobre por qué la
drop
solución de @ User es más lenta que la filtración basada en columnas sin procesar: -Una columna es básicamente una matriz,
Series
es decirNumPy
, puede indexarse sin costo alguno. Para las personas interesadas en cómo la organización de la memoria subyacente juega con la velocidad de ejecución, aquí hay un gran enlace para acelerar los pandas :fuente
En pandas, puede hacer
str.len
con su límite y usar el resultado booleano para filtrarlo.fuente
Si desea soltar filas de marco de datos sobre la base de alguna condición complicada en el valor de la columna, escribir eso de la manera que se muestra arriba puede ser complicado. Tengo la siguiente solución más simple que siempre funciona. Supongamos que desea colocar la columna con 'encabezado', así que primero obtenga esa columna en una lista.
ahora aplique alguna función en cada elemento de la lista y póngalo en una serie de panda:
en mi caso solo estaba tratando de obtener el número de tokens:
ahora agregue una columna adicional con la serie anterior en el marco de datos:
ahora podemos aplicar condiciones en la nueva columna como:
fuente