Преобразование файла данных из широкого в длинный формат, чтобы соответствовать порядковой смешанной модели в R

Я имею дело с набором данных в широком формате, например

> data=read.csv("http://www.kuleuven.be/bio/ento/temp/data.csv")
> data
  factor1 factor2 count_1 count_2 count_3
1       a       a       1       2       0
2       a       b       3       0       0
3       b       a       1       2       3
4       b       b       2       2       0
5       c       a       3       4       0
6       c       b       1       1       0

где factor1 и factor2 - это разные факторы, которые я хотел бы взять с собой (на самом деле у меня их больше 2, но это не имеет значения), а count_1 to count_3 - это количество агрессивных взаимодействий по порядковой шкале (3> 2> 1 ). Теперь я хотел бы преобразовать этот набор данных в длинный формат, чтобы получить что-то вроде

   factor1 factor2 aggression
1        a       a          1
2        a       a          2
3        a       a          2
4        a       b          1
5        a       b          1
6        a       b          1
7        b       a          1
8        b       a          2
9        b       a          2
10       b       a          3
11       b       a          3
12       b       a          3
13       b       b          1
14       b       b          1
15       b       b          2
16       b       b          2
17       c       a          1
18       c       a          1
19       c       a          1
20       c       a          2
21       c       a          2
22       c       a          2
23       c       a          2
24       c       b          1
25       c       b          2

Может ли кто-нибудь знать, как это сделать без использования циклов for ... to, например используя пакет reshape2? (Я понимаю, что это должно работать с melt, но я просто еще не смог придумать правильный синтаксис)

Изменить: для тех из вас, кому также может понадобиться такая функциональность, вот ответ Ананды ниже, завернутый в небольшую функцию:

    widetolong.ordinal<-function(data,factors,responses,responsename) {
    library(reshape2)
    data$ID=1:nrow(data) # add an ID to preserve row order
    dL=melt(data, id.vars=c("ID", factors)) # `melt` the data
    dL=dL[order(dL$ID), ] # sort the molten data
    dL[,responsename]=match(dL$variable,responses) # convert reponses to ordinal scores
    dL[,responsename]=factor(dL[,responsename],ordered=T)
    dL=dL[dL$value != 0, ] # drop rows where `value == 0`
    out=dL[rep(rownames(dL), dL$value), c(factors, responsename)] # use `rep` to "expand" `data.frame` & drop unwanted columns
    rownames(out) <- NULL
    return(out)
    }

    # example
    data <- read.csv("http://www.kuleuven.be/bio/ento/temp/data.csv")
    widetolong.ordinal(data,c("factor1","factor2"),c("count_1","count_2","count_3"),"aggression")

person Tom Wenseleers    schedule 30.09.2013    source источник
comment
Взгляните на melt в reshape2 пакете. Просмотрите простые примеры здесь, и я уверен, что вы сможете определить соответствующие id.vars и measure.vars в ваших собственных данных.   -  person Henrik    schedule 30.09.2013
comment
Я думаю, что единственное, для чего я использую SPSS, - это делать именно это.   -  person PascalVKooten    schedule 30.09.2013
comment
@AnandaMahto: извините за мой довольно длинный пример - теперь я отредактировал его, чтобы дать более абстрактный и простой пример - и спасибо Хенрику за указатель - я понял, что таяние, вероятно, было подходящим вариантом, но до сих пор не понял правильный синтаксис, хотя для моей цели ...   -  person Tom Wenseleers    schedule 01.10.2013
comment
У вас гораздо больше шансов получить помощь, если вы покажете нам, что вы пробовали. Опять же, взгляните на пример, который я предложил . Данные очень похожи на ваши данные: два фактора (пол испытуемого против фактора1 фактора2) и три измерения (контроль cond1 cond2 против count_1 count_2 count_3).   -  person Henrik    schedule 01.10.2013
comment
@Henrik, это похожая проблема, но для этого вопроса нужно немного больше, чем melt.   -  person A5C1D2H2I1M1N2O1R2T1    schedule 01.10.2013
comment
@Dualinity, у SPSS есть специальная функция для чего-то подобного? Просто любопытно. :)   -  person A5C1D2H2I1M1N2O1R2T1    schedule 01.10.2013
comment
@AnandaMahto, я полностью согласен. Я просто пытался подбодрить OP начать работу и показать нам код, который он пробовал. Отличный ответ, +1!   -  person Henrik    schedule 01.10.2013
comment
@AnandaMahto Да, у SPSS есть простое решение с графическим интерфейсом.   -  person PascalVKooten    schedule 01.10.2013
comment
@Dualinity, поделитесь, где это. Мне любопытно посмотреть, как это реализовано, и соответствующий код, который потребовался бы, если бы это было сделано вручную.   -  person A5C1D2H2I1M1N2O1R2T1    schedule 01.10.2013
comment
@AnandaMahto Из-за перехода на Ubuntu он в настоящее время не установлен. Я помню, что это легко заметить в меню.   -  person PascalVKooten    schedule 01.10.2013


Ответы (1)


melt из reshape2 поможет вам решить эту проблему только частично. Чтобы пройти оставшуюся часть пути, вам просто нужно использовать rep из базы R:

data <- read.csv("http://www.kuleuven.be/bio/ento/temp/data.csv")
library(reshape2)

## Add an ID if the row order is importantt o you
data$ID <- 1:nrow(data)

## `melt` the data
dL <- melt(data, id.vars=c("ID", "factor1", "factor2"))

## Sort the molten data, if necessary
dL <- dL[order(dL$ID), ]

## Extract the numeric portion of the "variable" variable
dL$aggression <- gsub("count_", "", dL$variable)

## Drop rows where `value == 0`
dL <- dL[dL$value != 0, ]

## Use `rep` to "expand" your `data.frame`.
## Drop any unwanted columns at this point.
out <- dL[rep(rownames(dL), dL$value), c("factor1", "factor2", "aggression")]

Вот как в итоге выглядит результат. Если вы хотите удалить забавные названия строк, просто используйте rownames(out) <- NULL.

out
#      factor1 factor2 aggression
# 1          a       a          1
# 7          a       a          2
# 7.1        a       a          2
# 2          a       b          1
# 2.1        a       b          1
# 2.2        a       b          1
# 3          b       a          1
# 9          b       a          2
# 9.1        b       a          2
# 15         b       a          3
# 15.1       b       a          3
# 15.2       b       a          3
# 4          b       b          1
# 4.1        b       b          1
# 10         b       b          2
# 10.1       b       b          2
# 5          c       a          1
# 5.1        c       a          1
# 5.2        c       a          1
# 11         c       a          2
# 11.1       c       a          2
# 11.2       c       a          2
# 11.3       c       a          2
# 6          c       b          1
# 12         c       b          2
person A5C1D2H2I1M1N2O1R2T1    schedule 01.10.2013