para - manual de programacion android pdf
R: perder nombres de columna al agregar filas a un marco de datos vacío (8)
En lugar de construir data.frame con numeric numeric(0)
, utilizo as.numeric(0)
.
a<-data.frame(one=as.numeric(0), two=as.numeric(0))
Esto crea una fila inicial adicional
a
# one two
#1 0 0
Enlaza las filas adicionales
a<-rbind(a,c(5,6))
a
# one two
#1 0 0
#2 5 6
Luego use indexación negativa para eliminar la primera fila (falsa)
a<-a[-1,]
a
# one two
#2 5 6
Nota: estropea el índice (extremo izquierdo). No he descubierto cómo prevenir eso (¿alguien más?), Pero la mayoría de las veces probablemente no importe.
Estoy comenzando con R y encontré un comportamiento extraño: al insertar la primera fila en un marco de datos vacío, los nombres originales de las columnas se pierden.
ejemplo:
a<-data.frame(one = numeric(0), two = numeric(0))
a
#[1] one two
#<0 rows> (or 0-length row.names)
names(a)
#[1] "one" "two"
a<-rbind(a, c(5,6))
a
# X5 X6
#1 5 6
names(a)
#[1] "X5" "X6"
Como puede ver, los nombres de columna uno y dos fueron reemplazados por X5 y X6 .
¿Podría alguien decirme por qué sucede esto y hay una forma correcta de hacerlo sin perder los nombres de las columnas?
Una solución de escopeta sería guardar los nombres en un vector auxiliar y luego agregarlos cuando termine de trabajar en el marco de datos.
Gracias
Contexto:
Creé una función que reúne algunos datos y los agrega como una nueva fila a un marco de datos recibido como parámetro. Creo el marco de datos, repito a través de mis fuentes de datos, pasando el data.frame a cada llamada de función para completar con sus resultados.
FWIW, un diseño alternativo podría tener sus funciones construyendo vectores para las dos columnas, en lugar de enlazar a un marco de datos:
ones <- c()
twos <- c()
Modifica los vectores en tus funciones:
ones <- append(ones, 5)
twos <- append(twos, 6)
Repita según sea necesario, luego cree su data.frame de una vez:
a <- data.frame(one=ones, two=twos)
La solución sería:
a <- rbind(a, data.frame(one = 5, two = 6))
?rbind
establece que la fusión de objetos exige nombres coincidentes:
A continuación, toma las clases de las columnas del primer marco de datos y las coincide con las columnas por nombre (en lugar de por posición)
Las páginas de ayuda de rbind
especifican que:
Para ''cbind'' (''rbind''), los vectores de longitud cero (incluyendo ''NULL'') se ignoran a menos que el resultado tenga cero filas (columnas), para la compatibilidad S. (Las matrices de extensión cero no ocurren en S3 y no se ignoran en R.)
Entonces, de hecho, a
es ignorado en su instrucción de rbind
. No totalmente ignorado, parece, porque como es un marco de datos, la función rbind
se llama rbind.data.frame
:
rbind.data.frame(c(5,6))
# X5 X6
#1 5 6
Quizás una forma de insertar la fila podría ser:
a[nrow(a)+1,] <- c(5,6)
a
# one two
#1 5 6
Pero puede haber una mejor manera de hacerlo dependiendo de su código.
Puedes hacerlo:
dar una fila al marco de datos inicial
df=data.frame(matrix(nrow=1,ncol=length(newrow))
agrega tu nueva fila y saca el NAS
newdf=na.omit(rbind(newrow,df))
pero ten cuidado con que tu newrow no tenga NA o se borrará también.
Saludos Agus
Una forma de hacer que esto funcione de forma genérica y con la menor cantidad de volver a escribir los nombres de las columnas es la siguiente. Este método no requiere hackear NA o 0.
rs <- data.frame(i=numeric(), square=numeric(), cube=numeric())
for (i in 1:4) {
calc <- c(i, i^2, i^3)
# append calc to rs
names(calc) <- names(rs)
rs <- rbind(rs, as.list(calc))
}
rs tendrá los nombres correctos
> rs
i square cube
1 1 1 1
2 2 4 8
3 3 9 27
4 4 16 64
>
Otra forma de hacerlo más limpiamente es usar data.table:
> df <- data.frame(a=numeric(0), b=numeric(0))
> rbind(df, list(1,2)) # column names are messed up
> X1 X2
> 1 1 2
> df <- data.table(a=numeric(0), b=numeric(0))
> rbind(df, list(1,2)) # column names are preserved
a b
1: 1 2
Tenga en cuenta que un data.table también es un data.frame.
> class(df)
"data.table" "data.frame"
Utilizo la siguiente solución para agregar una fila a un marco de datos vacío:
d_dataset <-
data.frame(
variable = character(),
before = numeric(),
after = numeric(),
stringsAsFactors = FALSE)
d_dataset <-
rbind(
d_dataset,
data.frame(
variable = "test",
before = 9,
after = 12,
stringsAsFactors = FALSE))
print(d_dataset)
variable before after
1 test 9 12
HTH.
Saludos cordiales
Georg
casi se estaba rindiendo a este problema.
1) crear un marco de datos con stringsAsFactor
establecido en FALSE
o ejecutar directamente en el siguiente problema
2) no use rbind
, no rbind
idea de por qué está estropeando los nombres de las columnas. simplemente hazlo de esta manera:
df[nrow(df)+1,] <- c("d","gsgsgd",4)
df <- data.frame(a = character(0), b=character(0), c=numeric(0))
df[nrow(df)+1,] <- c("d","gsgsgd",4)
#Warnmeldungen:
#1: In `[<-.factor`(`*tmp*`, iseq, value = "d") :
# invalid factor level, NAs generated
#2: In `[<-.factor`(`*tmp*`, iseq, value = "gsgsgd") :
# invalid factor level, NAs generated
df <- data.frame(a = character(0), b=character(0), c=numeric(0), stringsAsFactors=F)
df[nrow(df)+1,] <- c("d","gsgsgd",4)
df
# a b c
#1 d gsgsgd 4