【问题标题】:merge two data table into one, with alternating columns in R将两个数据表合并为一个,R中的列交替
【发布时间】:2019-06-06 17:10:28
【问题描述】:

我有两个数据表,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

【问题讨论】:

  • 另一种可能:d &lt;- cbind(odd_data, even_data); setcolorder(d, c(matrix(1:ncol(d), nrow = 2, byrow = TRUE)))

标签: r join merge


【解决方案1】:

您可以只 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

现在,如果我们想尝试通过使 evens 多于 odds 来破坏系统(这“不应该”发生):

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 列,但所有其他列的顺序仍然保留。

【讨论】:

  • :D 这很简单!我总是走奇怪的路线!
【解决方案2】:

你可以像这样使用 dplyr 包中的 bind_cols

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

【讨论】:

    猜你喜欢
    • 2021-11-09
    • 1970-01-01
    • 2020-10-16
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多