R tidyr基于查找收集()两组列

时间:2018-12-31 06:04:31

标签: 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点刻度指示级别)来将数据集从宽格式重整为长格式。然后创建一个名为Score的列,该列具有汇总分数,最后一个名为Total的列具有每个相应级别的受访者总数。

我的尝试

到目前为止,我已经能够gather 水平 到一列中,并创建Score列。

#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)

我无法弄清楚如何gather 总数 进入另一列,以使新创建的每个总数 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

等等...

任何输入都会受到赞赏。

1 个答案:

答案 0 :(得分:4)

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

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'中的值不同。