在 R 中将多行粘贴在一起

Paste multiple rows together in R

我有一个数据框,我想得到矩阵,第 1 行粘贴到第 2 行,第 3 行粘贴到第 4 行,如果数据框有奇数行,则保留最后一行,而不是粘贴行,粘贴第 1 列和第 2 列,第 3 列和第 4 列,矩阵将为:

data <- data.frame(name = c(1:4), plate=c("A","B","C","D"), value1=c(4:7), value2 = c(100, 200, 300, 400))

data
     name plate value1 value2
      1     A      4    100
      2     B      5    200
      3     C      6    300
      4     D      7    400

矩阵按行粘贴的结果:

 name   plate  value1   value2
 1-2    A-B    4-5      100-200
 3-4    C-D    6-7      300-400

矩阵按列粘贴的结果:

name-plate  value1-value2
  1-A          4-100
  2-B          5-200
  3-C          6-300
  4-D          7-400

我知道怎么把它们全部贴在一起,但我不知道怎么分开

> apply( data[,1:4] , 1, paste , collapse = "-" )
[1] "1-A-4-100" "2-B-5-200" "3-C-6-300" "4-D-7-400"

感谢您的帮助。

您可能可以从类似下面的内容开始,在其中分别提取奇数 (data[c(T, F), ]) 和偶数 (data[c(F, T), ]) 行,然后使用 mapply 函数同时循环并粘贴他们在一起。列也有类似的逻辑。

mapply(paste, sep = "-", data[c(T,F),], data[c(F,T),])
#      -     <NA>  <NA>  <NA>     
# [1,] "1-2" "A-B" "4-5" "100-200"
# [2,] "3-4" "C-D" "6-7" "300-400"

mapply(paste, sep = "-", dat[,c(T,F)], dat[,c(F,T)])
#      -     <NA>   
# [1,] "1-A" "4-100"
# [2,] "2-B" "5-200"
# [3,] "3-C" "6-300"

如果需要同时设置列名:

setNames(as.data.frame(mapply(paste, sep = "-", data[c(T,F),], data[c(F,T),])), 
         names(data))
#   name plate value1  value2
# 1  1-2   A-B    4-5 100-200
# 2  3-4   C-D    6-7 300-400

setNames(as.data.frame(mapply(paste, sep = "-", data[,c(T,F)], data[,c(F,T)])), 
         paste(names(data)[c(T,F)], names(data)[c(F,T)], sep = "-"))
#   name-plate value1-value2
# 1        1-A         4-100
# 2        2-B         5-200
# 3        3-C         6-300
# 4        4-D         7-400

注意:这不会处理奇数行或奇数列的情况,因此您需要一些努力来处理它。

我们可以用 lapply

as.data.frame(t(sapply(seq(1, nrow(data), by = 2), function(i)
                     apply(data[i:(i+1),], 2, paste, collapse="-"))))
 #    name plate value1  value2
 #1  1-2   A-B    4-5 100-200
 #2  3-4   C-D    6-7 300-400

setNames(as.data.frame(sapply(seq(1, nrow(data), by = 2), function(i) 
      apply(data[,i:(i+1)], 1, paste, collapse="-"))), c("name-plate", "value1-value2"))
#    name-plate value1-value2
#1        1-A         4-100
#2        2-B         5-200
#3        3-C         6-300
#4        4-D         7-400

另一种方法是使用 tidyr 包中的联合函数。

library(tidyr)
data <- data.frame(name = c(1:4), 
                   plate=c("A","B","C","D"), 
                   value1=c(4:7), 
                   value2 = c(100, 200, 300, 400))
data %>% 
  unite("name-plate", name, plate, remove = T, sep = "-") %>% 
  unite("value1-value2", value1, value2, remove = T, sep = "-")

# outputs the following data.frame

     name-plate value1-value2
1        1-A         4-100
2        2-B         5-200
3        3-C         6-300
4        4-D         7-400