web-dev-qa-db-ja.com

cbind:欠落している値をNAに設定する方法はありますか?

このような簡単な質問への回答を逃した場合は、ご容赦ください。

cbind()を使用して2つの列をバインドしたいと思います。それらの1つは、長さが短い単一のエントリーです。

不足している値に対してRにNAを提供させることはできますか?

ドキュメントでは、deparse.level引数ですが、これは私の解決策ではないようです。

さらに、私がとても大胆かもしれない場合、短い列の前にNAを付ける簡単な方法もありますか?

14
Matt O'Brien

これを試して:

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

またはこれ:

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

これは、DWinが提案したものと同様のことを行い、どのベクトルが短いかに関係なく機能すると思います。

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

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

上記のコードは、次のように要約することもできます。

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

編集

これが私が質問に対処するために思いついたものです:

「さらに、私がそれほど大胆である可能性がある場合、短い列の前にNAを追加する簡単な方法もありますか?」

mattO'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

関数は次のとおりです。

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)

このバージョンでは、異なるモードの2つのベクトルを結合できます。

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)
11
Mark Miller

しばらく前に、この種のことを行うことを目的としたCbindという関数をまとめました。現在の形式では、ベクトル、data.frames、および行列を入力として処理できる必要があります。

今のところ、関数はここにあります: https://Gist.github.com/mrdwab/6789277

関数の使用方法は次のとおりです。

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

ザ・  必要な3つの関数は、padNAdotnames、およびCbindで、次のように定義されています。

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

関数の作業をやめた理由の一部は、gdataパッケージにcbindXing data.framesと異なる数の行列を処理するcbindという関数がすでにあるためです。行。ベクトルでは直接機能しないため、最初にベクトルをdata.framesに変換する必要があります。

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