2016-05-17 3 views
0

У меня есть сгруппированный фрейм данных, и я хочу фильтровать значения внутри каждой группы в зависимости от этих значений.Фильтр внутри групп Pandas

Я пробовал:

figure_cols = list("ABC") 

def get_threshold_for_IV(gr_vals): 
    return (gr_vals[figure_cols].max())/(gr_vals["A"].count()) 

def filter_IV(group): 
    A_tr, B_tr, C_tr = get_threshold_for_IV(group) 
    return group[(group.A >= A_tr) & (group.B >= B_tr) & (group.C >= C_tr)] 

# 1 attempt 
grouped.apply(filter_IV) 

# 2 attempt 
for name, group in grouped: 
    A_tr, B_tr, C_tr = get_threshold_for_IV(group) 
    group = group[(group.A < A_tr) & (group.B < B_tr) & (group.C < C_tr)] 

Но ничего не работает. Данные не изменяются. Мои функции прекрасно работают. Если я вставляю print в цикле, я вижу результат фильтрации.

Другое дело, я должен сказать, что я хочу иметь сгруппированных объект после работы фильтра, чтобы сделать дальнейшие манипуляции

Я читал документы, но, похоже, я слеп к этому. Может ли кто-нибудь помочь?

EDIT

Добавлено самодостаточными пример:

import numpy as np 
import pandas as pd 

df = pd.DataFrame({'gr' : ['foo', 'bar', 'foo', 'bar', 
         'foo', 'bar', 'foo', 'foo'], 
        'A' : np.arange(8), 
        'B' : np.random.randn(8), 
        'C' : np.random.randn(8)}) 

def filter_gt_3(group): 
    return group[group.A < 3] 

grouped = df.groupby('gr') 
for name, group in grouped: 
    print 'group name: %s' % name 
    print group 
    group = filter_gt_3(group) 
    print "\nfiltered" 
    print group 


print '\n----------\n' 
print 'Nothing filtered:\n' 
for name, group in grouped: 
    print 'group name: %s' % name 
    print group 

Выходной

group name: bar 
    A   B   C gr 
1 1 1.486028 -0.382597 bar 
3 3 -0.501757 -0.771807 bar 
5 5 -0.836930 -1.514824 bar 

filtered 
    A   B   C gr 
1 1 1.486028 -0.382597 bar 

group name: foo 
    A   B   C gr 
0 0 0.678104 -0.940245 foo 
2 2 1.539903 1.460493 foo 
4 4 -0.033421 -1.078566 foo 
6 6 1.146298 0.039721 foo 
7 7 1.095707 -1.032275 foo 

filtered 
    A   B   C gr 
0 0 0.678104 -0.940245 foo 
2 2 1.539903 1.460493 foo 

---------- 

Nothing filtered: 

group name: bar 
    A   B   C gr 
1 1 1.486028 -0.382597 bar 
3 3 -0.501757 -0.771807 bar 
5 5 -0.836930 -1.514824 bar 
group name: foo 
    A   B   C gr 
0 0 0.678104 -0.940245 foo 
2 2 1.539903 1.460493 foo 
4 4 -0.033421 -1.078566 foo 
6 6 1.146298 0.039721 foo 
7 7 1.095707 -1.032275 foo 
+0

Можете ли вы предоставить автономный, исполняемый пример, демонстрирующий проблему? – BrenBarn

+0

@BrenBarn Я добавил пример –

ответ

1

Выполнение group = filter_gt_3(group) не изменяет исходные данные. Он просто назначает отфильтрованные данные локальной переменной с именем group. Аналогично, просто вызов groupby.apply (как в вашем первом примере) ничего не меняет. Если вы хотите что-либо сделать с отфильтрованными данными, вам необходимо использовать значение , возвращенное этими операциями.

Если вы хотите, чтобы получить отфильтрованные данные, сделать что-то вроде

new_data = df.groupby('gr').apply(filter_gt_3) 

Обратите внимание, что это также не будет изменять исходные данные: он создает новый DataFrame и присваивает его new_data. Вы можете присвоить его исходному имени, если хотите (например, df = df.groupby...)

+0

Да, я это понимаю. Итак, чтобы выполнять другие манипуляции с одними и теми же группами, я должен снова «сгруппировать»? –

+0

@ re-gor: Да. (Или вы можете написать функцию, которая делает все необходимые действия за один раз.) – BrenBarn

+0

спасибо, иногда панды выглядят для меня неочевидными. –

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