Вставить вместе два фрейма данных элемент за элементом в R - PullRequest
6 голосов
/ 20 июня 2011

Мне нужно вставить элемент за элементом содержимое двух фреймов данных для ввода в другую программу.У меня есть фрейм данных средних и фрейм данных стандартных ошибок среднего.

Я пытался использовать функцию 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 имен строк.Это может быть проблематично с некоторыми решениями, использующими melt ().

Ответы [ 4 ]

10 голосов
/ 20 июня 2011

Если вы сначала конвертируете в матрицы, вы можете сделать это без применений или циклов вообще.

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.

7 голосов
/ 20 июня 2011

Вот способ сделать это без указания вручную каждого столбца. Сначала мы создаем данные и помещаем их в массив, используя пакет 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 голосов
/ 20 июня 2011

Вот как я понимаю вашу проблему.Я объединил данные для средних и SE из нескольких столбцов в один столбец, используя 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 = " - ")
        })

И результат

 [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

Это решение учитывает исходные размеры данных.Что я делаю, так это создаю трехмерный массив и работаю с каждой ячейкой одновременно, удерживая постоянным третьего измерения ([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
}
2 голосов
/ 20 июня 2011

Вы можете сделать это для каждой строки одновременно, но вы применяете к парным столбцам между двумя data.frames.Поскольку у вас есть конкретное задание на вставку, которое нужно выполнять каждый раз, определите функцию:

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))

Именование предполагает, что номер столбца, имена и порядок являются точным соответствием между двумя входными данными.

names(datNew) <- names(datMean)

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

Преобразовать в data.frame:

datNew <- as.data.frame(datNew)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...