Builds a population one group at a time from a table of group
types, such as household compositions, returning each node's
group id and the attributes its group type implies. The result
supplies both the grouping attribute for netclique() and the
nodal attributes for the dynamic layers of the same model.
Arguments
- n
Number of nodes in the population.
- types
The group types. Either a character vector in which each element lists the members of one type separated by
sep, such asc("adult", "adult adult", "adult adult child"); a named numeric vector whose names are those templates and whose values are the type weights, in which caseprobis taken from the values; or a list ofdata.frames, each with one row per member and any number of attribute columns, for types that carry more than one attribute per member.- prob
Sampling weights for the types, one per type. They are normalized to sum to one. The default draws every type with equal probability.
- attr.name
Name of the attribute column in the result when
typesis a character vector.- sep
Separator between member labels within a character template.
Value
A data.frame with one row per node and n rows, in group order:
group (integer group id, 1 to the number of groups), type (index of
the type the group was drawn from), and the attribute columns (one column
named attr.name for character templates, or the columns of the
data.frames in types).
Details
Types are drawn with replacement until the population reaches n. The
final group is drawn from the types whose size fits the remaining slots, so
that the population has exactly n nodes without cutting a group short.
When no type fits (no type has size one, and the remainder is smaller than
every type), the last group is truncated and a message says so.
The realized distribution of group types, and so of group sizes and of the
attribute values, follows the prob weights up to sampling variation; the
expected mean group size is the weighted mean of the type sizes. The
expected share of nodes with a given attribute value is the weighted share
of that value among the members of all types. Tune the type table to hit
both.
See also
netclique() to turn the group column into a clique
layer, and assign_groups() for the reverse problem of assigning group
ids to a population whose attributes already exist.
Examples
# Household types by age group, weights chosen so that every child lives
# with at least one adult and about a quarter of older adults live alone
hh_types <- c("adult" = 0.15,
"adult adult" = 0.20,
"elderly" = 0.12,
"elderly elderly" = 0.10,
"adult elderly" = 0.03,
"adult child" = 0.05,
"adult adult child" = 0.15,
"adult adult child child" = 0.15,
"adult adult child elderly" = 0.05)
pop <- sample_groups(1000, hh_types, attr.name = "age")
head(pop, 10)
#> group type age
#> 1 1 2 adult
#> 2 1 2 adult
#> 3 2 2 adult
#> 4 2 2 adult
#> 5 3 2 adult
#> 6 3 2 adult
#> 7 4 4 elderly
#> 8 4 4 elderly
#> 9 5 2 adult
#> 10 5 2 adult
table(tabulate(pop$group)) # household size distribution
#>
#> 1 2 3 4
#> 107 155 77 88
prop.table(table(pop$age)) # person-level age distribution
#>
#> adult child elderly
#> 0.585 0.252 0.163
# Every child shares a household with an adult
has_adult <- tapply(pop$age == "adult", pop$group, any)
all(has_adult[as.character(pop$group[pop$age == "child"])])
#> [1] TRUE
# Types with more than one attribute per member
types <- list(
data.frame(age = "adult", sex = "F"),
data.frame(age = c("adult", "adult"), sex = c("F", "M")),
data.frame(age = c("adult", "adult", "child"), sex = c("F", "M", "F"))
)
pop2 <- sample_groups(100, types, prob = c(0.3, 0.4, 0.3))
head(pop2)
#> group type age sex
#> 1 1 3 adult F
#> 2 1 3 adult M
#> 3 1 3 child F
#> 4 2 2 adult F
#> 5 2 2 adult M
#> 6 3 1 adult F