Paste multiple rows together in R

时间:2016-06-18 20:03:09

标签: r matrix apply paste

I have a data frame, I want to get the matrix with row 1 paste with row 2, row 3 paste with row 4, if the data frame have odd row, leave the last row the same, instead of paste row, paste column 1 and column2, column 3 and column 4, Matrix will be:

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

The result for matrix paste by rows:

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

The result for matrix paste by columns:

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

I know how to paste all of them together, but I don't know how to do separately

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

Appreciate for your helps.

3 个答案:

答案 0 :(得分:3)

You can probably start from something like the following, where you extract the odd (data[c(T, F), ]) and even (data[c(F, T), ]) rows separately and use the mapply function to loop through them simultaneously and paste them together. Similar logic goes with the columns.

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"

If you need to set up the column names at the same time:

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

Note: This doesn't take care of the odd row or column cases, so you will need some effort to handle that.

答案 1 :(得分:1)

我们可以使用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

答案 2 :(得分:0)

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

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