R tidyr将列分布在给定变量的所有类别中

时间:2018-09-21 08:58:19

标签: r tidyr data-manipulation spread

我正在处理如下所示的数据集。

#Dataframe
df=data.frame(Type=c(1,2,4,5,4,3,3,4,5,1,2,3,2,1,2,3,3,2,1,1,NA),
          Q1=c(1,2,6,8,9,10,2,6,7,4,9,9,1,2,NA,4,3,8,7,6,4),
          Q2=c(1,2,4,NA,8,2,1,2,10,7,5,5,5,8,2,7,4,8,7,5,1))

上下文

数据框由问卷调查的结果组成。

第一列Type是指回答问卷的员工类型,其中1 ='Worker',2 ='Factory Lead',3 ='{{ 1}}',4 ='Administrative Staff'和5 ='Middle Management'

第二和第三列(ExecutiveQ1)是问题,评分范围为1 ='Q2'至10(Strongly Agree)。

我要实现的目标

我想根据得分计算每个Strongly Disagree的响应总数。 我为分数创建了垃圾箱,它们是-

1)Type协议-分数从0到4

2)Low协议-得分为5或6

3)Medium协议-得分为7或8

4)High协议-得分为9或10

所以我想计算每个分数箱中每个工人的响应次数。

我的尝试

Very High

我的逻辑是我使用library(dplyr) library(tidyr) result=df %>% gather(Item,response,-1) %>% filter(!is.na(response)) %>% group_by(Type,Item) %>% filter(!is.na(Type)) %>% summarise(Low=sum(response %in% c(0,1,2,3,4)), Medium=sum(response %in% c(5,6)), High=sum(response %in% c(7,8)), VHigh=sum(response %in% c(9,10)) %>% spread(Type,-Item) 库和第一个tidyr分数来计算总响应。然后展开这些列,这样我就可以得到按工人和分数类别分类的小计。

例如,对于Q1,此列是gather,然后依次是Low-Worker,然后是Medium-Worker,然后是High-Worker,然后是Very High-Worker,然后是Low-Factory Lead ....依此类推,适用于员工和分数类别的所有组合。

很明显,我的代码中有错误之处。

所需的输出

具有两行Medium-Factory LeadQ1)和 20列(对于每个员工分数组合)的数据框。

对此将提供任何帮助。

3 个答案:

答案 0 :(得分:2)

创建分数数据框

library(tidyr)
library(dplyr)
df <- data_frame(type=c(1,2,4,5,4,3,3,4,5,1,2,3,2,1,2,3,3,2,1,1,NA),
                 q1=c(1,2,6,8,9,10,2,6,7,4,9,9,1,2,NA,4,3,8,7,6,4),
                 q2=c(1,2,4,NA,8,2,1,2,10,7,5,5,5,8,2,7,4,8,7,5,1))

scores <- data_frame(score = 0:10,
                     scorebin = c(rep("Low", 5),
                                  rep("Medium", 2),
                                  rep("High", 2),
                                  rep("Very High", 2)))

以长格式收集数据。加入分数数据框以添加一个scorebin列。按itemtypescorebin分组,并计算每组下的答案数。

df2 <- df %>%
    gather(item, score, -type) %>% 
    left_join(scores, by = "score") %>% 
    group_by(item, type, scorebin) %>% 
    summarise(n = n()) %>% 
    unite(employeescore, type, scorebin)

employeescore更改为有序水平的因子 这样它们就不会按字母顺序显示(高,低,中) 但顺序正确(低,中,高)。

employeescoreorder <- scores %>% 
    distinct(scorebin) %>% 
    merge(distinct(df, type)) %>% 
    unite(employeescore, type, scorebin)
df2$employeescore <- factor(df2$employeescore, 
                            levels = employeescoreorder$employeescore)

以宽格式扩展数据框以获得20列。

df2 %>% 
    spread(employeescore, n)

# A tibble: 2 x 20
# Groups:   item [2]
   item `1_Low` `1_Medium` `1_High` `2_Low` `2_Medium` `2_High` `2_Very High` `4_Low`
* <chr>   <int>      <int>    <int>   <int>      <int>    <int>         <int>   <int>
1    q1       3          1        1       2         NA        1             1      NA
2    q2       1          1        3       2          2        1            NA       2
# ... with 11 more variables: `4_Medium` <int>, `4_High` <int>, `4_Very High` <int>,
#   `5_High` <int>, `5_Very High` <int>, `3_Low` <int>, `3_Medium` <int>, `3_High` <int>,
#   `3_Very High` <int>, NA_Low <int>, `<NA>` <int>

答案 1 :(得分:0)

喜欢吗?

 df%>%
   mutate(Type_real=case_when(
             Type==1~"Worker",
             Type==2~"Factory Lead",
             Type==3~"Administrative Staff",
             Type==4~"Middle Management",
             Type==5~"Executive"),
         Score=case_when(
             Q1<5~"Low",
             Q1>=5 & Q1<=6~"Medium",
             Q1>=7 & Q1<=8~"High",
             Q1>8~"Very High"))%>%
   na.omit()%>%
   group_by(Type_real,Score)%>%
   summarise(count=n())
# A tibble: 11 x 3
# Groups:   Type_real [?]
   Type_real            Score     count
   <chr>                <chr>     <int>
 1 Administrative Staff Low           3
 2 Administrative Staff Very High     2
 3 Executive            High          1
 4 Factory Lead         High          1
 5 Factory Lead         Low           2
 6 Factory Lead         Very High     1
 7 Middle Management    Medium        2
 8 Middle Management    Very High     1
 9 Worker               High          1
10 Worker               Low           3
11 Worker               Medium        1

答案 2 :(得分:0)

另一种类似于Paul Rougieux的解决方案,但没有加入:

df %>% 
  mutate(Type = case_when(Type == 1 ~ "Worker",
                          Type == 2 ~ "Factory Lead",
                          Type == 3 ~ "Administrative Staff",
                          Type == 4 ~ "Middle Management",
                          Type == 5 ~ "Executive")) %>% 
  mutate_at(c("Q1", "Q2"), 
            funs(case_when(. %in% 1:4 ~ "Low",
                           . %in% 5:6 ~ "Medium",
                           . %in% 7:8 ~ "High",
                           . %in% 9:10 ~ "Very High"))) %>%
  gather(Questions, Score, Q1:Q2) %>% 
  unite(Type_Score, Type, Score, sep = "_") %>% 
  count(Questions, Type_Score) %>% 
  spread(Type_Score, n)

# A tibble: 2 x 21
#   Questions `Administrative~ `Administrative~ `Administrative~ `Administrative~ Executive_High Executive_NA `Executive_Very~ `Factory Lead_H~
#   <chr>                <int>            <int>            <int>            <int>          <int>        <int>            <int>            <int>
# 1 Q1                      NA                3               NA                2              2           NA               NA                1
# 2 Q2                       1                3                1               NA             NA            1                1                1
# ... with 12 more variables: `Factory Lead_Low` <int>, `Factory Lead_Medium` <int>, `Factory Lead_NA` <int>, `Factory Lead_Very High` <int>,
#   `Middle Management_High` <int>, `Middle Management_Low` <int>, `Middle Management_Medium` <int>, `Middle Management_Very High` <int>,
#   NA_Low <int>, Worker_High <int>, Worker_Low <int>, Worker_Medium <int>