2013-09-29 1 views
11

Bitte vergib mir, wenn ich eine Antwort auf solch eine einfache Frage verpasst habe.cbind: Gibt es eine Möglichkeit, fehlende Werte auf NA zu setzen?

Ich möchte cbind() verwenden, um zwei Spalten zu binden. Einer von ihnen ist ein einzelner Eintrag kürzer in der Länge.

Kann ich R NA für den fehlenden Wert liefern lassen?

Die Dokumentation diskutiert ein deparse.level Argument, aber das scheint nicht meine Lösung zu sein.

Weiter, wenn ich so fett bin, wäre es auch eine schnelle Möglichkeit, die kürzere Spalte mit NA voranzustellen?

Antwort

7

Versuchen Sie folgendes:

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 

oder dieses:

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 

Ich denke, das etwas Ähnliches tun, was Dwin vorgeschlagen und arbeiten unabhängig von dem Vektor kürzer:

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

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

Der obige Code kann auch komprimiert werden:

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

EDIT

Hier ist, was mit ich kam die Frage zu beantworten:

„Weiter, wenn ich so kühn sein kann, gäbe es auch ein schneller Weg sein, um die kürzere Spalte mit der NA vorangestellt wird "

eingefügt in den ursprünglichen Beitrag von Matt O'Brien. Hier

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 

ist eine Funktion:

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) 

Diese Version ermöglicht es Ihnen, zwei Vektoren von anderen Modus cbind:

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

Das wird nur richtig funktionieren, wenn y kürzer als x ist. –

+0

@DWin Könnten Sie nicht einfach die Reihenfolge wechseln und 'Länge (x) = Länge (y)' 'wenn' x' kürzer wäre? –

+2

Sicher, aber Sie sollten einen Test verwenden und dann die richtige Aktion ausführen. –

4

Vor einer Weile ich zusammen hatten eine Funktion Cbind aufgerufen, sollte so etwas tun. In seiner aktuellen Form sollte es in der Lage sein, Vektoren, data.frame s und Matrizen als Eingabe zu handhaben.

Vorerst ist die Funktion hier: https://gist.github.com/mrdwab/6789277

Hier ist, wie man die Funktion verwenden würden:

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 

Die zwei drei Funktionen erforderlich sind padNA, dotnames und Cbind, das sind wie folgt definiert:

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) 
} 

Ein Teil des Grundes, warum ich auf der Funktion aufgehört zu arbeiten war, dass das gdata Paket bereits eine Funktion cbindX die Griffe cbind ing data.frame s und Matrizen mit einem unterschiedlichen Anzahl von Zeilen genannt hat. Es funktioniert nicht direkt auf Vektoren, also müssen Sie sie zuerst zu data.frame s konvertieren.

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 für die Erwähnung von 'cbindX' - funktioniert sehr gut. Hier ist [der Code] (https://github.com/cran/gdata/blob/master/R/cbindX.R) –

Verwandte Themen