Вычислить среднее значение ранга для нескольких столбцов вручную - PullRequest
2 голосов
/ 27 сентября 2019

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

import pandas as pd
df = pd.DataFrame(data={'String':['a','a','a','a','b','b','c','c','c','c'],'Integer':[1,2,3,3,1,3,6,4,4,4]})
print(df)
  String  Integer
0      a        1
1      a        2
2      a        3
3      a        3
4      b        1
5      b        3
6      c        6
7      c        4
8      c        4
9      c        4

Идея состоит в том, чтобы иметь возможность создавать ранжирование, которое ранжирует каждую строку по String в порядке убывания и целому в порядке возрастания, это будет вывод:

    Rank String  Integer
0      2      c        4           
1      2      c        4         
2      2      c        4          
3      4      c        6          
4      5      b        1          
5      6      b        3         
6      7      a        1            
7      8      a        2            
8    9.5      a        3            
9    9.5      a        3        

ТакПока это то, что мне удается сделать, но у меня возникают проблемы с тем, как сгенерировать «среднее» при распределении ранга.

df['concat_values'] = df['String'] + df['Integer'].astype(str)  
df = df.sort_values(['String','Integer'],ascending=[False,True])
df = df.reset_index(drop=True).reset_index()
df['repeated'] = df.groupby('concat_values')['concat_values'].transform('count')
df['pre_rank'] = df['index'] + 1
df = df.sort_values('pre_rank')
df = df.drop('index',axis=1)
print(df)
  String  Integer concat_values  repeated  pre_rank
0      c        4            c4         3         1
1      c        4            c4         3         2
2      c        4            c4         3         3
3      c        6            c6         1         4
4      b        1            b1         1         5
5      b        3            b3         1         6
6      a        1            a1         1         7
7      a        2            a2         1         8
8      a        3            a3         2         9
9      a        3            a3         2        10

Я думал об использовании некоторой фильтрации или формулы, чтобы пристолбец repeated принимает значение больше единицы, pre_rank получает примененную функцию, которая возвращает среднее значение, но эта функция не может быть обобщена для всех строк, она будет работать для первой, но она дастболее высокое значение для второго (потому что pre_rank теперь имеет более высокое значение).Я полагаю, что я просто пропускаю последний шаг к тому, чтобы сделать это, но не могу решить это.Спасибо!

Ответы [ 2 ]

5 голосов
/ 27 сентября 2019

sort + ngroup + rank.

Требуется указать sort=False в группе, чтобы метки ngroup генерировались в порядке сортировки.

df = df.sort_values(['String', 'Integer'], ascending=[False, True])
df['rank'] = df.groupby(['String', 'Integer'], sort=False).ngroup().rank()

  String  Integer  rank
7      c        4   2.0
8      c        4   2.0
9      c        4   2.0
6      c        6   4.0
4      b        1   5.0
5      b        3   6.0
0      a        1   7.0
1      a        2   8.0
2      a        3   9.5
3      a        3   9.5
3 голосов
/ 27 сентября 2019

Мой метод:

df = df.sort_values(['String','Integer'], ascending=[False, True])
df['rank'] = np.arange(len(df)) + 1
df['rank'] = df.groupby(['String', 'Integer'])['rank'].transform('mean')

Вывод:

  String  Integer  rank
7      c        4   2.0
8      c        4   2.0
9      c        4   2.0
6      c        6   4.0
4      b        1   5.0
5      b        3   6.0
0      a        1   7.0
1      a        2   8.0
2      a        3   9.5
3      a        3   9.5
...