2016-09-08 4 views
1
import pandas as pd 

data = { 
    "K": ["A", "A", "B", "B", "B"], 
    "LABEL": ["X123", "X123", "X21", "L31", "L31"], 
    "VALUE": [1, 3, 1, 2, 5.0] 
} 

df = pd.DataFrame.from_dict(data) 

output = """ 
    K LABEL VALUE 
0 A X12 1.0 
1 A X12 3.0 
2 B X21 1.0 
3 B L31 2.0 
4 B L31 5.0 
""" 

Преобразование шаги

Для каждой группы (сгруппированные по K), найти FINAL_VALUE определено ниже.Агрегат Pandas DataFrame основан на условии, которое использует несколько столбцов?

Где ярлык или два типа Х__ и L__

# if LABEL is X___ then FINAL_VALUE = sum(VALUE) 
# if LABEL is L___ then FINAL_VALUE = count(VALUE) 
# else FINAL_VALUE = 0 

Результат трансформации

expected_output = """ 
K LABEL FINAL_VALUE 
A X12   4 
B X21   1 
B L31   2 
""" 

Как я могу добиться этого с помощью Панды?

EDIT1: Частично работает

In [17]: df.groupby(["K", "LABEL"]).agg({"VALUE": {"VALUE_SUM": "sum", "VALUE_COUNT": "count"}}) 
Out[17]: 
       VALUE   
     VALUE_COUNT VALUE_SUM 
K LABEL      
A X12    2  4.0 
B L31    2  7.0 
    X21    1  1.0 

edit2: Использование reset_index() завалить dataframe

In [18]: df2 = df.groupby(["K", "LABEL"]).agg({"VALUE": {"VALUE_SUM": "sum", "VALUE_COUNT": "count"}}) 

In [21]: df2.reset_index() 
Out[21]: 
    K LABEL  VALUE   
      VALUE_COUNT VALUE_SUM 
0 A X12   2  4.0 
1 B L31   2  7.0 
2 B X21   1  1.0 

EDIT3: Окончательная решение с использованием df.apply()

In [59]: df3 = df2.reset_index() 

In [60]: df3["FINAL_VALUE"] = df3.apply(lambda x: x["VALUE"]["VALUE_SUM"] if x["LABEL"].str.startswith("X").any() else x["VALUE"]["VALUE_COUNT"] , axis=1) 

In [61]: df3[["K", "LABEL", "FINAL_VALUE"]] 
Out[61]: 
    K LABEL FINAL_VALUE 

0 A X12   4.0 
1 B L31   2.0 
2 B X21   1.0 
+0

ОК, я вижу, что вы уже получили ответ на себе :) –

+0

@ vlad.rad еще не :-) Я почти там. Мне нужно получить точные столбцы. – tuxdna

ответ

2

Вы можете использовать DFGroupby.agg, как вы делали до последующей записи обобщенной функции, которая вычисляет необходимые требования с помощью str.startswith и возвращает нужный кадр, как показано:

def compute_multiple_condition(row): 
    if row['LABEL'].startswith('X'): 
     return row['sum'] 
    elif row['LABEL'].startswith('L'): 
      return row['count'] 
    else: 
     return 0 

df = df.groupby(['K','LABEL'])['VALUE'].agg({'sum': 'sum', 'count': 'count'}).reset_index() 
df['FINAL_VALUE'] = df.apply(compute_multiple_condition, axis=1).astype(int) 
df = df[['K', 'LABEL', 'FINAL_VALUE']] 
df 

    K LABEL FINAL_VALUE 
0 A X12   4 
1 B L31   2 
2 B X21   1 
+0

Для меня «startswith» дал ошибку: «AttributeError: (« Объект «Серии» не имеет атрибута «startswith» », u'occurred at index 0 ')'. Но вы дали правильный подход. – tuxdna

+0

Вам нужно использовать его вместе с 'str' accessor like' series.str.startswith() '. В моей функции он вычисляется по отдельным строкам, а не по всей серии как таковой, и поэтому аксессуар не требуется. –

+0

Кроме того, проверьте 'dtypes'. Столбец 'LABEL' должен иметь тип' object', чтобы он работал. –

0

вы можете попробовать кадр данных цепь :

result = (df.groupby(['K', 'LABEL']) 
      .apply(lambda frame: frame.VALUE.sum() 
           if frame.LABEL.iloc[0].startswith("X") else len(frame)) 
      .to_frame() 
      .rename({'0': 'FINAL_VALUE'}) 
     ) 
Смежные вопросы