【问题标题】:Tidyverse Solution to get Counts Based on Filtering Different Combinations of VariablesTidyverse 解决方案通过过滤不同的变量组合获得计数
【发布时间】:2017-04-30 06:16:04
【问题描述】:
 Library(tidyverse)

使用下面的代码,我想使用 table() 或 dplyr 来获取 Sat 变量(Q1Sat、Q2Sat、Q3Sat)的计数。但是,Q1Sat 与变量 Q1Used 相关,Q2Sat 与 Q2Used 相关,Q3Sat 与 Q3Used 相关。我想过滤掉每个组合的 Used 变量中的“No”,以及 House 变量中的“No”。

因此,例如,要计算 Q1Sat 的计数,我需要在 Q1used 和 House 中过滤掉“否”。对于 Q2Sat,我需要在 Q2Used 和 House 中过滤掉“No”,对于 Q3 Sat,我必须在 Q3Used 和 House 中过滤掉“No”。

使用 Tidyverse,有什么简单的方法可以做到这一点? (最少的代码)。如有必要,我想使用最新版本的 Tidyverse 软件包,包括 dplyr 的开发版本。

Q1Sat<-c("Neutral","Neutral","VSat","Sat","Neutral","Sat","VDis","Sat","Sat","VSat")
Q2Sat<-c("Neutral","VSat","Dis","Dis","VDis","Sat","Sat","VSat","Neutral","Dis")
Q3Sat<-c("Sat","Sat","Diss","Neutral","VSat","VDis","Sat","Sat","Sat","Neutral")
Q3Used<-c("Yes","No","Yes","Yes","Yes","Yes","Yes","Yes","Yes","No")
Q2Used<-c("Yes","Yes","Yes","Yes","No","No","Yes","Yes","Yes","Yes")
Q1Used<-c("Yes","Yes","Yes","No","No","Yes","Yes","Yes","No","Yes")
House<-c("Yes","No","Unsure","Yes","Yes","No","Unsure","Unsure","Yes","Yes")

Test<-data_frame(Q1Sat,Q2Sat,Q3Sat,Q1Used,Q2Used,Q3Used,House)

【问题讨论】:

    标签: r dplyr tidyverse purrr


    【解决方案1】:
    Test %>% 
    mutate(q1 = ifelse(Q1Used=="Yes", Q1Sat, NA), 
           q2 = ifelse(Q2Used=="Yes", Q2Sat, NA), 
           q3 = ifelse(Q3Used=="Yes", Q3Sat, NA)) %>% 
    select(q1:q3) %>% 
    sapply(., table)
    
    $q1
    
    Neutral     Sat    VDis    VSat 
          2       2       1       2 
    
    $q2
    
        Dis Neutral     Sat    VSat 
          3       2       1       2 
    
    $q3
    
       Diss Neutral     Sat    VDis    VSat 
          1       1       4       1       1 
    

    【讨论】:

    • 这看起来像我一直在寻找的东西,因为它使用了 Tidyverse。我还没有机会尝试一下,但我认为您没有加入有问题的“House”组件?另外,有没有办法避免多个 ifelse 语句?使用 dplyr 的作用域过滤函数或 SE 的新开发版本怎么样?
    【解决方案2】:

    这是一个使用data.table 的选项。我们将“data.frame”转换为“data.table”(setDT(Test)),通过在melt 中指定patterns 将其重塑为“long”,按“Qs”和“Sat”分组,得到计算“已使用”为“是”的位置并将其重新调整为“宽”格式

    library(data.table)
    dcast(melt(setDT(Test), measure = patterns("Sat", "Used"), 
       value.name = c("Sat", "Used"), variable.name = 'Qs')[
       Used == "Yes", .N , .(Qs, Sat)], Qs~Sat, fill=0)[, Qs := nm1[Qs][]
    #   Qs Dis Diss Neutral Sat VDis VSat
    #1: Q1   0    0       2   2    1    2
    #2: Q2   3    0       2   1    0    2
    #3: Q3   0    1       1   4    1    1
    

    另外,我们可以用base R更简洁地做到这一点

    un1 <- unique(unlist(Test[1:3]))
    t(mapply(function(x,y) table(factor(x[y == "Yes"], levels = un1)), Test[1:3], Test[4:6]))
    

    甚至更紧凑

    table(col(Test[1:3]), unlist(replace(Test[1:3], Test[4:6]!= "Yes", NA)))
    #    Dis Diss Neutral Sat VDis VSat
    #1   0    0       2   2    1    2
    #2   3    0       2   1    0    2
    #3   0    1       1   4    1    1
    

    【讨论】:

    • 我希望每个变量都分开,就像下面的答案一样。另外,这是否考虑到“House”变量?我想过滤 Used 变量和 House 变量中的“否”。
    • 我喜欢简洁的代码,但是有没有办法以某种方式将新的作用域 dplyr 过滤器函数与 SE 一起使用?如果它更容易,我可以将它作为一个新问题问...我相信 Tidyverse 方法涉及多个嵌套的 if_else,但是有没有办法通过 dplyr 的开发版本中的范围过滤和 SE 来避免这种情况?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多