Упростите код для получения нескольких пропорций заболеваний в популяции - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть данные, которые выглядят так:

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

Мои данные намного больше, ок.1 миллион строкВ каждой строке указан человек, а переменные соответствуют заболеваниям, которые есть у этого человека (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, но это не позволяет человеку иметь более одногоусловия, а условия имеют приоритет в указанном порядке.

Буду признателен за совет, как упростить этот код, чтобы он не был таким длинным.

Ответы [ 3 ]

0 голосов
/ 21 ноября 2018

С помощью tidyverse мы можем использовать gather, чтобы свернуть фрейм данных в длинный формат в парах key, value, затем 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, поскольку он, кажется, не участвует в вычислениях.


Или мы можем сократить некоторые шаги, используя count, как предложено @Jake Kaupp

df %>%
  gather() %>%
  count(key, value) %>%
  group_by(key) %>%
  mutate(n = n/sum(n) * 100)
0 голосов
/ 21 ноября 2018

Используя 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
0 голосов
/ 21 ноября 2018

Процент населения с данной болезнью:

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