2014-09-26 2 views
2

Мне нужно извлечь общее максимальное значение из пар строк, которые имеют общие значения в двух столбцах.groupby общие значения в двух столбцах

Общность между значениями в столбцах A и B. Строки 0 и 1 являются общими, 2 и 3, а 4 - сами по себе.

f = DataFrame([[1, 2, 30], [2, 1, 20], [2, 6, 15], [6, 2, 70], [7, 10, 35]], columns=['A', 'B', 'Value']) 
f 
    A B Value 
0 1 2  30 
1 2 1  20 
2 2 6  15 
3 6 2  70 
4 7 10  35 

Цель извлечь максимальные значения, так что конечный результат:

f_final = DataFrame([[1, 2, 30, 30], [2, 1, 20, 30], [2, 6, 15, 70], [6, 2, 70, 70], [7, 10, 35, 35]], columns=['A', 'B', 'Value', 'Max']) 
f_final 

    A B Value Max 
0 1 2  30 30 
1 2 1  20 30 
2 2 6  15 70 
3 6 2  70 70 
4 7 10  35 35 

Я мог бы это сделать, если есть способ, чтобы назначить ключ общего, не повторяя:

f_key = DataFrame([[1, 1, 2, 30], [1, 2, 1, 20], [2, 2, 6, 15], [2, 6, 2, 70], [3, 7, 10, 35]], columns=['key', 'A', 'B', 'Value']) 
f_key 

    key A B Value 
0 1 1 2  30 
1 1 2 1  20 
2 2 2 6  15 
3 2 6 2  70 
4 3 7 10  35 

Следуя с GroupBy и преобразования:

f_key['Max'] = f_key.groupby(['key'])['Value'].transform(lambda x: x.max()) 
f_key.drop('key', 1, inplace=True) 
f_key 

    A B Value Max 
0 1 2  30 30 
1 2 1  20 30 
2 2 6  15 70 
3 6 2  70 70 
4 7 10  35 35 

Вопрос 1: Как назначить этот общий ключ?

Вопрос 2: Есть ли лучший способ сделать это, минуя общий ключевой шаг

Приветствие ...

ответ

2

Вы можете отсортировать значения в столбцах A и B так, чтобы для каждой строки значение в A меньше или равно значению в B. После того, как значения упорядочены, то можно применить groupby-transform-max как обычно:

import pandas as pd 
df = pd.DataFrame([[1, 2, 30], [2, 1, 20], [2, 6, 15], [6, 2, 70], [7, 10, 35]], 
        columns=['A', 'B', 'Value']) 
mask = df['A'] > df['B'] 
df.loc[mask, ['A','B']] = df.loc[mask, ['B','A']].values 
df['Max'] = df.groupby(['A', 'B'])['Value'].transform('max') 

print(df) 

дает

A B Value Max 
0 1 2  30 30 
1 1 2  20 30 
2 2 6  15 70 
3 2 6  70 70 
4 7 10  35 35 

выше метода еще будет работать, даже если значения в A и B являются строками. Так, например,

df = DataFrame([['ab', 'ac', 30], ['ac', 'ab', 20], 
       ['cb', 'ca', 15], ['ca', 'cb', 70], 
       ['ff', 'zz', 35]], columns=['A', 'B', 'Value']) 

mask = df['A'] > df['B'] 
df.loc[mask, ['A','B']] = df.loc[mask, ['B','A']].values 
df['Max'] = df.groupby(['A', 'B'])['Value'].transform('max') 

дает

In [267]: df 
Out[267]: 
    A B Value Max 
0 ab ac  30 30 
1 ab ac  20 30 
2 ca cb  15 70 
3 ca cb  70 70 
4 ff zz  35 35 
+0

Благодаря @unutbu. Есть ли аналогичный подход со строками? df = DataFrame ([['ab', 'ac', 30], ['ac', 'ab', 20], ['cb', 'ca', 15], ['ca', ' cb ', 70], [' ff ',' zz ', 35]], columns = [' A ',' B ',' Value ']) – coredump

+0

А в этом случае геометрия не поможет - - если вы сначала не преобразуете значения в факторы. Но это, вероятно, отрицает преимущество скорости. – unutbu

+0

Используется категориальный и get_indexer. Кажется работать. Спасибо за помощь. с = pd.Categorical.from_array (df.A) IDX = c.levels DF [ 'А1'] = idx.get_indexer (df.A) DF [ 'В1'] = idx.get_indexer (DF. B) – coredump

Смежные вопросы