2016-08-07 4 views
0

Может быть, это глупый вопрос, но я запутался между ними, и логика применения метода groupby в этом случае будет оценена по достоинству.groupby + Арифметическая операция на pandas dataframe в python

У меня есть dataframe как

id NAME TYPE SCORE title 
123 DDLJ  cat1 1-6  5 
123 DDLJ  cat1 9-10 25 
123 DDLJ  cat1  N  5 
456 Satya cat2 9-10 1 
456 Satya cat2 N  3 
222 India cat2 1-6  1 

Мне нужно выяснить, для groupof (ID NAME TYPE) столбец с именем «cat_score» должен быть сформирован с логикой «для этой группы [названия для SCORE (9 -10) - название для SCORE (1-6)]/[сумма заголовка этой группы] "

#ex for group 123, DDLJ cat1 
cat score = (title at SCORE "9-10" - title at SCORE "1-6")/(Sum of title of that group) 
      = (25 - 5)/(35) 
      = 0.58 

Примечание :: Есть 3 типа SCORE [" 9-10" , «1-6 "," N "]. Поэтому, если для любой группы какая-либо из категории баллов не найдена, ее следует рассматривать как 0 или ее можно игнорировать.

Мой последний dataframe должен выглядеть

id NAME TYPE SCORE title Cat_Score 
123 DDLJ  cat1 1-6  5  0.58 
123 DDLJ  cat1 9-10 25 0.58 
123 DDLJ  cat1  N  5  0.58 
456 Satya cat2 9-10 1  0.34 
456 Satya cat2 N  3  0.34 
222 India cat2 1-6  1  -1 

Пожалуйста Suggest.

Я попытался, взяв одну группу

s = round((int(df[(df['id']=='123') & (df['NAME'] == 'DDLJ') & (df['TYPE']=='cat1') & (df['SCORE']=='9-10')]['title'].values[0]) - int(df[(df['id']=='123') & (df['NAME'] == 'DDLJ') & (df['TYPE']=='cat1') & (df['SCORE']=='1-6')]['title'].values[0]))/(int(df['title'].sum())),2) 
s = 0.58 

Но для всех групп, я путаюсь, как повторить.

+0

Вы можете проверить результат для второй группы? Разве это не должно быть '(1-0)/4 = 0,25' – ayhan

+0

@ ayhan-yes вы правы – Satya

ответ

2

Я думаю, было бы проще, если сначала изменить ваше DataFrame:

df2 = df.set_index(['id', 'NAME', 'TYPE']).pivot(columns='SCORE').fillna(0) 
df2.columns = df.columns.droplevel(0) 
df2 
Out: 
SCORE   1-6 9-10 N 
id NAME TYPE     
123 DDLJ cat1 5.0 25.0 5.0 
222 India cat2 1.0 0.0 0.0 
456 Satya cat2 0.0 1.0 3.0 

Теперь вы можете сделать эти операции более легко:

(df['9-10'] - df['1-6'])/df.sum(axis=1) 
Out: 
id NAME TYPE 
123 DDLJ cat1 0.571429 
222 India cat2 -1.000000 
456 Satya cat2 0.250000 

Для того, чтобы использовать их в слиянии, я буду сбросить индекс:

res = ((df['9-10'] - df['1-6'])/df.sum(axis=1)).reset_index() 
res 
Out: 
    id NAME TYPE   0 
0 123 DDLJ cat1 0.571429 
1 222 India cat2 -1.000000 
2 456 Satya cat2 0.250000 

И, наконец, сливаются с оригинальным DataFrame:

df.merge(res) 
Out: 
    id NAME TYPE SCORE title   0 
0 123 DDLJ cat1 1-6  5 0.571429 
1 123 DDLJ cat1 9-10  25 0.571429 
2 123 DDLJ cat1  N  5 0.571429 
3 456 Satya cat2 9-10  1 0.250000 
4 456 Satya cat2  N  3 0.250000 
5 222 India cat2 1-6  1 -1.000000 
+0

@ ayhan-mine терпит неудачу с ошибкой ValueError: не может пометить индекс нулевым ключом для df2 = df. set_index (['id', 'NAME', 'TYPE']). pivot (columns = 'SCORE'). fillna (0) – Satya

+0

У вас есть значения NaN в одном из этих столбцов? (id, NAME или TYPE) – ayhan

+0

Нет, я проверил и также сделал fillna() для всех столбцов отдельно. – Satya

1

Попробуйте ответить на ваш вопрос, как применить GroupBy:

def getScore(gb): 
    x = gb[gb['SCORE'] == '9-10']['title'].values.sum() 
    y = gb[gb['SCORE'] == '1-6']['title'].values.sum() 
    z = float(gb['title'].sum()) 
    return pd.Series((x-y)/z) 

gb  = df2.groupby(["NAME"])['SCORE', 'title'].apply(getScore).reset_index() 
gbdict = dict(gb.values) 
gbdict 

{'DDLJ': 0.5714285714285714, 'India': -1.0, 'Satya': 0.25} 


df2['cat_score'] = df2['NAME'].map(dict(gb.values)) 

    id NAME TYPE SCORE title cat_score 
0 123 DDLJ cat1 1-6  5 0.571429 
1 123 DDLJ cat1 9-10  25 0.571429 
2 123 DDLJ cat1  N  5 0.571429 
3 456 Satya cat2 9-10  1 0.250000 
4 456 Satya cat2  N  3 0.250000 
5 222 India cat2 1-6  1 -1.000000 
Смежные вопросы