13

I want to add a new column with "NA"s in my dataframe:

     A       B
1    14379  32094
2   151884  174367
3   438422  449382

But I need it to be located between col. A and B, like this:

     A       C      B
1    14379   NA    32094
2   151884   NA    174367
3   438422   NA    449382

I know how to add col. C after col. B, but that is not helpful to me... Anyone know how to do it?

zx8754
  • 52,746
  • 12
  • 114
  • 209
TWest
  • 765
  • 2
  • 6
  • 27

4 Answers4

26

In 2 steps, you can reorder the columns:

dat$C <- NA
dat <- dat[, c("A", "C", "B")]
         A  C          B
1  0.596068 NA -0.7783724
2 -1.464656 NA -0.8425972

You can also use append

dat <- data.frame(A = rnorm(2), B = rnorm(2))
as.data.frame(append(dat, list(C = NA), after = 1))

           A   C          B
1 -0.7046408  NA  0.2117638
2  0.8402680  NA -2.0109721
flodel
  • 87,577
  • 21
  • 185
  • 223
agstudy
  • 119,832
  • 17
  • 199
  • 261
6

If you use data.table you can use the function setcolorder. Note that NA is stored as logical variable, if you want to have the column initiated as an integer, double or character column, you can use NA_integer, NA_real_ or NA_character_

eg

library(data.table)
DT <- data.table(DF)
# add column `C`  = NA 

DT[, C := NA]

setcolorder(DT, c('A','C','B'))
DT
##         A  C      B
## 1:  14379 NA  32094
## 2: 151884 NA 174367
## 3: 438422 NA 449382

You could do this in one line

setcolorder(DT[, C: = NA], c('A','B','C'))
mnel
  • 113,303
  • 27
  • 265
  • 254
3

You can also use the package tibble, which has a very interesting function (among many other) for that : add_column()

library(tibble)
df <- data.frame("a" = 1:5, "b" = 6:10)
add_column(df, c = rep(NA, nrow(df)), .after = 1)

That function is easy to use, and you can use the argument .before instead.

Kevin Zarca
  • 2,572
  • 1
  • 18
  • 18
1

I wrote a function to append columns onto (into) a data.frame. It allows you to name the column as well, and does a few checks...

append_col <- function(x, cols, after=length(x)) {
    x <- as.data.frame(x)
    if (is.character(after)) {
        ind <- which(colnames(x) == after)
        if (any(is.null(ind))) stop(after, "not found in colnames(x)\n")
    } else if (is.numeric(after)) {
        ind <- after
    }
    stopifnot(all(ind <= ncol(x)))
    cbind(x, cols)[, append(1:ncol(x), ncol(x) + 1:length(cols), after=ind)]
}

examples:

# create data
df <- data.frame("a"=1:5, "b"=6:10)

# append column 
append_col(df, list(c=1:5))

# append after an column index
append_col(df, list(c=1:5), after=1)

# or after a named column
append_col(df, list(c=1:5), after="a")

# multiple columns / single values work as expected
append_col(df, list(c=NA, d=4:8), after=1)

(One advantage of calling cbind at the end of the function and indexing is that characters within the data.frame are not coerced to factors as would be the case if using as.data.frame(append(x, cols, after=ind)))

waferthin
  • 1,582
  • 1
  • 16
  • 27