¿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:

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
Author: Community, 2013-03-05

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.

 55
Author: adibender,
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
 15
Author: Dinre,
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
 2
Author: maycca,
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.

 1
Author: Sam Firke,
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