# [ACCEPTED]-Paste together two data frames element by element in R-r

Score: 13

If you convert to matrices first, you can 4 do it with no applies or loops at all.

``````MdatMean <- as.matrix(datMean)
MdatSE <- as.matrix(datSE)
matrix( paste(MdatMean - MdatSE, MdatMean + MdatSE, sep="-"),
nrow=nrow(MdatMean), dimnames=dimnames(MdatMean) )
``````

You 3 also might consider `formatC` for better formatting.

``````lo <- formatC(MdatMean - MdatSE, format="f", digits=3)
hi <- formatC(MdatMean + MdatSE, format="f", digits=3)
matrix( paste(lo, hi, sep="-"),
nrow=nrow(MdatMean), dimnames=dimnames(MdatMean) )
``````

If 2 you want a `data.frame` in the end just wrap the last 1 line in `as.data.frame`.

Score: 8

Here is a way to do this without manually 5 specifying each column. First we make the 4 data and put them in an array using the 3 `abind` package, rounding to 3 because that looks 2 better:

``````datMean <- data.frame(a=rnorm(10, 3), b=rnorm(10, 3), d=rnorm(10, 3))
datSE <- data.frame(a=rnorm(10, 3)/100, b=rnorm(10, 3)/100, d=rnorm(10, 3)/100)

library(abind)

datArray <- round(abind(datMean,datSE,along=3),3)
``````

Then we can apply the `paste` function to 1 each element and column of this array:

``````apply(datArray,1:2,function(x)paste(x[1]-x[2],"-",x[1]+x[2]))

a               b               d
[1,] "3.537 - 3.581" "3.358 - 3.436" "3.282 - 3.312"
[2,] "2.452 - 2.516" "1.372 - 1.44"  "3.041 - 3.127"
[3,] "3.017 - 3.101" "3.14 - 3.228"  "5.238 - 5.258"
[4,] "3.397 - 3.451" "2.783 - 2.839" "3.381 - 3.405"
[5,] "1.918 - 1.988" "2.978 - 3.02"  "3.44 - 3.504"
[6,] "4.01 - 4.078"  "3.014 - 3.068" "1.914 - 1.954"
[7,] "3.475 - 3.517" "2.117 - 2.159" "1.871 - 1.929"
[8,] "2.551 - 2.619" "3.907 - 3.975" "1.588 - 1.614"
[9,] "1.707 - 1.765" "2.63 - 2.678"  "1.316 - 1.348"
[10,] "4.051 - 4.103" "3.532 - 3.628" "3.235 - 3.287"
``````
Score: 3

Here's how I understand your problem. I 6 melted the data for means and SE from multiple 5 columns to one column using `reshape2::melt`.

``````library(reshape2)
datMean <- melt(datMean)\$value
datSE <- melt(datSE)\$value
dat <- cbind(datMean, datSE)

apply(X = dat, MARGIN = 1, FUN = function(x) {
paste(x[1] - x[2], x[1] + x[2], sep = " - ")
})
``````

And the result

`````` [1] "3.03886802467251 - 3.08551547263516"
[2] "3.01803172559258 - 3.05247871975711"
[3] "3.4609230722069 - 3.56097173966387"
[4] "1.35368243309618 - 1.45548512578821"
[5] "2.39936853846605 - 2.47570756724791"
[6] "3.21849170272184 - 3.29653660329785"
``````

EDIT

This 4 solution respects your original data dimensions. What 3 I do is make a 3D array and work on each 2 cell at a time with holding the third dimension 1 (`[x,y, 1:2]`) constant.

``````dat <- array(c(datMean, datSE), dim = c(10, 3, 2))

datNEW <- matrix(rep(NA, nrow(dat)*ncol(dat)), ncol = ncol(dat))

for (column in seq(ncol(dat))) {
cls <- rep(NA, nrow(dat))
for (rows in seq(nrow(dat))) {
tmp <- dat[rows, column, 1:2]
cls[rows] <- paste(tmp[1] - tmp[2], tmp[1] + tmp[2], sep = " - ")
}
datNEW[, column] <- cls
}
``````
Score: 2

You can do this on every row at once, but 15 you are applying to paired columns between 14 two data.frames. Since you have a specific 13 paste job to do each time, define the function:

``````pfun <- function(x, y) paste(x - y, x + y, sep = "-")
``````

and 12 then construct the new data.frame with the 11 function:

`````` datNew <- data.frame(a = pfun(datMean\$a, datSE\$a), b = pfun(datMean\$b, datSE\$b), d = pfun(datMean\$d, datSE\$d))
``````

There would be terser ways to 10 apply this, but perhaps that helps you understand 9 better. You can pass whole columns to paste, but 8 not whole data.frames.

Use a loop to match 7 all columns in the result without specifying 6 them individually.

First create a list 5 to store all the columns, we will convert 4 to data.frame with the right column names.

``````datNew <- vector("list", ncol(datMean))
``````

The 3 naming does assume that column number, names 2 and order are an exact match between the 1 two input data.frames.

``````names(datNew) <- names(datMean)

for (i in 1:ncol(datMean)) {
datNew[[i]] <- pfun(datMean[[i]], datSE[[i]])
}
``````

Convert to data.frame:

``````datNew <- as.data.frame(datNew)
``````
Score: 0

Using mapply to paste and cbind to keep rownames:

``````x <- cbind(
datMean[, 0],
mapply(paste, round(datMean - datSE, 3), round(datMean + datSE, 3), sep = " - "))

x
#               a             b             d
# A 3.268 - 3.321 5.226 - 5.308   2.3 - 2.358
# B 3.795 - 3.874 1.772 - 1.833 2.265 - 2.335
# C 1.305 - 1.346 1.238 - 1.291 2.812 - 2.874
# D 1.957 - 2.041 3.016 - 3.057 2.402 - 2.473
# E  4.73 - 4.786 2.909 - 2.963 2.245 - 2.297
# F 3.511 - 3.554 3.547 - 3.603 2.316 - 2.374
# G 3.601 - 3.689 3.073 - 3.144 3.145 - 3.215
# H 2.056 - 2.118  2.597 - 2.69  2.58 - 2.627
# I 1.802 - 1.835 2.794 - 2.895   2.452 - 2.5
# J 2.399 - 2.461 1.807 - 1.844 3.199 - 3.254

class(x)
# [1] "data.frame"
identical(rownames(datMean), rownames(x))
# [1] TRUE
``````

0

More Related questions