将两个数据表合并为一个,在R中使用交替的列

时间:2019-06-06 17:10:28

标签: r join merge

我有两个数据表,odd_dataeven_data。我想将它们合并/合并成一个all_data,其中all_data的奇数列是odd_data的列,偶数列是even_data的列。但是,我尝试抛出一个错误。

让我们说odd_dataeven_data看起来像:

odd_data
   col_1 col_3
    11    13
    21    23
    31    33

even_data
  col_2 col_4
    12    14
    22    24
    32    34

所需结果如下:

all_data
   col_1 col_2 col_3 col_4
    11    12    13    14
    21    22    23    24
    31    32    33    34

我尝试过的是:

odd_data = data.table(col_1 = c(11, 21, 31),
                      col_3 = c(13, 23, 33))


even_data = data.table(col_2 = c(12, 22, 32),
                       col_4 = c(14, 24, 34))

all_data <- data.table(matrix(nrow = nrow(odd_data), ncol = (ncol(odd_data)*2)))
# change the name of columns of all_data to match column names of odd/even_data
colnames_data <- colnames(all_data)
setnames(all_data, old=colnames_data[c(TRUE, FALSE)], new= colnames(odd_data))
setnames(all_data, old=colnames_data[c(FALSE, TRUE)], new= colnames(even_data))

all_data[, c(rep(c(TRUE, FALSE), 2))] <- odd_data

错误是

Error in `[<-.data.table`(`*tmp*`, , c(rep(c(TRUE, FALSE), 2)), value = list( : 
  j must be vector of column name or positions

2 个答案:

答案 0 :(得分:2)

您可以只cbind,然后重新排列列:

neworder <- order(c(2*(seq_along(odd_data) - 1) + 1,
                    2*seq_along(even_data)))
cbind(odd_data, even_data)[,neworder]
#    col_1 col_2 col_3 col_4
# 1:    11    12    13    14
# 2:    21    22    23    24
# 3:    31    32    33    34

说明:

### count by odds
2*(seq_along(odd_data) - 1) + 1
# [1] 1 3

### count by evens
2*seq_along(even_data)
# [1] 2 4

neworder
# [1] 1 3 2 4

这为我们提供了最后所需的列顺序:第一列(col_1),第三列(col_2,因为它位于第一张表的所有列之后),等等。

为了进行测试,我们可以生成两个不对称的示例:

odd_data = data.table(col_1 = c(11, 21, 31),
                      col_3 = c(13, 23, 33),
                      col_5 = c(15, 25, 35))
even_data = data.table(col_2 = c(12, 22, 32),
                       col_4 = c(14, 24, 34))
neworder <- order(c(2*(seq_along(odd_data) - 1) + 1,
                    2*seq_along(even_data)))
cbind(odd_data, even_data)[,neworder]
#    col_1 col_2 col_3 col_4 col_5
# 1:    11    12    13    14    15
# 2:    21    22    23    24    25
# 3:    31    32    33    34    35

接下来的3和3:

odd_data = data.table(col_1 = c(11, 21, 31),
                      col_3 = c(13, 23, 33),
                      col_5 = c(15, 25, 35))
even_data = data.table(col_2 = c(12, 22, 32),
                       col_4 = c(14, 24, 34),
                       col_6 = c(16, 26, 36))

neworder <- order(c(2*(seq_along(odd_data) - 1) + 1,
                    2*seq_along(even_data)))
cbind(odd_data, even_data)[,neworder]
#    col_1 col_2 col_3 col_4 col_5 col_6
# 1:    11    12    13    14    15    16
# 2:    21    22    23    24    25    26
# 3:    31    32    33    34    35    36

现在,如果我们想通过比 odds 多的 evens (“不应该”发生)来破坏系统,则:

odd_data = data.table(col_1 = c(11, 21, 31),
                      col_3 = c(13, 23, 33),
                      col_5 = c(15, 25, 35))
even_data = data.table(col_2 = c(12, 22, 32),
                       col_4 = c(14, 24, 34),
                       col_6 = c(16, 26, 36),
                       col_8 = c(18, 28, 38))

neworder <- order(c(2*(seq_along(odd_data) - 1) + 1,
                    2*seq_along(even_data)))
cbind(odd_data, even_data)[,neworder]
#    col_1 col_2 col_3 col_4 col_5 col_6 col_8
# 1:    11    12    13    14    15    16    18
# 2:    21    22    23    24    25    26    28
# 3:    31    32    33    34    35    36    38

因此,尽管col_8从技术上讲不是第8列,但所有其他列的顺序仍然保留。

答案 1 :(得分:0)

您可以像这样从dplyr包中使用bind_cols

bind_cols(odd_data,even_data)[,c(1,3,2,4)]