我需要逐个元素地粘贴两个数据帧的内容,以便输入到另一个程序。我有一个平均值的数据框和一个标准误差的数据框。
我尝试使用R paste()函数,但它似乎无法处理数据框。当使用向量时,它似乎将第一个向量的所有元素连接成一个字符串,将第二个向量的所有元素连接成一个单独的字符串。相反,我需要将两个数据帧中的每个互惠元素连接在一起。
有关如何处理此问题的任何建议?我已经包含了虚拟输入数据(datMean和datSE)和我想要的输出(datNew)。我的实际数据框大小约为10行×150列。
# means and SEM
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)
# what the output should look like
# i've chosen some arbitrary values here, and show only the first row.
datNew <- data.frame(a="2.889-2.926", b="1.342-1.389", d="2.569-2.576")
这个想法是针对datNew中的每个元素都是由'mean-se'和'mean + se'组成的范围,用短划线' - '分隔。 paste()函数可以为一个元素执行此操作,如何在整个数据框中执行此操作?
paste(datMean[1,1] - datSE[1,1], datMean[1,1] + datSE[1,1], sep="-")
编辑1: 看一些答案,我意识到我在问题中遗漏了一些重要的信息。原始数据帧的每一行都被命名,我需要用这些名称重建最终数据帧。例如:
rownames(datMean) <- LETTERS[1:10]
rownames(datSE) <- LETTERS[1:10]
我需要datNew最终再次拥有这10个rownames。对于一些使用melt()的解决方案,这可能会有问题。
答案 0 :(得分:10)
如果首先转换为矩阵,则可以完全不使用或循环。
MdatMean <- as.matrix(datMean)
MdatSE <- as.matrix(datSE)
matrix( paste(MdatMean - MdatSE, MdatMean + MdatSE, sep="-"),
nrow=nrow(MdatMean), dimnames=dimnames(MdatMean) )
您还可以考虑使用formatC
来更好地进行格式化。
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) )
如果你想要data.frame
,最后只需在as.data.frame
中包裹最后一行。
答案 1 :(得分:7)
这是一种在不手动指定每列的情况下执行此操作的方法。首先,我们使用abind
包制作数据并将它们放入数组中,舍入为3,因为它看起来更好:
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)
然后我们可以将paste
函数应用于此数组的每个元素和列:
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"
答案 2 :(得分:2)
您可以一次对每一行执行此操作,但是您要应用于两个data.frame之间的成对列。由于每次都要执行特定的粘贴作业,因此请定义函数:
pfun <- function(x, y) paste(x - y, x + y, sep = "-")
然后使用函数
构造新的data.frame datNew <- data.frame(a = pfun(datMean$a, datSE$a), b = pfun(datMean$b, datSE$b), d = pfun(datMean$d, datSE$d))
有一些方法可以应用这个,但也许这有助于你更好地理解。您可以将整列传递给粘贴,但不能传递整个data.frames。
使用循环匹配结果中的所有列,而不单独指定它们。
首先创建一个列表来存储所有列,我们将转换为具有正确列名的data.frame。
datNew <- vector("list", ncol(datMean))
命名确实假设列号,名称和顺序是两个输入data.frames之间的完全匹配。
names(datNew) <- names(datMean)
for (i in 1:ncol(datMean)) {
datNew[[i]] <- pfun(datMean[[i]], datSE[[i]])
}
转换为data.frame:
datNew <- as.data.frame(datNew)
答案 3 :(得分:2)
以下是我理解您的问题的方法。我使用reshape2::melt
将means和SE的数据从多列熔合到一列。
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 = " - ")
})
结果
[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"
修改的
此解决方案尊重您的原始数据维度。我所做的是制作一个3D数组并一次处理每个单元格,同时保持第三维([x,y, 1:2]
)不变。
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
}