Подсчет строк во фрейме данных, которые удовлетворяют некоторым критериям, и группирование их по уникальным значениям в первом столбце фрейма данных - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть данные с id дома, пола и возраста следующим образом:

mydata <- 

structure(list(ID_HH = c(1,1,1,1,2,2,3,3,3,4,5,5), 
                           GENDER = c(1,2,1,1,1,2,2,1,2,2,1,1), 
                           AGE = c(50,45,3,15,25,5,32,30,10,28,64,16)), 
                      .Names = c("ID", "GENDER", "AGE"), 
                      class = "data.frame", row.names = c(NA, -12L))

   mydata

#  HH_ID GENDER AGE
# 1  1    1    50
# 2  1    2    45
# 3  1    1    3
# 4  1    1    15
# 5  2    1    25
# 6  2    2    5
# 7  3    2    32
# 8  3    1    30
# 9  3    2    10
# 10 4    2    28
# 11 5    1    64
# 12 5    1    16

У меня есть другой фрейм данных, давайте назовем его «output», который имеет только уникальные значения HH_ID и некоторые другие столбцы, следующиек этому.То, что я хотел бы сделать, это добавить новые столбцы к этому фрейму данных, которые показывают:

  • "число взрослых женщин (пол = 2 && возраст = 18)",
  • «количество взрослых мужчин (пол = 1 && возраст = 18)»,
  • «количество школьников (6–18)» (Num_Sch) и
  • «количествоpreschpol children (0-6) "(Num_PreSch)

для каждого домашнего хозяйства.Таким образом, «выходные данные» должны выглядеть следующим образом:

    #  HH_ID Col1 Col2 ... Num_Fem Num_Male Num_PreSch Num_Sch
# 1  1    ..              1       1         1        1 
# 2  2    ..              0       1         1        0 
# 3  3    ..              1       1         0        1
# 4  4    ..              1       0         0        0
# 5  5    ..              0       1         0        1

Я перепробовал множество различных функций и пакетов, но ничто не могло достичь именно того, чего я хочу.Буду признателен за любую помощь или комментарий.

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Вы уже думаете об этом таким образом, который хорошо переводит на логические утверждения (например, является ли этот человек женщиной и ей 18 лет или старше), поэтому я бы сделал это с помощью ряда логических векторов, используя тот факт, что, поскольку истинно/ false переводит в 1/0, вы можете суммировать их.

Установите различные категории и создайте логические столбцы для каждой.

library(tidyverse)

mydata %>%
  mutate(adult_female = (GENDER == 2 & AGE >= 18),
         adult_male = (GENDER == 1 & AGE >= 18),
         school = between(AGE, 6, 18),
         preschool = between(AGE, 0, 6))
#>    ID GENDER AGE adult_female adult_male school preschool
#> 1   1      1  50        FALSE       TRUE  FALSE     FALSE
#> 2   1      2  45         TRUE      FALSE  FALSE     FALSE
#> 3   1      1   3        FALSE      FALSE  FALSE      TRUE
#> 4   1      1  15        FALSE      FALSE   TRUE     FALSE
#> 5   2      1  25        FALSE       TRUE  FALSE     FALSE
#> 6   2      2   5        FALSE      FALSE  FALSE      TRUE
#> 7   3      2  32         TRUE      FALSE  FALSE     FALSE
#> 8   3      1  30        FALSE       TRUE  FALSE     FALSE
#> 9   3      2  10        FALSE      FALSE   TRUE     FALSE
#> 10  4      2  28         TRUE      FALSE  FALSE     FALSE
#> 11  5      1  64        FALSE       TRUE  FALSE     FALSE
#> 12  5      1  16        FALSE      FALSE   TRUE     FALSE

Затем вы можете сгруппировать по домохозяйствам и суммировать всестолбцы логического типа.

mydata %>%
  mutate(adult_female = (GENDER == 2 & AGE >= 18),
         adult_male = (GENDER == 1 & AGE >= 18),
         school = between(AGE, 6, 18),
         preschool = between(AGE, 0, 6)) %>%
  group_by(ID) %>%
  summarise_if(is.logical, sum)
#> # A tibble: 5 x 5
#>      ID adult_female adult_male school preschool
#>   <dbl>        <int>      <int>  <int>     <int>
#> 1     1            1          1      1         1
#> 2     2            0          1      0         1
#> 3     3            1          1      1         0
#> 4     4            1          0      0         0
#> 5     5            0          1      1         0

Одна проблема, которую я позволю вам решить: функция between включает свои конечные точки.Вы охарактеризовали дошкольный возраст от 0 до 6 лет, а школьный возраст от 6 до 18 лет. Это означает, что в обоих случаях учитываются 6 лет.Возможно, вы захотите настроить эти конечные точки, что не должно быть слишком сложно, поскольку кажется, что вы работаете с возрастом как целое число.

0 голосов
/ 05 декабря 2018

Может быть причудливый способ сделать это, но вы можете просто сделать это, используя цикл for, как показано ниже:

mydata  <- as.data.frame(mydata)
Num_Fem <- Num_Male <- Num_PreSch <- Num_Sch <- c()

for(ID_HH in output$ID_HH){
  curr_HH    <- mydata[mydata$ID_HH == ID_HH,]

  Num_Fem    <- c(Num_Fem,    nrow(curr_HH[curr_HH$GENDER==2 & curr_HH$AGE>=18,]))
  Num_Male   <- c(Num_Male,   nrow(curr_HH[curr_HH$GENDER==1 & curr_HH$AGE>=18,]))
  Num_PreSch <- c(Num_PreSch, nrow(curr_HH[curr_HH$AGE<6,]))
  Num_Sch    <- c(Num_Sch,    nrow(curr_HH[curr_HH$AGE>=6 & curr_HH$AGE<18,]))
}

output <- cbind(output, data.frame(Num_Fem, Num_Male, Num_PreSch, Num_Sch))

Это даст вам ожидаемые результаты:

    #  HH_ID Col1 Col2 ... Num_Fem Num_Male Num_PreSch Num_Sch
# 1        1   ..   ..           1        1         1        1 
# 2        2   ..   ..           0        1         1        0 
# 3        3   ..   ..           1        1         0        1
# 4        4   ..   ..           1        0         0        0
# 5        5   ..   ..           0        1         0        1

Надеюсь, это поможет.

...