【问题标题】:Simplify code for getting multiple disease proportions in the population简化获取人群中多种疾病比例的代码
【发布时间】:2018-11-21 00:56:52
【问题描述】:

我有这样的数据

df <- data.frame (
cancer = c(1, 0, 0, 0, 0, 1, 0, 0, 0, 0),
CVD =    c(0, 1, 1, 0, 1, 0, 0, 0, 0, 0),
diab =   c(0, 0, 0, 1, 0, 1, 0, 0, 1, 0),
stroke = c(0, 1, 1, 0, 1, 0, 0, 0, 1, 0),
asthma = c(0, 0, 0, 0, 1, 1, 0, 0, 0, 0),
LTC_count = c(1, 2, 2, 1, 4, 3, 0, 0, 2, 0))

我的数据要大得多,大约。 100 万行。每行是一个人,变量对应这个人的疾病(1=是)

我想要的是一个数据框,其中包含具有和不具有每种条件的人口比例。

这是我为生成我想要的输出所做的:

1) 分别构建具有每个条件的总体比例

Prop_cancer <- df %>%
group_by(cancer) %>%
summarise(count = n()) %>%
mutate(freq = round((count / sum(count))*100, digits = 1)) %>%
mutate(condition = "cancer") %>%
rename(Y_N = cancer) 

Prop_CVD <- df %>%
group_by(CVD) %>%
summarise(count = n()) %>%
mutate(freq = round((count / sum(count))*100, digits = 1)) %>%
mutate(condition = "CVD") %>%
rename(Y_N = CVD)

Prop_diab <- df %>%
group_by(diab) %>%
summarise(count = n()) %>%
mutate(freq = round((count / sum(count))*100, digits = 1)) %>%
mutate(condition = "diab") %>%
rename(Y_N = diab)

Prop_stroke <- df %>%
group_by(stroke) %>%
summarise(count = n()) %>%
mutate(freq = round((count / sum(count))*100, digits = 1)) %>%
mutate(condition = "stroke") %>%
rename(Y_N = stroke)

Prop_asthma <- df %>%
group_by(asthma) %>%
summarise(count = n()) %>%
mutate(freq = round((count / sum(count))*100, digits = 1)) %>%
mutate(condition = "asthma") %>%
rename(Y_N = asthma)

把这些加在一起

Prop_allcond <- bind_rows(Prop_cancer, Prop_CVD, Prop_stroke, Prop_diab, Prop_asthma)

我有大量的条件和大量的数据。有没有更简单/更快的方法来做到这一点?

我考虑通过ifelse 语句在原始数据框中创建一个新变量“条件”,但这不允许一个人拥有多个条件,并且这些条件按照我指定的顺序优先。

不胜感激有关如何简化此代码以使其不那么长的建议。

【问题讨论】:

    标签: r group-by dplyr bind


    【解决方案1】:

    患有特定疾病的人口百分比:

    colSums(df) / nrow(df) * 100
    #cancer       CVD      diab    stroke    asthma LTC_count 
    #20        30        30        40        20       150 
    

    【讨论】:

      【解决方案2】:

      使用dplyr,这可以在一行中完成,无需收集等:

      df %>% summarize_at(vars(-LTC_count),funs(sum(.)/n()))
        cancer CVD diab stroke asthma
      1    0.2 0.3  0.3    0.4    0.2
      

      如果我们想要是和否的频率:

      bind_rows("Y"=summarize_at(df,vars(-LTC_count),funs(sum(.)/n()*100)), 
        "N"=summarize_at(df,vars(-LTC_count),funs(sum(!.)/n()*100)),.id="id")
      
        id cancer CVD diab stroke asthma
      1  Y     20  30   30     40     20
      2  N     80  70   70     60     80
      

      为了响应您对长数据集的请求,我可以执行以下操作,但坦率地说,如果您想要这个,您最好使用@Ronak 的解决方案:

      df1<-bind_rows("Y"=summarize_at(df,vars(-LTC_count),funs(count=sum(.), freq=sum(.)/n()*100)), 
                       "N"=summarize_at(df,vars(-LTC_count),funs(count=sum(!.), freq=sum(!.)/n()*100)),.id="Y_N")
      
      df1<-bind_cols(select(gather(df1,"condition","count",ends_with("_count")),-ends_with("freq")),
                select(gather(df1,"condition","freq",ends_with("_freq")),freq))[,c(2,3,4,1)]
      
      df1$condition<-gsub("_count","",df1$condition)
      
         condition count freq Y_N
      1     cancer     2   20   Y
      2     cancer     8   80   N
      3        CVD     3   30   Y
      4        CVD     7   70   N
      5       diab     3   30   Y
      6       diab     7   70   N
      7     stroke     4   40   Y
      8     stroke     6   60   N
      9     asthma     2   20   Y
      10    asthma     8   80   N
      

      【讨论】:

      • 这太棒了,谢谢。这很好用。但是是否有可能有一个长数据集,其中一列称为“条件”,另一列称为“计数”,另一列称为“频率”,最后一列“Y_N”?
      • 我在此基础上创建了一个解决方案来满足您的要求,但坦率地说,此时@Ronak 的解决方案更有意义。
      【解决方案3】:

      使用tidyverse,我们可以使用gather将数据帧折叠成keyvalue对的长格式,然后group_by它们并计算每个组中的比率。

      library(tidyverse)
      
      df %>%
        gather() %>%
        group_by(key, value) %>%
        summarise(freq = n()) %>%
        ungroup() %>%
        group_by(key) %>%
        mutate(freq = freq/sum(freq) * 100)
      
      
      #   key    value  freq
      #   <chr>  <dbl> <dbl>
      # 1 CVD        0    70
      # 2 CVD        1    30
      # 3 asthma     0    80
      # 4 asthma     1    20
      # 5 cancer     0    80
      # 6 cancer     1    20
      # 7 diab       0    70
      # 8 diab       1    30
      # 9 stroke     0    60
      #10 stroke     1    40
      

      注意 - 我忽略了 LTC_count 列,因为它似乎不参与计算。


      或者我们可以按照@Jake Kaupp 的建议使用count 减少一些步骤

      df %>%
        gather() %>%
        count(key, value) %>%
        group_by(key) %>%
        mutate(n = n/sum(n) * 100)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-16
        • 1970-01-01
        • 1970-01-01
        • 2017-06-22
        • 2023-04-03
        • 1970-01-01
        相关资源
        最近更新 更多