2012-05-01 12 views
17

para empezar: He buscado durante horas en este problema ahora - por lo que si la respuesta debería ser trivial, por favor, perdóname ...¿Cómo suprimir una fila de una hoja.de.datos sin perder los atributos

Lo que Lo que quiero hacer es eliminar una fila (n. ° 101) de un data.frame. Contiene datos de prueba y no debe aparecer en mis análisis. Mi problema es: cada vez que subconjunto desde el data.frame, los atributos (especialmente los comentarios) se pierden.

str(x) 
# x has comments for each variable 
x <- x[1:100,] 
str(x) 
# now x has lost all comments 

Está bien documentado que los subconjuntos de todos los atributos caerá - hasta ahora, es perfectamente clara. El manual (por ejemplo http://stat.ethz.ch/R-manual/R-devel/library/base/html/Extract.data.frame.html) incluso sugiere una manera de preservar los atributos:

## keeping special attributes: use a class with a 
## "as.data.frame" and "[" method: 


as.data.frame.avector <- as.data.frame.vector 

`[.avector` <- function(x,i,...) { 
    r <- NextMethod("[") 
    mostattributes(r) <- attributes(x) 
    r 
} 

d <- data.frame(i= 0:7, f= gl(2,4), 
       u= structure(11:18, unit = "kg", class="avector")) 
str(d[2:4, -1]) # 'u' keeps its "unit" 

todavía no estoy tan lejos en R entender qué es exactamente lo que ocurre aquí. Sin embargo, simplemente ejecutar estas líneas (excepto las últimas tres) no cambia el comportamiento de mi subconjunto. Usar el subconjunto de comandos() con un vector apropiado (100 veces VERDADERO + 1 FALSO) me da el mismo resultado. Y simplemente almacenar los atributos en una variable y restaurarla después del subconjunto, tampoco funciona.

# Does not work... 
tmp <- attributes(x) 
x <- x[1:100,] 
attributes(x) <- tmp 

Por supuesto, podría escribir todos los comentarios a un vector (var => Comentario), subconjunto y escribir de nuevo utilizando un bucle - pero eso no parece una solución bien fundada. Y estoy bastante seguro de que encontraré conjuntos de datos con otros atributos relevantes en futuros análisis.

Así que aquí es donde mis esfuerzos en stackoverflow, Google y el poder del cerebro se atascaron. Apreciaría mucho si alguien pudiera ayudarme con una pista. ¡Gracias!

+1

También se podría establecer la fila NA: x [101], <- NA. Pero esta es solo otra pseudo-solución que no resuelve el problema. – BurninLeo

Respuesta

10

Si le entiendo correctamente, tiene algunos datos en un data.frame, y las columnas del data.frame tienen comentarios asociados. Tal vez algo como lo siguiente?

set.seed(1) 

mydf<-data.frame(aa=rpois(100,4),bb=sample(LETTERS[1:5], 
    100,replace=TRUE)) 

comment(mydf$aa)<-"Don't drop me!" 
comment(mydf$bb)<-"Me either!" 

Así que esto le daría algo así como

> str(mydf) 
'data.frame': 100 obs. of 2 variables: 
$ aa: atomic 3 3 4 7 2 7 7 5 5 1 ... 
    ..- attr(*, "comment")= chr "Don't drop me!" 
$ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2 2 5 4 2 1 3 5 3 ... 
    ..- attr(*, "comment")= chr "Me either!" 

Y cuando subconjunto de esto, los comentarios se dejan caer:

> str(mydf[1:2,]) # comment dropped. 
'data.frame': 2 obs. of 2 variables: 
$ aa: num 3 3 
$ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2 

Para conservar los comentarios, defina la función [.avector, como lo hizo arriba (de la documentación) y luego agrega los atributos de clase apropiados a cada una de las columnas en su data.frame (EDIT: para mantener los niveles de factor de bb, añadir "factor" a la clase de bb):.

mydf$aa<-structure(mydf$aa, class="avector") 
mydf$bb<-structure(mydf$bb, class=c("avector","factor")) 

Para que los comentarios se conservan:

> str(mydf[1:2,]) 
'data.frame': 2 obs. of 2 variables: 
$ aa:Class 'avector' atomic [1:2] 3 3 
    .. ..- attr(*, "comment")= chr "Don't drop me!" 
$ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2 
    ..- attr(*, "comment")= chr "Me either!" 

EDIT:

Si hay muchas columnas en su data.frame que tienen atributos que desea conservar, puede usar lapply (EDITED para incluir clase columna original):

mydf2 <- data.frame(lapply(mydf, function(x) { 
    structure(x, class = c("avector", class(x))) 
})) 

Sin embargo, esta cae comentarios asociados a los datos.enmarcarse (como comment(mydf)<-"I'm a data.frame"), por lo que si usted tiene cualquiera, asignarles a la nueva hoja.de.datos:

comment(mydf2)<-comment(mydf) 

Y entonces usted tiene

> str(mydf2[1:2,]) 
'data.frame': 2 obs. of 2 variables: 
$ aa:Classes 'avector', 'numeric' atomic [1:2] 3 3 
    .. ..- attr(*, "comment")= chr "Don't drop me!" 
$ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2 
    ..- attr(*, "comment")= chr "Me either!" 
- attr(*, "comment")= chr "I'm a data.frame" 
+0

¡Hola BenBarnes! Gracias por esta respuesta. Dadas tus explicaciones y el ejemplo del código, la función del manual finalmente tiene sentido para mí. Parece que tengo que aprender un poco sobre las clases en R. – BurninLeo

+0

Estoy tratando de usar este enfoque. Sin embargo, esta operación 'transformColumn <- as.numeric (unlist (data [" Registration Time "]))' da como resultado el siguiente mensaje de error: '" Error en \ '[.data.frame \' (data, "Registration time "): \ n columnas indefinidas seleccionadas \ n Llamadas: lapply ... do.call -> -> unlist -> [-> [.data.frame'" (He añadido '\ n' caracteres para la legibilidad). ¿Qué estoy haciendo mal? –

+0

Perdón por la confusión, creo que funciona. Bueno ..., hasta cierto punto, donde probablemente rompo cosas en mi código. Informará, cuando descubra esto. –

4

Para aquellos que buscan el "todo- en "solución basada en la explicación de BenBarnes: aquí está.

(dar al su "arriba" a la entrada de Ben Barnes si esto funciona para usted)

# Define the avector-subselection method (from the manual) 
as.data.frame.avector <- as.data.frame.vector 
`[.avector` <- function(x,i,...) { 
    r <- NextMethod("[") 
    mostattributes(r) <- attributes(x) 
    r 
} 

# Assign each column in the data.frame the (additional) class avector 
# Note that this will "lose" the data.frame's attributes, therefore write to a copy 
df2 <- data.frame(
    lapply(df, function(x) { 
    structure(x, class = c("avector", class(x))) 
    }) 
) 

# Finally copy the attribute for the original data.frame if necessary 
mostattributes(df2) <- attributes(df) 

# Now subselects work without losing attributes :) 
df2 <- df2[1:100,] 
str(df2) 

Lo bueno: Cuando se conecta a la clase a todos los elementos de la hoja.de.datos vez, los subselects Nunca de nuevo molesta los atributos.

bien - a veces me siento aturdido lo complicado que es hacer las operaciones más simples en R. Pero seguramente no aprender acerca de la función "clases" si se acaban de marcar y eliminado el caso en SPSS;)

+0

He intentado con esta solución (http: // stackoverflow.com/questions/23991060/loss-of-attributes-despite-attempts-to-preserve-them), pero uno de los problemas que he tenido es que cada ejecuciones posteriores del código agrega la clase 'avector' al objeto. Entonces, termino con múltiples atributos de clase 'avector' que son redundantes. Además, el parámetro 'i' en la definición de función del selector no se utiliza y, por lo tanto, en mi humilde opinión, se puede eliminar. –

+0

Utilizo este código en mi secuencia de comandos de lectura/importación y guardo el conjunto de datos a continuación. Entonces el código solo se ejecuta una vez, por marco de datos. – BurninLeo

+0

Ya veo. Ya he descifrado la mayoría de los problemas con la pregunta mencionada. Pero, independientemente, gracias por la respuesta. –

1

Esto se soluciona con el paquete sticky. (Divulgación completa: soy el autor del paquete.) Aplique el sticky() a sus vectores y los atributos se conservan mediante operaciones de subconjuntos. Por ejemplo:

> df <- data.frame( 
+ sticky = sticky(structure(1:5, comment="sticky attribute")), 
+ nonstick = structure(letters[1:5], comment="non-sticky attribute") 
+) 
> 
> comment(df[1:3, "nonstick"]) 
NULL 
> comment(df[1:3, "sticky"]) 
[1] "sticky attribute" 

Esto funciona para cualquier atributo y no sólo comment.

Ver el paquete sticky para más detalles:

+1

Es bueno saber que hay tal paquete. ¿De verdad tiene que ejecutar 'sticky()' en cada variable para que sus atributos sean pegajosos? Sin intención de ofender, pero la solución de @BenBarnes, que también conserva los atributos, se encarga de todo el marco de datos en un solo paso (que es lo que generalmente necesito). – BurninLeo

+1

Me complace hacer esa adición a los paquetes adhesivos. Consulte: https://github.com/decisionpatterns/sticky/issues/1 – ctbrown

+0

@ctbrown, parece que resolvió ese problema. ¿Puedes actualizar la solución anterior para reflejar eso? –

Cuestiones relacionadas