2013-09-29 17 views
11

Proszę mi wybaczyć, jeśli przegapię odpowiedź na tak proste pytanie.cbind: czy istnieje sposób na ustawienie brakujących wartości na NA?

Chcę użyć cbind() do wiązania dwóch kolumn. Jednym z nich jest jeden wpis o krótszej długości.

Czy mogę podać R, aby podać brakującą wartość NA?

Dokumentacja dotyczy argumentu deparse.level, ale nie wydaje mi się to moim rozwiązaniem.

Co więcej, jeśli mogę być tak odważny, czy istnieje również szybki sposób na dodanie krótszej kolumny z NA?

Odpowiedz

7

Spróbuj tego:

x <- c(1:5) 
y <- c(4:1) 
length(y) = length(x) 
cbind(x,y) 
    x y 
[1,] 1 4 
[2,] 2 3 
[3,] 3 2 
[4,] 4 1 
[5,] 5 NA 

czy to:

x <- c(4:1) 
y <- c(1:5) 
length(x) = length(y) 
cbind(x,y) 
     x y 
[1,] 4 1 
[2,] 3 2 
[3,] 2 3 
[4,] 1 4 
[5,] NA 5 

myślę, że to będzie coś podobnego do tego, co sugeruje Dwin i działa niezależnie od wektor jest krótszy:

x <- c(4:1) 
y <- c(1:5) 

lengths <- max(c(length(x), length(y))) 
length(x) <- lengths 
length(y) <- lengths 
cbind(x,y) 

Powyższy kod można również skondensować na:

x <- c(4:1) 
y <- c(1:5) 
length(x) <- length(y) <- max(c(length(x), length(y))) 
cbind(x,y) 

EDIT

Oto co wymyśliłem, aby odpowiedzieć na pytanie:

„Ponadto, jeśli mogę być tak śmiały, będzie tam również szybki sposób poprzedzić krótszą kolumnę NA użytkownika ? "

wstawiony do pierwotnego postu przez Matt O'Brien.

x <- c(4:1) 
y <- c(1:5) 

first <- 1 # 1 means add NA to top of shorter vector 
      # 0 means add NA to bottom of shorter vector 

if(length(x)<length(y)) { 
    if(first==1) x = c(rep(NA, length(y)-length(x)),x);y=y 
    if(first==0) x = c(x,rep(NA, length(y)-length(x)));y=y 
} 

if(length(y)<length(x)) { 
    if(first==1) y = c(rep(NA, length(x)-length(y)),y);x=x 
    if(first==0) y = c(y,rep(NA, length(x)-length(y)));x=x 
} 

cbind(x,y) 

#  x y 
# [1,] NA 1 
# [2,] 4 2 
# [3,] 3 3 
# [4,] 2 4 
# [5,] 1 5 

Oto funkcja:

x <- c(4:1) 
y <- c(1:5) 

first <- 1 # 1 means add NA to top of shorter vector 
      # 0 means add NA to bottom of shorter vector 

my.cbind <- function(x,y,first) { 

    if(length(x)<length(y)) { 
    if(first==1) x = c(rep(NA, length(y)-length(x)),x);y=y 
    if(first==0) x = c(x,rep(NA, length(y)-length(x)));y=y 
    } 

    if(length(y)<length(x)) { 
    if(first==1) y = c(rep(NA, length(x)-length(y)),y);x=x 
    if(first==0) y = c(y,rep(NA, length(x)-length(y)));x=x 
    } 

    return(cbind(x,y)) 

} 

my.cbind(x,y,first) 

my.cbind(c(1:5),c(4:1),1) 
my.cbind(c(1:5),c(4:1),0) 
my.cbind(c(1:4),c(5:1),1) 
my.cbind(c(1:4),c(5:1),0) 
my.cbind(c(1:5),c(5:1),1) 
my.cbind(c(1:5),c(5:1),0) 

Ta wersja pozwala na cbind dwa wektory różnych trybach:

x <- c(4:1) 
y <- letters[1:5] 

first <- 1 # 1 means add NA to top of shorter vector 
      # 0 means add NA to bottom of shorter vector 

my.cbind <- function(x,y,first) { 

    if(length(x)<length(y)) { 
    if(first==1) x = c(rep(NA, length(y)-length(x)),x);y=y 
    if(first==0) x = c(x,rep(NA, length(y)-length(x)));y=y 
    } 

    if(length(y)<length(x)) { 
    if(first==1) y = c(rep(NA, length(x)-length(y)),y);x=x 
    if(first==0) y = c(y,rep(NA, length(x)-length(y)));x=x 
    } 

    x <- as.data.frame(x) 
    y <- as.data.frame(y) 

    return(data.frame(x,y)) 

} 

my.cbind(x,y,first) 

# x y 
# 1 NA a 
# 2 4 b 
# 3 3 c 
# 4 2 d 
# 5 1 e 

my.cbind(c(1:5),letters[1:4],1) 
my.cbind(c(1:5),letters[1:4],0) 
my.cbind(c(1:4),letters[1:5],1) 
my.cbind(c(1:4),letters[1:5],0) 
my.cbind(c(1:5),letters[1:5],1) 
my.cbind(c(1:5),letters[1:5],0) 
+1

To zadziała tylko wtedy, gdy y jest krótszy niż x. –

+0

@DWin Nie możesz po prostu zmienić kolejności i użyć 'length (x) = length (y)' jeśli 'x' było krótsze? –

+2

Oczywiście, ale powinieneś użyć testu, a następnie wykonać poprawną akcję. –

4

Jakiś czas temu miałem ułożyła funkcja o nazwie Cbind że miał robić takie rzeczy. W obecnej formie powinien być w stanie obsłużyć wektory, data.frame s, a macierze jako dane wejściowe.

Na razie funkcja jest tutaj: https://gist.github.com/mrdwab/6789277

Oto jak można by użyć funkcji:

x <- 1:5 
y <- letters[1:4] 
z <- matrix(1:4, ncol = 2, dimnames = list(NULL, c("a", "b"))) 
Cbind(x, y, z) 
# x y z_a z_b 
# 1 1 a 1 3 
# 2 2 b 2 4 
# 3 3 c NA NA 
# 4 4 d NA NA 
# 5 5 <NA> NA NA 
Cbind(x, y, z, first = FALSE) 
# x y z_a z_b 
# 1 1 <NA> NA NA 
# 2 2 a NA NA 
# 3 3 b NA NA 
# 4 4 c 1 3 
# 5 5 d 2 4 

The dwa trzy funkcje są wymagane padNA, dotnames i Cbind, które są zdefiniowane w następujący sposób:

padNA <- function (mydata, rowsneeded, first = TRUE) { 
## Pads vectors, data.frames, or matrices with NA 
    temp1 = colnames(mydata) 
    rowsneeded = rowsneeded - nrow(mydata) 
    temp2 = setNames(
    data.frame(matrix(rep(NA, length(temp1) * rowsneeded), 
         ncol = length(temp1))), temp1) 
    if (isTRUE(first)) rbind(mydata, temp2) 
    else rbind(temp2, mydata) 
} 

dotnames <- function(...) { 
## Gets the names of the objects passed through ... 
    vnames <- as.list(substitute(list(...)))[-1L] 
    vnames <- unlist(lapply(vnames,deparse), FALSE, FALSE) 
    vnames 
} 

Cbind <- function(..., first = TRUE) { 
## cbinds vectors, data.frames, and matrices together 
    Names <- dotnames(...) 
    datalist <- setNames(list(...), Names) 
    nrows <- max(sapply(datalist, function(x) 
    ifelse(is.null(dim(x)), length(x), nrow(x)))) 
    datalist <- lapply(seq_along(datalist), function(x) { 
    z <- datalist[[x]] 
    if (is.null(dim(z))) { 
     z <- setNames(data.frame(z), Names[x]) 
    } else { 
     if (is.null(colnames(z))) { 
     colnames(z) <- paste(Names[x], sequence(ncol(z)), sep = "_") 
     } else { 
     colnames(z) <- paste(Names[x], colnames(z), sep = "_") 
     } 
    } 
    padNA(z, rowsneeded = nrows, first = first) 
    }) 
    do.call(cbind, datalist) 
} 

Po części przestałem działać na tej funkcji, ponieważ pakiet gdata ma już funkcję o nazwie cbindX, która obsługuje cbind i data.frame s oraz macierze z różnymi numerami wierszy. Nie będzie działać bezpośrednio na wektorach, więc najpierw musisz przekonwertować je na data.frame.

library(gdata) 
cbindX(data.frame(x), data.frame(y), z) 
# x y a b 
# 1 1 a 1 3 
# 2 2 b 2 4 
# 3 3 c NA NA 
# 4 4 d NA NA 
# 5 5 <NA> NA NA 
+0

+1 za wzmiankę o 'cbindX' - działa bardzo dobrze. Oto [kod] (https://github.com/cran/gdata/blob/master/R/cbindX.R) –

Powiązane problemy