Панды: Группировать и перебирать с условностями внутри групп? - PullRequest
0 голосов
/ 19 сентября 2018

У меня относительно сложный итерационный вопрос, который мне не удается реализовать.

У меня есть датафрейм с первыми 6 столбцами, показанными ниже.Я пытаюсь написать функцию, которая выполняет итерации внутри групп - в частности, группирует строки по категориям и уровням - и затем генерирует новую переменную, если для этой строки выполняются два условия, против любой другой строки в группе ,Я хотел бы создать возможность?двоичный индикатор ниже, где он равен 1, если он соответствует условию.Столбец Reason просто объясняет результат, который я хочу получить.

Логика: Для каждой группы id_, если ((metric_LHS [объект]> Metric_RHS [другой объект в группе]) & (metric_LHS [объект]> базовый уровень [объект])), возможность?= 1

Итак, в моем примере, Возможность?для Jim столбец равен 1, потому что Metric_LHS (Jim)> Metric_RHS (Jack) и Metric_LHS (Jim)> Baseline (Jim).Между тем, Рик равен 0, например, потому что критерии не работают для единственного другого человека в группе, Джо.

Ниже приведены некоторые фрагменты кода и логики, которые я написал.Мой вопрос заключается в следующем: как выполнить итерацию в каждой строке каждой группы и сравнить эту строку с каждой другой строкой в ​​этой группе?

id_group=df.groupby(['Category','Level'])
    for row in id_group:
       df['Opportunity?'](([df[metric_LHS][row]>df[Metric_RHS][row+1]) &\
       (df[metric_LHS][row]>df[Baseline][row])) = 1  
***How to iterate to next row in group?***

Example data

1 Ответ

0 голосов
/ 19 сентября 2018

При итерации таким способом по объекту groupby возвращаемый объект будет кортежем (index, group).

Чтобы перебрать строки для каждого group, вы можете использовать DataFrame.itterrows.

Примерно так:

id_group=df.groupby(['Category','Level'])

for g_idx, group in id_group:
    for r_idx, row in group.iterrows():
        if (((row['Metric_LHS'] > group['Metric_RHS']).any())
             & (row['Metric_LHS'] > row['Baseline'])):
            df.loc[r_idx, 'Opportunity?'] = 1

Рабочий пример с данными предоставленной вами игрушки

df = pd.DataFrame({'Name':['Jim', 'Jack', 'Greg', 'Alex', 'Steve', 'Jack', 'Rick', 'Joe', 'Bill', 'Dave', 'Dan'],
        'Category':['South']*3 + ['North']*3 + ['West']*3 + ['East']*2,
        'Level': [1,1,2,2.5,2.5,2.5,3,3,3.25,4,4],
        'Metric_LHS': [100,80,70,110,90,105,110,111,90,87,83],
        'Metric_RHS': [120,90,75,115,95,110,112,113,95,90,85],
        'Baseline': [95,np.nan,73,112,85,103,105,112,93,75,81],
        'Opportunity?': [np.nan]*11})


id_group=df.groupby(['Category','Level'])

for g_idx, group in id_group:
    for r_idx, row in group.iterrows():
        if (((row['Metric_LHS'] > group['Metric_RHS']).any())
             & (row['Metric_LHS'] > row['Baseline'])):
            df.loc[r_idx, 'Opportunity?'] = 1


print(df)

     Name Category  Level  Metric_LHS  Metric_RHS  Baseline  Opportunity?
0     Jim    South   1.00         100         120      95.0           1.0
1    Jack    South   1.00          80          90       NaN           NaN
2    Greg    South   2.00          70          75      73.0           NaN
3    Alex    North   2.50         110         115     112.0           NaN
4   Steve    North   2.50          90          95      85.0           NaN
5    Jack    North   2.50         105         110     103.0           1.0
6    Rick     West   3.00         110         112     105.0           NaN
7     Joe     West   3.00         111         113     112.0           NaN
8    Bill     West   3.25          90          95      93.0           NaN
9    Dave     East   4.00          87          90      75.0           1.0
10    Dan     East   4.00          83          85      81.0           NaN
...