r - shinythemes - tags$div shiny
Crear un marco de datos de longitudes desiguales (5)
Si bien las columnas de marcos de datos deben tener las mismas filas numéricas, existe alguna forma de crear un marco de datos de longitudes desiguales. No estoy interesado en guardarlos como elementos separados de una lista porque a menudo tengo que enviar esta información a las personas como un archivo csv, y esto es más fácil como marco de datos.
x = c(rep("one",2))
y = c(rep("two",10))
z = c(rep("three",5))
cbind(x,y,z)
En el código anterior, la función cbind()
simplemente recicla las columnas más cortas para que todas tengan 10 elementos en cada columna. ¿Cómo puedo alterarlo solo para que las longitudes sean 2, 10 y 5?
He hecho esto en el pasado haciendo lo siguiente, pero es ineficiente.
df = data.frame(one=c(rep("one",2),rep("",8)),
two=c(rep("two",10)), three=c(rep("three",5), rep("",5)))
Esto no es posible. Lo más cerca que puede acercarse es llenar los espacios "vacíos" con el valor NA
.
Lo siento, no es exactamente lo que pediste, pero creo que puede haber otra manera de obtener lo que quieres.
Primero, si los vectores tienen diferentes longitudes, los datos no son realmente tabulares, ¿verdad? ¿Qué tal simplemente guardarlo en diferentes archivos CSV? También puede probar formatos ascii que permitan almacenar múltiples objetos ( json , XML ).
Si crees que los datos realmente son tabulares, podrías rellenar los NA:
> x = 1:5
> y = 1:12
> max.len = max(length(x), length(y))
> x = c(x, rep(NA, max.len - length(x)))
> y = c(y, rep(NA, max.len - length(y)))
> x
[1] 1 2 3 4 5 NA NA NA NA NA NA NA
> y
[1] 1 2 3 4 5 6 7 8 9 10 11 12
Si absolutamente debe hacer un data.frame
con columnas desiguales, podría subvertir el cheque, bajo su propio riesgo:
> x = 1:5
> y = 1:12
> df = list(x=x, y=y)
> attributes(df) = list(names = names(df),
row.names=1:max(length(x), length(y)), class=''data.frame'')
> df
x y
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 <NA> 6
7 <NA> 7
[ reached getOption("max.print") -- omitted 5 rows ]]
Warning message:
In format.data.frame(x, digits = digits, na.encode = FALSE) :
corrupt data frame: columns will be truncated or padded with NAs
Otro acercamiento al relleno:
na.pad <- function(x,len){
x[1:len]
}
makePaddedDataFrame <- function(l,...){
maxlen <- max(sapply(l,length))
data.frame(lapply(l,na.pad,len=maxlen),...)
}
x = c(rep("one",2))
y = c(rep("two",10))
z = c(rep("three",5))
makePaddedDataFrame(list(x=x,y=y,z=z))
La función na.pad()
explota el hecho de que R rellenará automáticamente un vector con NA si intentas indexar elementos no existentes.
makePaddedDataFrame()
solo encuentra el más largo y rellena el resto hasta una longitud correspondiente.
Para amplificar la respuesta de @ goodside, puedes hacer algo como
L <- list(x,y,z)
cfun <- function(L) {
pad.na <- function(x,len) {
c(x,rep(NA,len-length(x)))
}
maxlen <- max(sapply(L,length))
do.call(data.frame,lapply(L,pad.na,len=maxlen))
}
(sin probar).
Problema similar:
coin <- c("Head", "Tail")
toss <- sample(coin, 50, replace=TRUE)
categorize <- function(x,len){
count_heads <- 0
count_tails <- 0
tails <- as.character()
heads <- as.character()
for(i in 1:len){
if(x[i] == "Head"){
heads <- c(heads,x[i])
count_heads <- count_heads + 1
}else {
tails <- c(tails,x[i])
count_tails <- count_tails + 1
}
}
if(count_heads > count_tails){
head <- heads
tail <- c(tails, rep(NA, (count_heads-count_tails)))
} else {
head <- c(heads, rep(NA,(count_tails-count_heads)))
tail <- tails
}
data.frame(cbind("Heads"=head, "Tails"=tail))
}
categorizar (tirar, 50)
Salida: Después del sorteo de la moneda habrá 31 Head y 19 Tail. Luego, el resto de la cola se llenará con NA para crear un marco de datos.