I have a data.table:
library(data.table)
p1 = data.table(a = c(10.34,25.87,53.2), b=c(15.3,183.2,34.8))
print(p1)
a b
1: 10.34 15.3
2: 25.87 183.2
3: 53.20 34.8
What I would like to get is a new data.table with the following structure:
a b a1 b1 a2 b2 a3 b3
1: 10.34 15.3 10.34 15.3 25.87 183.2 53.2 34.8
2: 25.87 183.2 10.34 15.3 25.87 183.2 53.2 34.8
3: 53.20 34.8 10.34 15.3 25.87 183.2 53.2 34.8
My current solution is:
p2 = cbind(p,p[1,],p[2,],p[3,])
How do I create a similar (other than using for loops) data.table p2 with 10001 columns when I have input data.table p with 10000 rows?
Any help is appreciated.
Here is another option using rbindlist
and cbind
on rep
for transposed data frame.
library(data.table)
cbind(p1, rbindlist(rep(list(data.table(t(unlist(p1)))), times = nrow(p1))))
# a b a1 a2 a3 b1 b2 b3
# 1: 10.34 15.3 10.34 25.87 53.2 15.3 183.2 34.8
# 2: 25.87 183.2 10.34 25.87 53.2 15.3 183.2 34.8
# 3: 53.20 34.8 10.34 25.87 53.2 15.3 183.2 34.8
Update
@Frank pointed out in the comments that cbind
can take unequal row numbers of two data frames. In this case, the data frame with less row numbers would be "recycled". So we don't need rep
or rbindlist
and below is the updated code.
cbind(p1, data.table(t(unlist(p1))))
# a b a1 a2 a3 b1 b2 b3
# 1: 10.34 15.3 10.34 25.87 53.2 15.3 183.2 34.8
# 2: 25.87 183.2 10.34 25.87 53.2 15.3 183.2 34.8
# 3: 53.20 34.8 10.34 25.87 53.2 15.3 183.2 34.8
To get the col order as desired by OP, one option is setcolorder
:
cbind(p1, setcolorder(data.table(t(unlist(p1))), order(row(p1))) )
# a b a1 b1 a2 b2 a3 b3
# 1: 10.34 15.3 10.34 15.3 25.87 183.2 53.2 34.8
# 2: 25.87 183.2 10.34 15.3 25.87 183.2 53.2 34.8
# 3: 53.20 34.8 10.34 15.3 25.87 183.2 53.2 34.8
We can use shift
out <- cbind(p1, p1[, shift(.SD, type = 'lead',
n = c(0, seq_len(.N-1)))][rep(1, nrow(p1))])
setnames(out, make.unique(c(names(p1), rep(names(p1), each = nrow(p1)))))
or with tidyverse
library(tidyverse)
pmap_dfc(p1, list) %>%
uncount(nrow(p1))
If we need the original data as well
pmap_dfc(p1, list) %>%
rowr::cbind.fill(p1, .)
# a b a b a1 b1 a2 b2
#1 10.34 15.3 10.34 15.3 25.87 183.2 53.2 34.8
#2 25.87 183.2 10.34 15.3 25.87 183.2 53.2 34.8
#3 53.20 34.8 10.34 15.3 25.87 183.2 53.2 34.8
Or with transpose
and bind_cols
purrr::transpose(p1) %>%
bind_cols %>%
rowr::cbind.fill(p1, .)
Here's another option, similar to www
's:
> cbind(p1, matrix(rep(unlist(p1), nrow(p1)), nrow = nrow(p1), byrow=T))
a b V1 V2 V3 V4 V5 V6
1: 10.34 15.3 10.34 25.87 53.2 15.3 183.2 34.8
2: 25.87 183.2 10.34 25.87 53.2 15.3 183.2 34.8
3: 53.20 34.8 10.34 25.87 53.2 15.3 183.2 34.8
cbind(p1, do.call(cbind, split(p1, 1:nrow(p1))))
# a b 1.a 1.b 2.a 2.b 3.a 3.b
# 1: 10.34 15.3 10.34 15.3 25.87 183.2 53.2 34.8
# 2: 25.87 183.2 10.34 15.3 25.87 183.2 53.2 34.8
# 3: 53.20 34.8 10.34 15.3 25.87 183.2 53.2 34.8
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.