psysky
psysky

Reputation: 3195

rbind command in R within one and the same datasets

the rbind command is easy to use if we have 2 split datasets. for example

d1=structure(list(a = c(1L, 4L), b = c(2L, 5L), c = c(3L, 6L)), class = "data.frame", row.names = c(NA, 
-2L))
d2=structure(list(a = c(7L, 10L), b = c(8L, 11L), c = c(9L, 12L)), class = "data.frame", row.names = c(NA, 
-2L))

new=rbind(d1,d2)

but how to use the rbind function if the data is not separated, but they are in one dataset for example

test=structure(list(a = c(1L, 4L), b = c(2L, 5L), c = c(3L, 6L), X = c(NA, 
NA), X.1 = c(NA, NA), d = c(7L, 10L), e = c(8L, 11L), f = c(9L, 
12L)), class = "data.frame", row.names = c(NA, -2L))

to get output

   a  b  c
1  1  2  3
2  4  5  6
3  7  8  9
4 10 11 12

Upvotes: 0

Views: 54

Answers (3)

jay.sf
jay.sf

Reputation: 72909

You could write a small function that uses seq.int in an mapply and that would do the job for you.

f <- function(data, start, ncol) {
  s <- mapply(seq.int, start, start + ncol - 1)
  as.data.frame(apply(s, 1, function(s) unlist(data[, s])))
}

Usage

res <- f(test, start=c(1, 6), ncol=3)
res
#   V1 V2 V3
# 1  1  2  3
# 2  4  5  6
# 3  7  8  9
# 4 10 11 12

## or, if names wanted
res <- setNames(f(test, start=c(1, 6), ncol=3), names(test)[1:3])
res
#    a  b  c
# 1  1  2  3
# 2  4  5  6
# 3  7  8  9
# 4 10 11 12

Data:

test <- structure(list(a = c(1L, 4L), b = c(2L, 5L), c = c(3L, 6L), X = c(NA, 
NA), X.1 = c(NA, NA), d = c(7L, 10L), e = c(8L, 11L), f = c(9L, 
12L)), class = "data.frame", row.names = c(NA, -2L))

Upvotes: 1

ThomasIsCoding
ThomasIsCoding

Reputation: 101568

Assuming the data columns are always separated by NA columns, then perhaps we can try the base R code below, where rle + is.na + Filter + rbind are applied

lst <- with(
  rle(sapply(
    test,
    function(x) all(!is.na(x))
  )),
  Filter(
    function(v) all(!is.na(v)),
    split.default(
      test,
      cut(seq_along(test), c(0, cumsum(lengths)))
    )
  )
)

out <- do.call(
  rbind,
  c(
    make.row.names = FALSE,
    lapply(lst, setNames, nm = names(lst[[1]]))
  )
)

and we will obtain

> out
   a  b  c
1  1  2  3
2  4  5  6
3  7  8  9
4 10 11 12

Upvotes: 1

Duck
Duck

Reputation: 39595

Try next code:

#Code
new <- rbind(test[,1:3],setNames(test[,6:8],names(test[,1:3])))

Output:

   a  b  c
1  1  2  3
2  4  5  6
3  7  8  9
4 10 11 12

Upvotes: 1

Related Questions