Изменение формы кадра данных в R
Я сталкиваюсь с трудностями при изменении формы большого кадра данных. И мне посчастливилось избежать переделки проблем в прошлом, что также означает, что я ужасен в этом.
Мой текущий dataframe выглядит примерно так:
unique_id seq response detailed.name treatment
a N1 123.23 descr. of N1 T1
a N2 231.12 descr. of N2 T1
a N3 231.23 descr. of N3 T1
...
b N1 343.23 descr. of N1 T2
b N2 281.13 descr. of N2 T2
b N3 901.23 descr. of N3 T2
...
И мне бы хотелось:
seq detailed.name T1 T2
N1 descr. of N1 123.23 343.23
N2 descr. of N2 231.12 281.13
N3 descr. of N3 231.23 901.23
Я просмотрел пакет reshape, но я не уверен, как я могу преобразовать факторы обработки в имена отдельных столбцов.
Спасибо!
Изменить: я попытался запустить это на моей локальной машине (4 ГБ двухъядерного iMac 3.06Ghz), и он продолжает работать с:
> d.tmp.2 <- cast(d.tmp, `SEQ_ID` + `GENE_INFO` ~ treatments)
Aggregation requires fun.aggregate: length used as default
R(5751) malloc: *** mmap(size=647168) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Я попробую запустить это на одной из наших больших машин, когда у меня появится шанс.
Ответы
Ответ 1
Изменение всегда кажется мне сложным, но всегда кажется, что он работает с небольшим проб и ошибок. Вот что я нашел:
> x
unique_id seq response detailed.name treatment
1 a N1 123.23 dN1 T1
2 a N2 231.12 dN2 T1
3 a N3 231.23 dN3 T1
4 b N1 343.23 dN1 T2
5 b N2 281.13 dN2 T2
6 b N3 901.23 dN3 T2
> x2 <- melt(x, c("seq", "detailed.name", "treatment"), "response")
> x2
seq detailed.name treatment variable value
1 N1 dN1 T1 response 123.23
2 N2 dN2 T1 response 231.12
3 N3 dN3 T1 response 231.23
4 N1 dN1 T2 response 343.23
5 N2 dN2 T2 response 281.13
6 N3 dN3 T2 response 901.23
> cast(x2, seq + detailed.name ~ treatment)
seq detailed.name T1 T2
1 N1 dN1 123.23 343.23
2 N2 dN2 231.12 281.13
3 N3 dN3 231.23 901.23
Ваши исходные данные были уже в длинном формате, но не в длинном формате, который использует расплав/литье. Поэтому я переплавил его. Второй аргумент (id.vars) - это список вещей, которые не тают. Третий аргумент (measure.vars) - это список вещей, которые меняются.
Затем литье использует формулу. Слева от тильды находятся те вещи, которые остаются такими, какими они есть, а справа от тильды - столбцы, которые используются для определения столбца значения.
Больше или меньше...!
Ответ 2
Основываясь на ответе Harlan - можно избежать шага переплавки, если данные уже находятся в длинном формате, а значения удержания столбца указаны в вызове cast
.
> x <- read.table(textConnection(" unique_id seq response detailed.name treatment
+ 1 a N1 123.23 dN1 T1
+ 2 a N2 231.12 dN2 T1
+ 3 a N3 231.23 dN3 T1
+ 4 b N1 343.23 dN1 T2
+ 5 b N2 281.13 dN2 T2
+ 6 b N3 901.23 dN3 T2"))
>
> cast(x, seq + detailed.name ~ treatment, value = "response")
seq detailed.name T1 T2
1 N1 dN1 123.23 343.23
2 N2 dN2 231.12 281.13
3 N3 dN3 231.23 901.23
Ответ 3
Другой вариант - использовать spread
из tidyr
library(tidyr)
Wide1 <- spread(x[-1], treatment, response)
Wide1
# seq detailed.name T1 T2
#1 N1 dN1 123.23 343.23
#2 N2 dN2 231.12 281.13
#3 N3 dN3 231.23 901.23
Противоположное действие выполняется gather
gather(Wide1, detailed.name, response, T1:T2)
# seq detailed.name detailed.name response
#1 N1 dN1 T1 123.23
#2 N2 dN2 T1 231.12
#3 N3 dN3 T1 231.23
#4 N1 dN1 T2 343.23
#5 N2 dN2 T2 281.13
#6 N3 dN3 T2 901.23
Кроме того, есть dcast.data.table
из data.table
library(data.table)
dcast.data.table(setDT(x), seq + detailed.name~treatment,
value.var='response')
# seq detailed.name T1 T2
#1: N1 dN1 123.23 343.23
#2: N2 dN2 231.12 281.13
#3: N3 dN3 231.23 901.23
данные
x <- structure(list(unique_id = structure(c(1L, 1L, 1L, 2L, 2L, 2L
), .Label = c("a", "b"), class = "factor"), seq = structure(c(1L,
2L, 3L, 1L, 2L, 3L), .Label = c("N1", "N2", "N3"), class = "factor"),
response = c(123.23, 231.12, 231.23, 343.23, 281.13, 901.23
), detailed.name = structure(c(1L, 2L, 3L, 1L, 2L, 3L), .Label = c("dN1",
"dN2", "dN3"), class = "factor"), treatment = structure(c(1L,
1L, 1L, 2L, 2L, 2L), .Label = c("T1", "T2"), class = "factor")), .Names =
c("unique_id", "seq", "response", "detailed.name", "treatment"), class =
"data.frame", row.names = c(NA, -6L))
Ответ 4
Вы также можете использовать функцию reshape
в пакете stats
. У меня нет образца набора данных, но он будет выглядеть примерно так:
reshape(x, idvar=c("seq","detailed.name"), timevar="treatment", direction="wide")
Ответ 5
Если вы хотите получить те же результаты с помощью reshape2
, который представляет собой более быструю и более эффективную запись памяти пакета reshape
, тогда будет работать следующее.
Основное изменение - использование функции dcast
, если вы хотите cast
с выходом data.frame
. Это заменяет функцию cast
reshape
library(reshape2)
x = read.table(text = "unique_id seq response detailed.name treatment
a N1 123.23 dN1 T1
a N2 231.12 dN2 T1
a N3 231.23 dN3 T1
b N1 343.23 dN1 T2
b N2 281.13 dN2 T2
b N3 901.23 dN3 T2",
sep = "", header = TRUE)
x
y <- dcast(x, seq + detailed.name ~ treatment, value.var = "response")
y
# seq detailed.name T1 T2
# 1 N1 dN1 123.23 343.23
# 2 N2 dN2 231.12 281.13
# 3 N3 dN3 231.23 901.23
# EDIT to show how to return to the original data set:
melt(y, id.vars=c('seq', 'detailed.name'), variable.name='T', value.name='response')
# seq detailed.name T response
# 1 N1 dN1 T1 123.23
# 2 N2 dN2 T1 231.12
# 3 N3 dN3 T1 231.23
# 4 N1 dN1 T2 343.23
# 5 N2 dN2 T2 281.13
# 6 N3 dN3 T2 901.23