在 R 中重塑 Table - 更好的方法?

Reshaping a Table in R - Better Approach?

我有一个名为 questions

的因子数据框
q1 q2 q3
A  A  B
C  A  A
A  B  C

我想重塑成

question answer freq
1        A      2
1        B      0
1        C      1
2        A      2
2        B      1
2        C      0
3        A      1
3        B      1
3        C      1

我觉得应该有办法用 reshape2 或 plyr 解决这个问题,但我想不出来。

相反,我执行了以下操作:

tbl <- data.frame()
for(i in 1:dim(questions)[2]){
    subtable <- cbind(question = rep(i, 3),
                      as.data.frame(table(questions[i])))
    tbl <- rbind(tbl, subtable)
}

是否有更简洁的方法来重塑此 table?

尝试

library(qdapTools)
library(reshape2)
colnames(questions) <- sub('\D+', '', colnames(questions))
setNames(melt(as.matrix(mtabulate(questions))), 
                      c('question', 'answer', 'freq'))

或使用data.table

library(data.table)#v.1.9.5+
setkey(
    setnames(
      melt(setDT(questions, keep.rownames=TRUE), id.var='rn',
             value.name='answer')[, list(freq=.N),
                  by=list(variable, answer)],
           'variable', 'question'), 
                  question, answer)[
       CJ(question=unique(question), answer=unique(answer))][
                 is.na(freq), freq:=0][]
 #   question answer freq
 #1:        1      A    2
 #2:        1      B    0
 #3:        1      C    1
 #4:        2      A    2
 #5:        2      B    1
 #6:        2      C    0
 #7:        3      A    1
 #8:        3      B    1
 #9:        3      C    1

是的,由于零,这有点棘手。熔化后,不是直接浇铸成你需要的形状,而是浇铸成宽的形状,然后再熔化。不过,使用 base R 和 table 可能同样简单。

d <- read.table(text="q1 q2 q3
                       A  A  B
                       C  A  A
                       A  B  C", header=TRUE, as.is=TRUE)
melt(dcast(melt(d, measure.vars=1:3), value ~ variable))

## Aggregation function missing: defaulting to length
## Using value as id variables
##   value variable value
## 1     A       q1     2
## 2     B       q1     0
## 3     C       q1     1
## 4     A       q2     2
## 5     B       q2     1
## 6     C       q2     0
## 7     A       q3     1
## 8     B       q3     1
## 9     C       q3     1

这是一个基本的 R 方法,在概念上类似于@akrun 发布的方法。我没有费心清理,因为这主要是装饰性的,与问题的概念无关。

一般方法是:

data.frame(table(stack(mydf))

但是,stack 不适用于 factors,因此如果您的数据是 factors 而不是 characters,则必须使用as.character 首先,像这样:

data.frame(table(stack(lapply(mydf, as.character))))
#   values ind Freq
# 1      A  q1    2
# 2      B  q1    0
# 3      C  q1    1
# 4      A  q2    2
# 5      B  q2    1
# 6      C  q2    0
# 7      A  q3    1
# 8      B  q3    1
# 9      C  q3    1

从 "plyr" 和 "reshape2" 转向 "dplyr" 和 "tidyr",您可以尝试:

library(dplyr)
library(tidyr)

mydf %>% 
  gather(question, answer, everything()) %>%  ## Get the data into a long form
  group_by(question, answer) %>%              ## Group by both question and answer columns
  summarise(freq = n()) %>%                   ## Calculate the relevant frequency
  right_join(expand(., question, answer))     ## Merge with all combinations of Qs and As
# Joining by: c("question", "answer")
# Source: local data frame [9 x 3]
# Groups: question
# 
#   question answer freq
# 1       q1      A    2
# 2       q1      B   NA
# 3       q1      C    1
# 4       q2      A    2
# 5       q2      B    1
# 6       q2      C   NA
# 7       q3      A    1
# 8       q3      B    1
# 9       q3      C    1