R tidyr gather() 基于查找的两组列

标签 r tidyr data-manipulation

我有一个按地区进行满意度调查的结果数据集。调查中的每个问题都采用 4 分制评分(从非常满意非常不满意)。数据集中的每一行都包含给定“财政年度”结束时给定区域中给定问题的汇总结果。它还包含每个级别的受访者总数。

这是数据集的样子

testdf=data.frame(FY=c("FY13","FY14","FY15","FY14","FY15","FY13","FY14","FY15","FY13","FY15","FY13","FY14","FY15","FY13","FY14","FY15"),
                  Region=c(rep("AFRICA",5),rep("ASIA",5),rep("AMERICA",6)),
                  QST=c(rep("Q2",3),rep("Q5",2),rep("Q2",3),rep("Q5",2),rep("Q2",3),rep("Q5",3)),
                  Very.Satisfied=runif(16,min = 0, max=1),
                  Total.Very.Satisfied=floor(runif(16,min=10,max=120)),
                  Satisfied=runif(16,min = 0, max=1),
                  Total.Satisfied=floor(runif(16,min=10,max=120)),
                  Dissatisfied=runif(16,min = 0, max=1),
                  Total.Dissatisfied=floor(runif(16,min=10,max=120)),
                  Very.Dissatisfied=runif(16,min = 0, max=1),
                  Total.Very.Dissatisfied=floor(runif(16,min=10,max=120))
                  )

我的目标

我的目标是通过首先创建一个名为 Level 的列(表示 4 分制的级别),将数据集从宽格式 reshape 为长格式。然后创建一个名为 Score 的列,其中包含汇总分数,最后一列名为 Total,其中包含每个相应级别的受访者总数。

我的尝试

到目前为止,我已经能够收集级别到一个列中,并创建分数列。

#Gather Satisfation levels
library(tidyverse)
testfinal = testdf %>% gather(Level,Score,-FY:-QST,-Total.Very.Satisfied,-Total.Satisfied,-Total.Dissatisfied,-Total.Very.Dissatisfied) %>%
  select(1:3,8:9,4:7)

我无法弄清楚如何收集总计到另一列这样新创建的每个总计 Total 列对应于与其关联的级别。

如果一切顺利,这里是最终数据集的预览

#FY   #Region  #QST  #Level            #Score        #Total
 FY13  AFRICA   Q2    Very.Satisfied    0.73080770    48
 FY14  AFRICA   Q2    Very.Satisfied    0.58686424    97
 FY15  AFRICA   Q2    Very.Satisfied    0.07358698    34
 FY14  AFRICA   Q5    Very.Satisfied    0.59996830    22

等等...

如有任何意见,我们将不胜感激。

最佳答案

使用 data.table 中的 melt 可以更轻松地完成此操作。将 'data.frame' 转换为 'data.table' (setDT),melt 从 'wide' 到 'long',同时指定多列名称 patterns measure 参数中

library(data.table)
out <- melt(setDT(testdf), measure = patterns("^Total", 
     "^(Very|Satisfied|Dis)"), value.name = c("Total", "Score"), 
       variable.name = "Level")
nm1 <- names(testdf)[c(4, 6, 8, 10)]
out[, Level := nm1[Level]][]
head(out)
#     FY Region QST          Level Total      Score
#1: FY13 AFRICA  Q2 Very.Satisfied    85 0.36888202
#2: FY14 AFRICA  Q2 Very.Satisfied   108 0.67589979
#3: FY15 AFRICA  Q2 Very.Satisfied    13 0.90792351
#4: FY14 AFRICA  Q5 Very.Satisfied    52 0.01966743
#5: FY15 AFRICA  Q5 Very.Satisfied    59 0.68895083
#6: FY13   ASIA  Q2 Very.Satisfied    96 0.24912066

或者使用tidyverse

library(tidyverse)
testdf %>%
    gather(key, val, 4:ncol(.)) %>%
    extract(key, into = c("key1", "Level"), "(Total)?\\.?(.*)") %>%
    mutate(key1 = replace_na(key1, "Score")) %>%
    spread(key1, val)
#      FY  Region QST             Level      Score Total
#1  FY13  AFRICA  Q2      Dissatisfied 0.69226483    71
#2  FY13  AFRICA  Q2         Satisfied 0.91617425    26
#3  FY13  AFRICA  Q2 Very.Dissatisfied 0.64277110    43
#4  FY13  AFRICA  Q2    Very.Satisfied 0.36888202    85
#5  FY13 AMERICA  Q2      Dissatisfied 0.10219036    37
#6  FY13 AMERICA  Q2         Satisfied 0.28281065    26
#7  FY13 AMERICA  Q2 Very.Dissatisfied 0.59667659    90
#8  FY13 AMERICA  Q2    Very.Satisfied 0.30204224    76
# ....

注意:'Total' 和 'Score' 中的值不同,因为在创建数据集时没有 set.seed

关于R tidyr gather() 基于查找的两组列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53984126/

相关文章:

r - 列表中的模型无法预测

r - 使用 R tidyrivot_wide 从多个列名称和值获取宽格式数据

r - 为什么 complete() 在我的数据中创建重复的行?

php - 寻找一种方法来获取一个字符串并用两个符号替换每个字符串然后再返回

r - 根据列中的条件为组分配值

python - 根据字符串中定义的条件填充新列

r - 按组手动填充多个比例的geom_tile

r - 纵向数据集中事件发生后删除后续观测值

r - dplyr:子集、总结和变异新函数的工作流程

r - 一次旋转更长的十二列