Отобрать статистически значимое количество значений в группе в датафрейме

Имеется фрейм данных:

data = {'id_поставки': ['101','102','103','250','255','260','290','0112', '7011', '0151','06611', '600', '56','96', '59', '235', '785'],
'месяц_поставки': ['январь','март','январь','март', 'сентябрь','март','март', 'март', 'ноябрь', 'январь','январь', 'март', 'январь','июль', 'март', 'март', 'апрель']        
}
dates = pd.DataFrame(data, columns = ['id_поставки', 'месяц_поставки'])

введите сюда описание изображения

В котором есть id поставки и месяц поставки.

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

Ожидаемый результат:

введите сюда описание изображения

Для вычисления статистически значимого числа поставок для каждого месяца используется функция sample_size

def sample_size(population_size, confidence_level=90, confidence_interval=50):
    confidence_level_constants = {
        50: 0.67,
        68: 0.99,
        90: 1.64,
        95: 1.96,
        99: 2.57
    }
    p = 0.5
    e = confidence_interval / 100.0
    N = population_size
    n_0 = 0.0
    n = 0.0
    Z = confidence_level_constants[confidence_level]
    n_0 = ((Z**2) * p * (1-p)) / (e**2)
    n = n_0 / (1 + ((n_0 - 1) / float(N)) )
    return int(math.ceil(n))

Вычислить необходимый размер выборки для каждого месяца можно, применив sample_size к колонке id_поставки при группировке: data.groupby('месяц_поставки',as_index=False).agg({'id_поставки':'count'})

Как получить таблицу из ожидаемого результата?


Ответы (1 шт):

Автор решения: Pak Uula

У вас уже почти всё готово.

Сначала нужно сделать серию с необходимым числом поставок для каждого месяца:

month_size = dates.groupby('месяц_поставки')\
    .count()['id_поставки']\
    .apply(sample_size) 

Результат

месяц_поставки
апрель      1
июль        1
март        3
ноябрь      1
сентябрь    1
январь      3

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

Выборка строк. Для примера возьмём январь:

m = 'январь'
dates[dates['месяц_поставки'] == m][:month_size[m]]

Результат введите сюда описание изображения

Склеивание в один фрейм: pd.concat

Итого:

pd.concat([
    dates[dates['месяц_поставки'] == m][:month_size[m]]  
    for m in month_size.index
])

введите сюда описание изображения

Если вам нужно, чтобы нумерация строк была с нуля, то добавьте вызов метода reset_index:

pd.concat([
    dates[dates['месяц_поставки'] == m][:month_size[m]]  
    for m in month_size.index
]).reset_index(drop=True)
→ Ссылка