R 如何将测量数据行转换为(长格式)频率计数?
我已经给出了一些调查的结果作为数据框架,问题是列,答案是行。即,数据帧具有以下形式:R 如何将测量数据行转换为(长格式)频率计数?,r,R,我已经给出了一些调查的结果作为数据框架,问题是列,答案是行。即,数据帧具有以下形式: Q1 Q2 Q3 ... Qn 1 5 4 5 ... 2 2 5 5 NA ... 3 3 2 4 1 ... 2 4 3 3 3 ... 3 5 5 3 5 ... 1 ... 问题(=列)的数量因调查而异(通常很大),但给出的答案总是1到5之间的整数,如果没有给出答案,则为NA 我需要将这些数据转换为(长格式)数据框,表示每个问题给定答案的频率计数,即: que
Q1 Q2 Q3 ... Qn
1 5 4 5 ... 2
2 5 5 NA ... 3
3 2 4 1 ... 2
4 3 3 3 ... 3
5 5 3 5 ... 1
...
问题(=列)的数量因调查而异(通常很大),但给出的答案总是1到5之间的整数,如果没有给出答案,则为NA
我需要将这些数据转换为(长格式)数据框,表示每个问题给定答案的频率计数,即:
question value freq
Q1 1 12
Q1 2 41
Q1 3 123
Q1 4 231
Q1 5 401
Q2 1 11
Q2 2 32
Q2 3 122
Q2 4 321
Q2 5 173
...
然而,我无法想出一个解决方案来实现这一点。我知道,data.frame(表(调查$Q1))
会产生我想要的频率计数,但只针对一个问题。为大量问题中的每一个“手工”组合所有这些数据帧是不可行的。如果可能的话,我也在寻找一个相当普遍的解决方案,可以处理我不同调查中数量可变的问题
提前感谢,感谢您的帮助
用于生成示例数据的代码段:
Q1 = c(5, 5, 2, 3, 5, 4, 3, 5, 2, 3)
Q2 = c(4, 5, 4, 3, 3, 5, 3, 5, 4, 3)
Q3 = c(5, NA, 1, 3, 5, 5, 2, 3, 5, 5)
Qn = c(2, 3, 2, 3, 1, NA, 3, 2, 3, 1)
survey <- data.frame(Q1,Q2,Q3,Qn)
Q1=c(5,5,2,3,5,4,3,5,2,3)
Q2=c(4,5,4,3,3,5,3,5,4,3)
Q3=c(5,NA,1,3,5,5,2,3,5,5)
Qn=c(2,3,2,3,1,NA,3,2,3,1)
调查我们可以尝试使用melt
将“宽”格式转换为“长”格式,转换为data.table(setDT
),获得按“值”、“变量”分组的NROW(.N
)
library(reshape2)
library(data.table)
melt(setDT(survey), na.rm=TRUE)[, .N, by = list(variable,value)]
或者一个base R
方法
subset(as.data.frame(table(stack(survey))), Freq!=0)
我们可以尝试使用melt
将“宽”格式转换为“长”格式,转换为data.table(setDT
),获得按“值”、“变量”分组的NROW(.N
)
library(reshape2)
library(data.table)
melt(setDT(survey), na.rm=TRUE)[, .N, by = list(variable,value)]
或者一个base R
方法
subset(as.data.frame(table(stack(survey))), Freq!=0)
可以使用包创建长数据集,然后使用包创建子组的计数:
library(tidyr)
library(dplyr)
long <- gather(survey, question, value, na.rm = TRUE)
long %>%
group_by(question, value) %>%
tally() %>% # populate the counts
arrange(question, value) # sort the results
library(tidyr)
图书馆(dplyr)
长%
分组依据(问题、值)%>%
tally()%>%#填充计数
安排(问题、价值)#对结果进行排序
您可以使用包创建一个长数据集,然后使用包创建子组的计数:
library(tidyr)
library(dplyr)
long <- gather(survey, question, value, na.rm = TRUE)
long %>%
group_by(question, value) %>%
tally() %>% # populate the counts
arrange(question, value) # sort the results
library(tidyr)
图书馆(dplyr)
长%
分组依据(问题、值)%>%
tally()%>%#填充计数
安排(问题、价值)#对结果进行排序
制表
是一个很好的选择。将其与lappy
和stack
组合,并使用cbind
添加1到5的指示符,以表示您要查找的值。这是@akrun的表
+堆栈
方法的一个细微变化,如果您有很多行和很多列,那么这种方法应该更有效一些:
cbind(Val = 1:5, stack(lapply(survey, tabulate, nbins = 5)))
# Val values ind
# 1 1 0 Q1
# 2 2 2 Q1
# 3 3 3 Q1
# 4 4 1 Q1
# 5 5 4 Q1
# 6 1 0 Q2
# 7 2 0 Q2
# 8 3 4 Q2
# 9 4 3 Q2
# 10 5 3 Q2
# 11 1 1 Q3
# 12 2 1 Q3
# 13 3 2 Q3
# 14 4 0 Q3
# 15 5 5 Q3
# 16 1 2 Qn
# 17 2 3 Qn
# 18 3 4 Qn
# 19 4 0 Qn
# 20 5 0 Qn
您可以使用setNames
“动态”重命名列:
cbind(Value = 1:5,
setNames(stack(lapply(survey, tabulate, nbins = 5)),
c("Freq", "Question")))
下面是base的比较:
f1 <- function() cbind(Val = 1:5, stack(lapply(survey, tabulate, nbins = 5)))
f2 <- function() as.data.frame(table(stack(survey)))
f3 <- function() melt(as.data.table(survey), na.rm=TRUE)[, .N, by = list(variable,value)]
f4 <- function() {
long <- gather(survey, question, value, na.rm = TRUE)
long %>%
group_by(question, value) %>%
tally() %>% # populate the counts
arrange(question, value) # sort the results
}
library(tidyr)
library(dplyr)
library(data.table)
library(microbenchmark)
## A bigger dataset
set.seed(1)
survey <- data.frame(do.call(cbind, replicate(100, list(sample(c(1:5, NA), 10000, TRUE)))))
system.time(f2())
# user system elapsed
# 0.801 0.000 0.802
system.time(f4())
# user system elapsed
# 0.261 0.000 0.268
microbenchmark(f1(), f3()) # The warnings are from `melt`
# Unit: milliseconds
# expr min lq mean median uq max neval
# f1() 2.96567 3.772974 5.157065 4.16065 4.793876 13.51471 100
# f3() 23.79500 77.893235 91.029498 87.22616 102.263556 147.69982 100
# There were 50 or more warnings (use warnings() to see the first 50)
f1制表
是一个很好的候选。将其与lappy
和stack
组合,并使用cbind
添加1到5的指示符,以表示您要查找的值。这是@akrun的表
+堆栈
方法的一个细微变化,如果您有很多行和很多列,那么这种方法应该更有效一些:
cbind(Val = 1:5, stack(lapply(survey, tabulate, nbins = 5)))
# Val values ind
# 1 1 0 Q1
# 2 2 2 Q1
# 3 3 3 Q1
# 4 4 1 Q1
# 5 5 4 Q1
# 6 1 0 Q2
# 7 2 0 Q2
# 8 3 4 Q2
# 9 4 3 Q2
# 10 5 3 Q2
# 11 1 1 Q3
# 12 2 1 Q3
# 13 3 2 Q3
# 14 4 0 Q3
# 15 5 5 Q3
# 16 1 2 Qn
# 17 2 3 Qn
# 18 3 4 Qn
# 19 4 0 Qn
# 20 5 0 Qn
您可以使用setNames
“动态”重命名列:
cbind(Value = 1:5,
setNames(stack(lapply(survey, tabulate, nbins = 5)),
c("Freq", "Question")))
下面是base的比较:
f1 <- function() cbind(Val = 1:5, stack(lapply(survey, tabulate, nbins = 5)))
f2 <- function() as.data.frame(table(stack(survey)))
f3 <- function() melt(as.data.table(survey), na.rm=TRUE)[, .N, by = list(variable,value)]
f4 <- function() {
long <- gather(survey, question, value, na.rm = TRUE)
long %>%
group_by(question, value) %>%
tally() %>% # populate the counts
arrange(question, value) # sort the results
}
library(tidyr)
library(dplyr)
library(data.table)
library(microbenchmark)
## A bigger dataset
set.seed(1)
survey <- data.frame(do.call(cbind, replicate(100, list(sample(c(1:5, NA), 10000, TRUE)))))
system.time(f2())
# user system elapsed
# 0.801 0.000 0.802
system.time(f4())
# user system elapsed
# 0.261 0.000 0.268
microbenchmark(f1(), f3()) # The warnings are from `melt`
# Unit: milliseconds
# expr min lq mean median uq max neval
# f1() 2.96567 3.772974 5.157065 4.16065 4.793876 13.51471 100
# f3() 23.79500 77.893235 91.029498 87.22616 102.263556 147.69982 100
# There were 50 or more warnings (use warnings() to see the first 50)
f1我特别喜欢这个基本解决方案,因为如果用户想要完全填充的结果集为零,他们可以省略subset()。这两个解决方案对我来说都很好,非常感谢。我总是对大多数R解决方案的简洁性感到惊讶。我真希望我自己能想出这样的解决办法/我特别喜欢这个基本解决方案,因为如果用户想要完全填充的结果集为零,他们可以省略subset()。这两个解决方案对我来说都很好,非常感谢。我总是对大多数R解决方案的简洁性感到惊讶。我真希望我自己能想出这样的解决办法/似乎是一个合理的解决方案,但我无法安装tidyr。尝试安装.packages(“tidyr”)
只会给我带来一条“警告消息:包'tidyr'不可用”。我的安装程序有什么问题吗,或者我必须以某种方式“侧载”软件包吗?奇怪的是,当我运行这个确切的命令时,它对我来说安装得很好。它安装在起重机上,所以应该很容易安装。一些故障排除的想法:似乎是一个合理的解决方案,但我无法安装tidyr。尝试安装.packages(“tidyr”)
只会给我带来一条“警告消息:包'tidyr'不可用”。我的安装程序有什么问题吗,或者我必须以某种方式“侧载”软件包吗?奇怪的是,当我运行这个确切的命令时,它对我来说安装得很好。它安装在起重机上,所以应该很容易安装。一些疑难解答的想法: