4

我有一个数据框,它由代表问题的 4 列组成,每列代表响应的 4 个级别。

  Q1 Q2
1  A  A
2  A  B
3  B  B
4  C  C
5  D  D

我想得出一个data.frame这样的:

   question response percent
1       Q2        A     0.2
2       Q2        B     0.4
3       Q2        C     0.2
4       Q2        D     0.2
5       Q1        A     0.4
6       Q1        B     0.2
7       Q1        C     0.2
8       Q1        D     0.2

到目前为止,我一直在使用循环来实现这一点for,但是我的脚本充满了for循环,所以我想使用 inreshape2或 with中的函数来实现这一点lapply。例如,这段代码比for循环干净得多,但仍然不是我想要的。任何帮助将不胜感激!

这是我到目前为止所得到的:

lapply(lapply(df, summary), function(x) x/sum(x))

编辑:包括每个请求的数据框示例。本来担心关卡标签太长会占用太多空间,所以我把它们缩短了。

dput(df[1:4,])
structure(list(Q1 = structure(c(4L, 4L, 1L, 4L), .Label = c("1.A", 
    "1.B", "1.C", "1.D"), class = "factor"), 
    Q2 = structure(c(4L, 4L, 4L, 1L), .Label = c("2.A","2.B",
    "2.C", "2.D"), class = "factor"), 
    Q3 = structure(c(4L, 3L, 4L, 4L), .Label = c("3.A","3.B",
    "3.C","3.D"), class = "factor"), 
    Q4 = structure(c(3L, 1L, 3L, 3L), .Label = c("4.A","4.B", 
    "4.C","4.D")), 
    .Names = c("Q1.pre", "Q2.pre", "Q3.pre", "Q4.pre"), row.names = c(NA, 4L), 
    class = "data.frame")

我发现 Lafortune 和 user20650 的回答结合起来给了我几乎正是我一直在寻找的东西:

melt(sapply(df, function(x) prop.table(table(x))))

然而有一个问题。在sapply级别上, 与dimnamesQ1 级别的标签名称相同,因此在执行melt的输出后sapply,Var1 列只是 Q1s 级别的重复,而我希望 Var1 在 Q1 中具有 Q1 的级别行,Q2 行中的 Q2 级别等。我找到了一种解决方法,方法是将levels所有列拉到一个单独的变量qnames 中,然后再执行任何操作,df如下所示:

qnames = melt(sapply(df, levels))
qnames = qnames[ ,3]
melt(sapply(df, function(x) prop.table(table(x))))
df = cbind(qnames, df)

这正是我需要的结果。我有兴趣看看是否有办法在没有额外的情况下实现这一点sapplyand cbind,所以我将把这个问题留得更久一点。谢谢你的帮助!

4

2 回答 2

2

单线使用data.table

library(data.table) # 1.9.5+
dt<-data.table(Q1=c("A","A","B","C","D"),
               Q2=c("A","B","B","C","D"))

rbindlist(lapply(
  names(dt),
  function(x)dt[,.N/nrow(dt),by=x
                ][,.(question=x,response=get(x),percent=V1)]))
于 2015-07-10T21:07:01.410 回答
2
library(reshape2)
indx <- lapply(df, function(x) prop.table(table(x)))
out <- melt(do.call(rbind, indx))
out <- out[order(out$Var1, decreasing=TRUE),];rownames(out) <- NULL
#   Var1 Var2 value
# 1   Q2    A   0.2
# 2   Q2    B   0.4
# 3   Q2    C   0.2
# 4   Q2    D   0.2
# 5   Q1    A   0.4
# 6   Q1    B   0.2
# 7   Q1    C   0.2
# 8   Q1    D   0.2

您可以使用lapplyand reshape2,但有一个很好的功能是prop.table。当它包装table函数时,它会为你计算百分比。我们为每一列创建一个比例表lapply,然后将它们与始终忠实的do.call(rbind, lst). 最后一行是“外观”。

于 2015-07-10T21:01:24.153 回答