将数据文件从宽格式转换为长格式以适合R中的序数混合模型

时间:2013-09-30 16:53:59

标签: r reshape data-conversion reshape2 ordinal

我正在处理宽格式的数据集,如

> 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

其中因子1和因子2是我想要采用的不同因素(实际上我有2个以上,但这不重要),而count_1到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,但我还没有找到正确的语法)

编辑:对于那些也需要这种功能的人来说,下面是Ananda的回答,包含在一个小功能中:

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

1 个答案:

答案 0 :(得分:2)

来自“reshape2”的

melt只会让你解决这个问题的一部分。要完成剩下的工作,您只需要使用基础R中的rep

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