Multiple Columns to calculate new column using equation

Viewed 102

I'm a fairly new R user -- trying to teach myself based on forums, videos, and trial+error. I have a very large dataset and would like to calculate number of members in the household who are considered children ( aged under 18). I have a column for number of household members, as well as 11 columns for each household member's age. My initial thought would be to select those who are under 18 and subtract from total household members. I've tried a few different lines of code unsuccessfully and I'm not sure how best to go about executing this. Any help is greatly appreciated!

enter image description here

2 Answers

There are a few ways to do this. I'm using something called a datastep from the libr package.

First, here is your data:

df <- data.frame(num_hhmem = c(6, 4, 4, 5, 4, NA, 8, NA),
                 ChildAge = c(9, 8, 10, 10, 9, NA, 8, NA),
                 hhm2_Age = c(36, 44, 52, 40, 33, NA, 37, NA),
                 hhm3_Age = c(34, 16, 53, 15, 15, NA, 39, NA),
                 hhm4_Age = c(15, 10, 92, 17, 11, NA, NA, NA),
                 hhm5_Age = c(7, NA, NA, 20, NA, NA, 10, NA),
                 hhm6_Age = c(11, NA, NA, NA, NA, NA, 6, NA),
                 hhm7_Age = c(NA, NA, NA, NA, NA, NA, 68, NA),
                 hhm8_Age = c(NA, NA, NA, NA, NA, NA, 78, NA),
                 hhm9_Age = c(NA, NA, NA, NA, NA, NA, NA, NA))

Then I set up the datastep with an array for the columns you want to iterate. Also I also set up a childCount variable with the value of 0 to start with. The datastep will loop through the dataframe row by row. So then you just iterate through the array and add any children to the childCount variable.

library(libr)

res <- datastep(df, 
                arrays = list(ages = dsarray("ChildAge", "hhm2_Age", "hhm3_Age",
                                             "hhm4_Age", "hhm5_Age", "hhm6_Age",
                                             "hhm7_Age", "hhm8_Age", "hhm9_Age")),
                calculate = { childCount <- 0 },
                drop = "age",
                {
                  
                  for(age in ages) {

                    if (!is.na(ages[age])) {
                      if (ages[age] < 18)
                        childCount <- childCount + 1
                    
                    }
                  }
                  
                })

Here are the results:

res
#   num_hhmem ChildAge hhm2_Age hhm3_Age hhm4_Age hhm5_Age hhm6_Age hhm7_Age hhm8_Age hhm9_Age childCount
# 1         6        9       36       34       15        7       11       NA       NA       NA          4
# 2         4        8       44       16       10       NA       NA       NA       NA       NA          3
# 3         4       10       52       53       92       NA       NA       NA       NA       NA          1
# 4         5       10       40       15       17       20       NA       NA       NA       NA          3
# 5         4        9       33       15       11       NA       NA       NA       NA       NA          3
# 6        NA       NA       NA       NA       NA       NA       NA       NA       NA       NA          0
# 7         8        8       37       39       NA       10        6       68       78       NA          3
# 8        NA       NA       NA       NA       NA       NA       NA       NA       NA       NA          0

Here is another potential solution using tidyverse functions and the data formatted by @David J. Bosak:

df1 <- data.frame(num_hhmem = c(6, 4, 4, 5, 4, NA, 8, NA),
                  ChildAge = c(9, 8, 10, 10, 9, NA, 8, NA),
                  hhm2_Age = c(36, 44, 52, 40, 33, NA, 37, NA),
                  hhm3_Age = c(34, 16, 53, 15, 15, NA, 39, NA),
                  hhm4_Age = c(15, 10, 92, 17, 11, NA, NA, NA),
                  hhm5_Age = c(7, NA, NA, 20, NA, NA, 10, NA),
                  hhm6_Age = c(11, NA, NA, NA, NA, NA, 6, NA),
                  hhm7_Age = c(NA, NA, NA, NA, NA, NA, 68, NA),
                  hhm8_Age = c(NA, NA, NA, NA, NA, NA, 78, NA),
                  hhm9_Age = c(NA, NA, NA, NA, NA, NA, NA, NA))

df2 <- df1 %>%
  rowwise() %>%
  mutate(total_kids = rowSums(across(-c(num_hhmem), ~sum(.x <= 18, na.rm = TRUE))))
df2
#> # A tibble: 8 × 11
#> # Rowwise: 
#>   num_hhmem ChildAge hhm2_Age hhm3_Age hhm4_Age hhm5_Age hhm6_Age hhm7_Age hhm8_Age hhm9_Age total_kids
#>       <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl> <lgl>         <dbl>
#> 1         6        9       36       34       15        7       11       NA       NA NA                4
#> 2         4        8       44       16       10       NA       NA       NA       NA NA                3
#> 3         4       10       52       53       92       NA       NA       NA       NA NA                1
#> 4         5       10       40       15       17       20       NA       NA       NA NA                3
#> 5         4        9       33       15       11       NA       NA       NA       NA NA                3
#> 6        NA       NA       NA       NA       NA       NA       NA       NA       NA NA                0
#> 7         8        8       37       39       NA       10        6       68       78 NA                3
#> 8        NA       NA       NA       NA       NA       NA       NA       NA       NA NA                0

Or, if you just want the counts in a dataframe on their own:

df3 <- df1 %>%
  rowwise() %>%
  summarise(total_kids = rowSums(across(-c(num_hhmem), ~sum(.x <= 18, na.rm = TRUE))))
df3
#> # A tibble: 8 × 1
#>   total_kids
#>        <dbl>
#> 1          4
#> 2          3
#> 3          1
#> 4          3
#> 5          3
#> 6          0
#> 7          3
#> 8          0
Related