Как я могу написать с нуля код для стратифицированной выборки по целевой переменной?

все, я пытаюсь создать с нуля (без использования sklearn libs), чтобы создать 5 образцов (длина df / 5), чтобы каждый из них имел ту же пропорцию целевой переменной (1), что и исходный набор данных. например у оригинала 5% больных раком, я хотел бы, чтобы каждый из моих 5 образцов также имел целевую переменную 5%. не уверен, как это сделать,

df_list=[]
n= round(len(df)/5)
for m in range(1,6):
    m = m*n
    print(df[:m])
    df_list.append(df[:m])

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

Это то, что вы ожидали? Если это так, я полагаю, я заслужил пятерку.

Caner Burc BASKAYA 11.12.2020 12:54
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
618
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решение:

import numpy as np
import math

def stratify(data, target='y', n=10):
    array = data.values
    y = data[target].values
    
    unique, counts = np.unique(data[target].values, return_counts=True)
    new_counts = counts * (n/sum(counts))
    new_counts = fit_new_counts_to_n(new_counts, n)
    
    selected_count = np.zeros(len(unique))
    selected_row_indices = []
    for i in range(array.shape[0]):
        if sum(selected_count) == sum(new_counts):
            break
        cr_target_value = y[i]
        cr_target_index = np.where(unique==cr_target_value)[0][0]
        if selected_count[cr_target_index] < new_counts[cr_target_index]:
            selected_row_indices.append(i)
            selected_count[cr_target_index] += 1
    row_indices_mask = np.array([x in selected_row_indices for x in np.arange(array.shape[0])])
    
    return pd.DataFrame(array[row_indices_mask], columns=data.columns)

Класс полезности:

def fit_new_counts_to_n(new_counts, n):
    decimals = [math.modf(x)[0] for x in new_counts]
    integers = [int(math.modf(x)[1]) for x in new_counts]
    arg_max = np.array(map(np.argmax, decimals))
    sorting_indices =  np.argsort(decimals)[::-1][:n]
    for i in sorting_indices:
        if sum(integers) < n:
            integers[i] += 1
        else:
            break
    return integers

Пример использования:

data = [[  3,   0],
        [ 54,   3],
        [  3,   1],
        [ 64,   1],
        [ 65,   0],
        [ 34,   1],
        [ 45,   2],
        [534,   2],
        [ 57,   1],
        [ 64,   3],
        [  5,   1],
        [ 45,   1],
        [546,   1],
        [  4,   2],
        [ 53,   3],
        [345,   2],
        [456,   2],
        [435,   3],
        [545,   1],
        [ 45,   3]]

data = pd.DataFrame(data, columns=['X1', 'y'])

stratified_data = stratify(data, target='y', n=10)

Результат:

      [[  3,   0],
       [ 54,   3],
       [  3,   1],
       [ 64,   1],
       [ 34,   1],
       [ 45,   2],
       [534,   2],
       [ 57,   1],
       [ 64,   3],
       [ 53,   3]]

спасибо, а что делает новый счет?? counts * (n/sum(counts))<-- что здесь должен делать n

Maths12 11.12.2020 14:18

np.array([x in selected_row_indices for x in np.arange(20)]) <-- также почему здесь выбрано 20?

Maths12 11.12.2020 14:20

Поменял просто на пробу, теперь поменял как положено спасибо за отзыв

Caner Burc BASKAYA 11.12.2020 14:24

@Maths12 Maths12 Hi n - это новое количество строк в результирующем фрейме данных. Если вы хотите получить 5 образцов после стратификации, вы можете просто установить n равным 5. new_count — это массив для предполагаемых (предполагаемых) номеров каждого класса (целевого типа переменной) после стратификации.

Caner Burc BASKAYA 11.12.2020 14:36

спасибо за это, это работает, но довольно медленно, в основном я хочу делать стратифицированную выборку на постоянно увеличивающихся фрагментах моего полного набора данных, например. если его длина 10 000, я хочу разбить его на увеличивающиеся интервалы, например. 1-й — 2000, второй — 4000, третий — 6000 и так далее, сохраняя пропорции классов.

Maths12 11.12.2020 15:33

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

Caner Burc BASKAYA 11.12.2020 15:35

Другие вопросы по теме