DataFrame: добавить столбец, значения которого являются квантильным числом/рангом существующего столбца?

У меня есть DataFrame с некоторыми столбцами. Я хотел бы добавить новый столбец, где каждое значение строки является квантильным рангом одного существующего столбца.

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

Пример: если это мой DataFrame

df = pd.DataFrame(np.array([[1, 1], [2, 10], [3, 100], [4, 100]]), columns=['a', 'b'])

   a    b
0  1    1
1  2   10
2  3  100
3  4  100

и я хотел бы знать квантильный номер (используя 2 квантиля) столбца b. Я ожидал такого результата:

   a    b  quantile
0  1    1    1
1  2   10    1
2  3  100    2
3  4  100    2

person luca    schedule 13.07.2016    source источник
comment
Я думаю, вам нужен DataFrame.quantile с q=[0, 0.25, 0.5, 0.75, 1]... Тогда вы сможете рейтинг в этом столбце   -  person jeyoor    schedule 13.07.2016
comment
А, это имеет смысл. Спасибо!   -  person luca    schedule 13.07.2016
comment
Пожалуйста, разместите комментарий выше в качестве ответа ниже.   -  person jeyoor    schedule 13.07.2016
comment
Я пытаюсь применить ваше предложение, но, похоже, я не могу этого сделать.   -  person luca    schedule 13.07.2016
comment
Похоже, что для возврата результирующего кадра данных из квантиля в исходный кадр данных требуется несколько дополнительных операций... Работа над редактированием   -  person jeyoor    schedule 13.07.2016
comment
Новое редактирование с примером кода... как это работает для вас?   -  person jeyoor    schedule 13.07.2016


Ответы (4)


Я обнаружил, что это довольно просто:

df['quantile'] = pd.qcut(df['b'], 2, labels=False)

   a    b  quantile
0  1    1         0
1  2   10         0
2  3  100         1
3  4  100         1

Интересно узнать «разницу между pandas.qcut и pandas. вырезать"

person luca    schedule 16.08.2016
comment
Обычно это выдает SettingWithCopyWarning, по крайней мере, в 0.16.1 (которую я все еще использую). - person feetwet; 26.12.2016
comment
@feetweet, спасибо за сообщение о проблеме со старой версией pandas (‹= 0.16.1) и за альтернативное решение. Во всяком случае для версий ›= 0.18 работает без предупреждения. - person luca; 28.12.2016

Вы можете использовать DataFrame.quantile с q= [0,25, 0,5, 0,75] в существующем столбце для создания квартильного столбца.

Затем вы можете DataFrame.rank на этом квартильный столбец.

Ниже приведен пример добавления столбца квартилей:

import pandas as pd

d = {'one' : pd.Series([40., 45., 50., 55, 60, 65], index=['val1', 'val2', 'val3', 'val4', 'val5', 'val6'])}
df = pd.DataFrame(d)

quantile_frame = df.quantile(q=[0.25, 0.5, 0.75])
quantile_ranks = []
for index, row in df.iterrows():
    if (row['one'] <= quantile_frame.ix[0.25]['one']):
        quantile_ranks.append(1)
    elif (row['one'] > quantile_frame.ix[0.25]['one'] and row['one'] <= quantile_frame.ix[0.5]['one']):
        quantile_ranks.append(2)
    elif (row['one'] > quantile_frame.ix[0.5]['one'] and row['one'] <= quantile_frame.ix[0.75]['one']):
        quantile_ranks.append(3)
    else:
        quantile_ranks.append(4)

df['quartile'] = quantile_ranks

Примечание. Вероятно, есть более идиоматический способ сделать это с помощью Pandas... но это выше моего понимания.

person jeyoor    schedule 13.07.2016

df['quantile'] = pd.qcut(df['b'], 2, labels=False), кажется, имеет тенденцию выбрасывать SettingWithCopyWarning.

Единственный найденный мною общий способ сделать это без жалоб выглядит следующим образом:

quantiles = pd.qcut(df['b'], 2, labels=False)
df = df.assign(quantile=quantiles.values)

Это назначит значения квантильного ранга как новый столбец DataFrame df['quantile'].

Здесь дано решение для более общего случая, когда требуется разбить разрез на несколько столбцов.

person feetwet    schedule 26.12.2016

df.sort_values(['b'],inplace = True)
df.reset_index(inplace = True,drop = True)
df.reset_index(inplace = True)
df.rename(columns = {'index':'row_num'},inplace = True)
df['quantile'] = df['row_num'].apply(lambda x: math.ceil(10*(x+1)/df.shape[0]))

Раньше я использовал это, но я думаю, что могу использовать квантили

person Abhishek Singh    schedule 08.02.2019