Выбор образца для соответствия распределению переменных в другом наборе данных - PullRequest
3 голосов
/ 06 марта 2020

Пусть x будет набором данных с 5 переменными и 15 наблюдениями:

age gender  height  weight  fitness
17  M   5.34    68  medium
23  F   5.58    55  medium
25  M   5.96    64  high
25  M   5.25    60  medium
18  M   5.57    60  low
17  F   5.74    61  low
17  M   5.96    71  medium
22  F   5.56    75  high
16  F   5.02    56  medium
21  F   5.18    63  low
20  M   5.24    57  medium
15  F   5.47    72  medium
16  M   5.47    61  high
22  F   5.88    73  low
18  F   5.73    62  medium

Частоты значений для пригодной переменной следующие: низкая = 4, средняя = 8, высокая = 3.

Предположим, у меня есть другой набор данных y с теми же 5 переменными, но 100 наблюдениями. Частоты значений для переменной пригодности в этом наборе данных следующие: низкая = 42, средняя = 45, высокая = 13.

Используя R, как я могу получить репрезентативную выборку из y, такую ​​что выборка Пригодность близко соответствует распределению пригодности по x?

Моими первоначальными идеями было использование функции выборки в R и назначение взвешенных вероятностей для аргумента prob. Однако использование вероятностей приведет к точному совпадению распределения частот. Моя цель - получить достаточно близкое совпадение при максимальном размере выборки.

Кроме того, предположим, что я sh добавлю еще одно ограничение, в котором распределение пола также должно точно соответствовать распределению x?

Ответы [ 2 ]

2 голосов
/ 06 марта 2020

Минимальная частота у вас равна 13, что соответствует «высокому» уровню физической подготовки. Таким образом, вы не можете попробовать больше, чем это число. Это ваше первое ограничение. Вы хотите максимизировать размер своей выборки, поэтому вы выбираете все 13. Для соответствия пропорциям в x, 13 должно составлять 20% от вашего общего значения, что означает, что ваше общее число должно составлять 65 (13 / 0,2). Следовательно, другие частоты должны быть 17 (низкие) и 35 (умеренные). Поскольку у вас достаточно этих уровней физической подготовки, вы можете взять это в качестве образца. Если какая-либо из других частот выборки превысит число в y, у вас будет другое ограничение, и вам придется его соответствующим образом скорректировать.

Для выборки сначала нужно выбрать все записи с «высокой» пригодностью ( выборка с уверенностью). Далее, выборка из других уровней отдельно (стратифицированная случайная выборка). Наконец, объедините все три.

Пример:

rm(list=ls())
# set-up the data (your "y"):
df <- data.frame(age=round(rnorm(100, 20, 5)), 
                 gender=factor(gl(2,50), labels=LETTERS[c(6, 13)]), 
                 height=round(rnorm(100, 12, 3)), 
                 fitness=factor(c(rep("low", 42), rep("medium", 45), rep("high", 13)), 
                                levels=c("low","medium","high")))

Создание подмножеств для выборки:

fit.low <- subset(df, subset=fitness=="low")
fit.medium <- subset(df, subset=fitness=="medium")
fit.high <- subset(df, subset=fitness=="high")

Образец 17 из группы с низким уровнем подготовки (40,5% или 26,7%) от общего числа).

fit.low_sam <- fit.low[sample(1:42, 17),]

Образец 35 из группы средней подготовленности (77,8% или 53,8% от общего числа).

fit.med_sam <- fit.medium[sample(1:45, 35),]

Объедините их все.

fit.sam <- rbind(fit.low_sam, fit.med_sam, fit.high)

Я пытался сделать это, используя функции sample_n и sample_frac из dplyr, но я думаю, что эти функции не позволяют вам делать стратифицированную выборку с различными пропорциями.

library(dplyr)
df %>%
  group_by(fitness) %>%
  sample_n(size=c(17,35,13), weight=c(0.27, 0.53, 0.2))
# Error

Но выборка пакет, безусловно, может сделать это. Стратифицированная случайная выборка из фрейма данных

library(sampling)
s <- strata(df, "fitness", size=c(17,35,13), "srswor")
getdata(df, s)
1 голос
/ 06 марта 2020

Подумайте об использовании rmultinom для подготовки отсчетов проб на каждом уровне пригодности.

Подготовьте данные (я использовал y подготовку от @Edward answer)

x <- read.table(text = "age gender  height  weight  fitness
17  M   5.34    68  medium
23  F   5.58    55  medium
25  M   5.96    64  high
25  M   5.25    60  medium
18  M   5.57    60  low
17  F   5.74    61  low
17  M   5.96    71  medium
22  F   5.56    75  high
16  F   5.02    56  medium
21  F   5.18    63  low
20  M   5.24    57  medium
15  F   5.47    72  medium
16  M   5.47    61  high
22  F   5.88    73  low
18  F   5.73    62  medium", header = TRUE)

y <- data.frame(age=round(rnorm(100, 20, 5)), 
                 gender=factor(gl(2,50), labels=LETTERS[c(6, 13)]), 
                 height=round(rnorm(100, 12, 3)), 
                 fitness=factor(c(rep("low", 42), rep("medium", 45), rep("high", 13)), 
                                levels=c("low","medium","high")))

Сейчас процедура выборки: UPD: Я изменил код для двух переменных case (пол и пригодность)

library(tidyverse)

N_SAMPLES = 100

# Calculate frequencies
freq <- x %>%
    group_by(fitness, gender) %>% # You can set any combination of factors
    summarise(freq = n() / nrow(x)) 

# Prepare multinomial distribution
distr <- rmultinom(N_SAMPLES, 1, freq$freq)
# Convert to counts
freq$counts <- rowSums(distr)

# Join y with frequency for further use in sampling
y_count <- y %>% left_join(freq)

# Perform sampling using multinomial distribution counts
y_sampled <- y_count %>%
    group_by(fitness, gender) %>% # Should be the same as in frequencies calculation
    # Check if count is greater then number of observations
    sample_n(size = ifelse(n() > first(counts), first(counts), n()),
        replace = FALSE) %>%
    select(-freq, -counts)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...