¿Cómo puedo subconjunto de filas en un marco de datos en R, basado en un vector de valores?
Tengo dos conjuntos de datos que se supone que son del mismo tamaño, pero no lo son. Necesito recortar los valores de A que no están en B y viceversa con el fin de eliminar el ruido de un gráfico que va en un informe. (No se preocupe, ¡estos datos no se eliminan permanentemente!)
He leído lo siguiente:
- Selección de columnas en el marco de datos R basado en aquellos * no* en un vector
- http://www.ats.ucla.edu/stat/r/faq/subset_R.htm
- Cómo combinar múltiples condiciones para subconjunto de un marco de datos utilizando "O"?
Pero todavía no soy capaz de hacer que esto funcione bien. Aquí está mi código:
bg2011missingFromBeg <- setdiff(x=eg2011$ID, y=bg2011$ID)
#attempt 1
eg2011cleaned <- subset(eg2011, ID != bg2011missingFromBeg)
#attempt 2
eg2011cleaned <- eg2011[!eg2011$ID %in% bg2011missingFromBeg]
El primer intento simplemente elimina el primer valor en el vector setdiff resultante. El segundo intento produce un error difícil de manejar:
Error in `[.data.frame`(eg2012, !eg2012$ID %in% bg2012missingFromBeg)
: undefined columns selected
4 answers
Esto te dará lo que quieres:
eg2011cleaned <- eg2011[!eg2011$ID %in% bg2011missingFromBeg, ]
El error en tu segundo intento es porque olvidaste el ,
En general, por conveniencia, la especificación object[index]
subconjuntos columnas para un 2d object
. Si desea subconjuntos de filas y mantener todas las columnas, debe usar la especificación
object[index_rows, index_columns]
, mientras que index_cols
se puede dejar en blanco, que utilizará todas las columnas por defecto.
Sin embargo, todavía necesita incluir el ,
para indicar que desea obtener un subconjunto de filas en lugar de un subconjunto de columnas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-06 09:32:23
Si realmente solo desea subconjuntar cada marco de datos por un índice que existe en ambos marcos de datos, puede hacer esto con la función' match', así:
data_A[match(data_B$index, data_A$index, nomatch=0),]
data_B[match(data_A$index, data_B$index, nomatch=0),]
Esto es, sin embargo, lo mismo que:
data_A[data_A$index %in% data_B$index,]
data_B[data_B$index %in% data_A$index,]
Aquí está una demostración:
# Set seed for reproducibility.
set.seed(1)
# Create two sample data sets.
data_A <- data.frame(index=sample(1:200, 90, rep=FALSE), value=runif(90))
data_B <- data.frame(index=sample(1:200, 120, rep=FALSE), value=runif(120))
# Subset data of each data frame by the index in the other.
t_A <- data_A[match(data_B$index, data_A$index, nomatch=0),]
t_B <- data_B[match(data_A$index, data_B$index, nomatch=0),]
# Make sure they match.
data.frame(t_A[order(t_A$index),], t_B[order(t_B$index),])[1:20,]
# index value index.1 value.1
# 27 3 0.7155661 3 0.65887761
# 10 12 0.6049333 12 0.14362694
# 88 14 0.7410786 14 0.42021589
# 56 15 0.4525708 15 0.78101754
# 38 18 0.2075451 18 0.70277874
# 24 23 0.4314737 23 0.78218212
# 34 32 0.1734423 32 0.85508236
# 22 38 0.7317925 38 0.56426384
# 84 39 0.3913593 39 0.09485786
# 5 40 0.7789147 40 0.31248966
# 74 43 0.7799849 43 0.10910096
# 71 45 0.2847905 45 0.26787813
# 57 46 0.1751268 46 0.17719454
# 25 48 0.1482116 48 0.99607737
# 81 53 0.6304141 53 0.26721208
# 60 58 0.8645449 58 0.96920881
# 30 59 0.6401010 59 0.67371223
# 75 61 0.8806190 61 0.69882454
# 63 64 0.3287773 64 0.36918946
# 19 70 0.9240745 70 0.11350771
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-05 15:48:52
Really human comprehensible ejemplo (ya que esta es la primera vez que estoy usando %in%), cómo comparar dos marcos de datos y mantener solo filas que contengan los valores iguales en una columna específica:
# Set seed for reproducibility.
set.seed(1)
# Create two sample data frames.
data_A <- data.frame(id=c(1,2,3), value=c(1,2,3))
data_B <- data.frame(id=c(1,2,3,4), value=c(5,6,7,8))
# compare data frames by specific columns and keep only
# the rows with equal values
data_A[data_A$id %in% data_B$id,] # will keep data in data_A
data_B[data_B$id %in% data_A$id,] # will keep data in data_b
Resultados:
> data_A[data_A$id %in% data_B$id,]
id value
1 1 1
2 2 2
3 3 3
> data_B[data_B$id %in% data_A$id,]
id value
1 1 5
2 2 6
3 3 7
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-13 20:56:31
Según los comentarios de la publicación original, las fusiones / uniones son adecuadas para este problema. En particular, un inner join devolverá solo los valores que están presentes en ambos dataframes, haciendo innecesaria la instrucciónsetdiff
.
Usando los datos del ejemplo de Dinre:
En base R:
cleanedA <- merge(data_A, data_B[, "index"], by = 1, sort = FALSE)
cleanedB <- merge(data_B, data_A[, "index"], by = 1, sort = FALSE)
Usando el paquete dplyr:
library(dplyr)
cleanedA <- inner_join(data_A, data_B %>% select(index))
cleanedB <- inner_join(data_B, data_A %>% select(index))
Para mantener los datos como dos tablas separadas, cada una conteniendo solo sus propias variables, esto subconjuntos los no deseados tabla a solo su variable índice antes de unirse. A continuación, no se añaden nuevas variables a la tabla resultante.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-02 13:40:57