Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 使用lappy()查找因子变量的百分比_R_Lapply_Reshape2_Split Apply Combine - Fatal编程技术网

R 使用lappy()查找因子变量的百分比

R 使用lappy()查找因子变量的百分比,r,lapply,reshape2,split-apply-combine,R,Lapply,Reshape2,Split Apply Combine,我有一个数据框架,由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

我有一个数据框架,由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
循环,因此我希望使用
restrape2
中的函数或
lappy
来实现这一点。例如,这个代码比
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
级别上,
dimnames
与Q1级别的标签名称相同,因此在执行
melt
sapply的输出后,Var1列只是Q1级别的重复,而我希望Var1在Q1行中有Q1级别,在Q2行中有Q2级别,等等。在对
df
执行任何操作之前,我通过将所有列的
levels
拉入一个单独的变量
qnames
找到了一个解决方法,例如:

qnames = melt(sapply(df, levels))
qnames = qnames[ ,3]
melt(sapply(df, function(x) prop.table(table(x))))
df = cbind(qnames, df)
这正是我需要的结果。我很想知道是否有一种方法可以在不使用额外的
sapply
cbind
的情况下实现这一点,因此我将把问题留得更久一些。谢谢你的帮助

library(重塑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

indx使用
数据的一条线性。表

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)]))
library(data.table)#1.9.5+

请张贴一个可复制的例子。在您的数据帧上使用
dput()
,并为我们提供例如前20行这只是一个聚合。阅读关于dplyr和data.table的信息。做一个
group\u by(问题)
(顺便说一下,
percent
应该被称为
fraction
,除非你在函数中用它乘以100)如果你使用
sapply
你可以避免
Do.call
东西。。。ie
melt(sappy(数据,函数(x)属性表(表(x)))
谢谢。总是伟大的优化!没问题。。。lappy/do.call实际上可能更快。。。但是sapply imo在这里更具可读性,我现在无法测试(如此移动),但我认为一个函数通常比两个好。我同意sapply的可读性更高-谢谢,这是我追求的路线。谢谢,这是难以置信的高效代码!然而,我更喜欢使用
sapply
lappy
函数,因为我认为代码更透明,更容易复制(我肯定需要阅读data.table包)。@Killerfurbies你会注意到我的代码的关键确实是
lappy
。如果您想要一个启动
data.table
的好资源,请查看他们的github页面上的入门小故事,它们是非常清晰的挖掘方法。我必须补充的是,学习
数据.table
的回报是巨大的。我已返回到您的代码,并试图在自定义函数中实现它,但我一直在.subset(x,j):无效的下标类型“list”
中收到错误
。我一直在研究stackoverflow,我认为它与计算
j
表达式或
by
的框架有关。关于如何解决这个问题,您有什么想法吗?这是因为
别名是
data.table的开发版本中的新别名,请参阅,以获取有关安装最新更新的说明。如果您不想这样做(我推荐它,因为1.9.5中有各种各样的优点),您可以替换
。(问题…
列表(问题…
啊,我确实使用了较旧版本的
data.table
。现在,在用
列表(
替换
)后,我在get(x)中得到了错误
错误):找不到对象“Q1”
。同样,这仅在个人函数中发生,在控制台中运行相同代码时不会发生。感谢您的帮助@MichaelChirico!