Filtrar filas: la máscara lógica
Para filtrar un data frame en R, pon una condición en la posición de filas de los corchetes: df[condición, ]. La condición se evalúa a un vector de TRUE/FALSE, uno por fila, y R conserva las filas TRUE:
Lee scores[scores$score > 80, ] de dentro hacia fuera: scores$score > 80 produce TRUE FALSE TRUE TRUE FALSE, y los corchetes conservan las filas 1, 3 y 4. La coma final no es opcional. Los corchetes en un data frame reciben [filas, columnas]; dejar vacío el hueco de columnas significa "todas las columnas". Olvida la coma y estarás indexando columnas en su lugar - uno de los errores de principiante más comunes en R.
Fíjate en que los números de fila impresos son 1 3 4, no 1 2 3: el filtrado conserva las etiquetas de fila originales. Inofensivo, pero sorprende a la gente.
Condiciones múltiples: & y | (no &&)
Combina condiciones con & (Y) y | (O). Cada condición lleva su propia comparación completa:
La trampa: R también tiene && y ||, y no son intercambiables con & y | aquí. Las formas dobles funcionan con valores individuales (existen para las condiciones de if); ante columnas completas, el R moderno (4.3+) se detiene con un error como 'length = 5' in coercion to 'logical(1)', y el R más antiguo comparaba en silencio solo la primera fila - posiblemente peor. Dentro de los corchetes, siempre el & y el | simples. La documentación de operadores cubre la distinción al completo.
%in%: comparar contra un conjunto de valores
Cuando una columna debe coincidir con cualquiera de varios valores, no encadenes == con | - usa %in%:
x %in% set devuelve TRUE allí donde x es uno de los valores de set. Se lee mejor que status == "pending" | status == "shipped", escala a cualquier número de valores y se niega limpiamente: !(orders$status %in% c("refunded")).
Seleccionar columnas
El hueco de columnas de los corchetes acepta nombres o posiciones:
Dos apuntes. Seleccionar por nombre sobrevive a la reordenación de columnas; seleccionar por posición (scores[, c(1, 3)]) se rompe el día que alguien inserta una columna. Y pedir una sola columna devuelve un vector plano, no un data frame - por eso el segundo print() muestra 91 88 sin tabla alrededor. Cuando necesites conservar la forma de data frame, añade drop = FALSE: scores[, "score", drop = FALSE].
subset(): la línea única amigable de base
R base incluye un envoltorio que hace filas y columnas en una sola llamada legible - sin $, sin contabilidad de comas:
Dentro de subset() escribes nombres de columna a secas (score, no scores$score): los evalúa contra el data frame. Esto se llama evaluación no estándar, y viene con una advertencia documentada: resuelve los nombres en tiempo de ejecución de maneras que se comportan mal dentro de tus propias funciones (una variable llamada score en tu función puede quedar eclipsada por una columna llamada score). La regla general, directa de ?subset: estupendo de forma interactiva, evítalo al programar - usa indexación con corchetes ahí.
La trampa de NA
Una comparación contra NA produce NA, no FALSE - y el filtrado con corchetes conserva las filas con máscara NA como filas llenas de NA:
El primer resultado contiene una fila basura de NAs porque la condición de la fila 2 no fue ni TRUE ni FALSE. La solución es exigir !is.na() explícitamente. Tanto subset() como el filter() de dplyr descartan silenciosamente las filas con condición NA - cómodo, pero conviene saber que está ocurriendo. La documentación de valores faltantes explica por qué NA se propaga así.
La forma dplyr: filter() y select()
El paquete dplyr divide el trabajo en dos verbos - filter() para filas, select() para columnas - con nombres de columna a secas y sin repetir df$ (estático; el sandbox solo ejecuta R base):
library(dplyr)
scores |> filter(score > 80)
scores |> filter(score > 80, team == "red") # comma = AND
scores |> filter(status %in% c("pending", "shipped"))
scores |> select(name, score)
scores |> filter(team == "red") |> select(name, score)
filter() descarta automáticamente las filas con condición NA y siempre devuelve un data frame (nunca un vector suelto), lo que elimina las dos trampas de base de arriba. El precio es una dependencia de paquete y las mismas advertencias de evaluación no estándar que subset() - consulta la introducción a dplyr para el recorrido completo de verbos.
Lo que te llevas
df[condición, ]es el idioma fundamental - y la coma es obligatoria.- Combina condiciones con
&y|simples;&&da error con vectores. %in%supera a los==encadenados para comparar contra un conjunto de valores.- Selecciona columnas por nombre, y recuerda que las columnas individuales se degradan a vectores salvo con
drop = FALSE. subset()es la agradable línea única interactiva; los corchetes son la programable.- Las comparaciones con
NAproducen filas fantasma en los corchetes - protégete con!is.na().
A continuación: añadir y transformar columnas - df$new <- ..., ifelse() y el mutate() de dplyr.
Preguntas frecuentes
¿Cómo filtro las filas de un data frame en R?
Pon una condición lógica en la posición de filas de los corchetes: df[df$score > 80, ]. La condición produce un vector de TRUE/FALSE, y R conserva las filas TRUE. La coma importa: separa el filtro de filas del filtro (vacío) de columnas. subset(df, score > 80) hace lo mismo escribiendo menos.
¿Cómo filtro con varias condiciones en R?
Combina condiciones con & (Y) y | (O): df[df$score > 80 & df$team == "red", ]. Usa el & simple, no && - la forma doble funciona solo con valores individuales y da error con vectores en las versiones modernas de R.
¿Cuál es la diferencia entre subset() y el filtrado con corchetes en R?
Conservan las mismas filas, con dos diferencias: subset() descarta silenciosamente las filas donde la condición es NA (los corchetes las conservan como filas llenas de NA), y subset() usa evaluación no estándar: escribes nombres de columna a secas, lo cual es cómodo de forma interactiva pero poco fiable dentro de tus propias funciones.
¿Cómo filtro las filas donde una columna coincide con una lista de valores?
Usa %in%: df[df$team %in% c("red", "blue"), ] conserva las filas cuyo team es cualquiera de los valores listados. Sustituye una cadena de comparaciones == unidas con |, y a diferencia de ==, nunca devuelve NA.