Переменный заголовок (или) n наибольший в группе по / мультииндексированным df - PullRequest
0 голосов
/ 14 июля 2020

В следующем фрейме данных df ...

import string, random
import pandas as pd
random.seed(1234)

sz = 1000
c = pd.Series(random.choice(string.ascii_uppercase[:8]) for _ in range(sz))
d = pd.Series(random.randint(0,30) for _ in range(sz))
v = pd.Series(random.randint(i, i+30) for i in range(sz))

df = pd.DataFrame({'c': c, 'd': d, 'v': v}) # the dataframe

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

hds = {'A': 2, 'B': 3, 'D': 1}

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

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

... который я получил с помощью следующего кода:

dfs = []

# require result by group of `c` and `d`
g = df.sort_values(['c', 'd'], ascending=[True, False]).groupby(['c', 'd'])

for s in hds.keys():
    dfs.append(g.apply(lambda x: x[x.c == s][['v']].head(hds[s])))

dfr = pd.concat(dfs)

dfr1 = dfr.reset_index().set_index('level_2')
dfr1.index.rename('orig_index', inplace=True)

Есть ли более быстрый способ векторизации для достижения вышеуказанного? Пробовал ...

g.apply(lambda x: x.head(y) for y in [hds[s] if s in hds else 0 for s in list(hds.keys())])

... но он дает:

TypeError: объект 'generator' не вызывается

1 Ответ

1 голос
/ 14 июля 2020

Найти максимальное значение для группы легко. Вы можете использовать df.describe(), чтобы получить max(). Соответствует ли это цели вашего вопроса?

df = df[(df['c'] == 'A')|(df['c'] == 'B')|(df['c'] == 'D')]
gb = df.groupby(['c','d'])
df1 = gb.describe()

df1.head()
        count   mean    std min 25% 50% 75% max
c   d                               
A   0   3.0 813.333333  127.472873  670.0   763.0   856.0   885.0   914.0
    1   6.0 611.333333  363.566592  141.0   313.5   803.0   824.5   939.0
    2   2.0 474.000000  593.969696  54.0    264.0   474.0   684.0   894.0
    3   5.0 344.000000  222.121588  57.0    249.0   278.0   543.0   593.0
    4   5.0 480.000000  261.788082  107.0   368.0   553.0   559.0   813.0

final = df1.iloc[:,7].reset_index()
final.columns = ['c','d','v']

final
    c   d   v
0   A   0   914.0
1   A   1   939.0
2   A   2   894.0
3   A   3   593.0
4   A   4   813.0
... ... ... ...
86  D   26  693.0
87  D   27  913.0
88  D   28  825.0
89  D   29  840.0
90  D   30  1007.0
91 rows × 3 columns
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...