Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/82.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 如何将测量数据行转换为(长格式)频率计数?_R - Fatal编程技术网

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'不可用”。我的安装程序有什么问题吗,或者我必须以某种方式“侧载”软件包吗?奇怪的是,当我运行这个确切的命令时,它对我来说安装得很好。它安装在起重机上,所以应该很容易安装。一些疑难解答的想法: