Назначьте остатки определенным ячейкам в pandas.qcut ()

1

Я пытаюсь реплицировать определенный метод приписывания записей в децили, и есть pandas.qcut() которая делает хорошую работу. Моя единственная проблема заключается в том, что не существует метода для привязки неравномерного числа к определенному ящику, как это обозначается методом, который я пытаюсь реплицировать.

Это мой пример:

num = np.random.rand(153, 1)
my_list = map(lambda x: x[0], num)
ser = pd.Series(my_list)
bins = pd.qcut(ser, 10, labels=False)
bins.value_counts()

Какие результаты:

9    16
4    16
0    16
8    15
7    15
6    15
5    15
3    15
2    15
1    15

Есть 7 с 15 и 3 с 16, то, что я хотел бы сделать, это указать ячейки, которые будут получать 16 записей:

9    16 <
4    16
0    16
8    15
7    15
6    15
5    15 <
3    15
2    15 <
1    15

Возможно ли это с помощью pd.qcut?

Теги:
pandas

1 ответ

0
Лучший ответ

Поскольку ответа не было и попросить нескольких людей, это казалось невозможным, я объединил функцию, которая делает это:

 def defined_qcut(df, value_series, number_of_bins, bins_for_extras, labels=False):
    if max(bins_for_extras) > number_of_bins or any(x < 0 for x in bins_for_extras):
        raise ValueError('Attempted to allocate to a bin that doesnt exist')
    base_number, number_of_values_to_allocate = divmod(df[value_series].count(), number_of_bins)
    bins_for_extras = bins_for_extras[:number_of_values_to_allocate]
    if number_of_values_to_allocate == 0:
        df['bins'] = pd.qcut(df[value_series], number_of_bins, labels=labels)
        return df
    elif number_of_values_to_allocate > len(bins_for_extras):
        raise ValueError('There are more values to allocate than the list provided, please select more bins')
    bins = {}
    for i in range(number_of_bins):
        number_of_values_in_bin = base_number
        if i in bins_for_extras:
            number_of_values_in_bin += 1
        bins[i] = number_of_values_in_bin
    df1 = df.copy()
    df1['rank'] = df1[value_series].rank()
    df1 = df1.sort_values(by=['rank'])
    df1['bins'] = 0
    row_to_start_allocate = 0
    row_to_end_allocate = 0
    for bin_number, number_in_bin in bins.items():
        row_to_end_allocate += number_in_bin
        bins.update({bin_number: [number_in_bin, row_to_start_allocate, row_to_end_allocate]})
        row_to_start_allocate = row_to_end_allocate
    conditions = [df1['rank'].iloc[v[1]: v[2]] for k, v in bins.items()]
    series_to_add = pd.Series()
    for idx, series in enumerate(conditions):
        series[series > -1] = idx
        series_to_add = series_to_add.append(series)
    df1['bins'] = series_to_add
    df1 = df1.reset_index()
    return df1

Это некрасиво, но это делает работу. Вы передаете в dataframe, имя столбца со значениями и упорядоченный список бункеров, где должны быть выделены любые дополнительные значения. Я бы с удовольствием посоветовал, как улучшить этот код.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню