Выполнение операций над сгруппированными строками в python - PullRequest
0 голосов
/ 10 мая 2018

У меня есть датафрейм, где значение pic_code может повторяться.Если это повторяется, я хочу установить переменную "keep" в "t" для pic_code, ближайшего к его mpe_wgt.

Например, второй pic_code имеет "keep", установленный в t, так как он имеет«вес» ближе всего к соответствующему «mpe_weight».Мой код приводит к тому, что «keep» остается «f» для всех, а «diff» остается «100» для всех.

df['keep']='f'
df['diff']=100

def cln_df(data):
    if pd.unique(data['mpe_wgt']).shape==(1,):
        data['keep'][0:1]='t'
    elif pd.unique(data['mpe_wgt']).shape!=(1,): 
        data['diff']=abs(data['weight']-(data['mpe_wgt']/100))
        data['keep'][data['diff']==min(data['diff'])]='t'
    return data

df=df.groupby('pic_code').apply(cln_df)

df до

  pic_code      weight      mpe_wgt    keep    diff
  1234          45          34         f       100
  1234          32          23         f       100
  45344         54          35         f       100
  234           76          98         f       100
  234           65          12         f       100

df должно быть

  pic_code      weight      mpe_wgt    keep    diff
  1234          45          34         f       11
  1234          32          23         t       9
  45344         54          35         t       100
  234           76          98         t       22
  234           65          12         f       53

Я довольно плохо знаком с Python, поэтому, пожалуйста, держите решения как можно более простыми.Я действительно хочу, чтобы мой метод работал, поэтому, пожалуйста, не слишком увлекайтесь.Заранее благодарим за помощь.

Ответы [ 4 ]

0 голосов
/ 10 мая 2018

Использование eval и assign для выполнения логики, аналогичной другим ответам.

m = dict(zip([False, True], 'tf'))
f = lambda d: d.sort_values('diff').duplicated('pic_code').map(m)
df.eval('diff=abs(weight - mpe_wgt)').assign(keep=f)

   pic_code  weight  mpe_wgt keep  diff
0      1234      45       34    f  11.0
1      1234      32       23    t   9.0
2     45344      54       35    t  19.0
3       234      76       98    t  22.0
4       234      65       12    f  53.0
0 голосов
/ 10 мая 2018

Использование:

df['keep'] = df.assign(closest=(df['mpe_wgt']-df['weight']).abs())\
               .sort_values('closest').duplicated(subset=['pic_code'])\
               .replace({True:'f',False:'t'})

Выход:

   pic_code  weight  mpe_wgt keep
0      1234      45       34    f
1      1234      32       23    t
2     45344      54       35    t
3       234      76       98    t
4       234      65       12    f
0 голосов
/ 10 мая 2018

Может быть, вы можете попробовать cumcount

df['diff'] = (df['weight'] - df['mpe_wgt']).abs()
df['keep'] = df.sort_values('diff').groupby('pic_code').cumcount().eq(0)
df
   pic_code  weight  mpe_wgt  diff   keep
0      1234      45       34    11  False
1      1234      32       23     9   True
2     45344      54       35    19   True
3       234      76       98    22   True
4       234      65       12    53  False
0 голосов
/ 10 мая 2018

Это один из способов. Примечание. Я использую логические значения True / False вместо строк "t" и "f". Это просто хорошая практика.

Обратите внимание, что все перечисленные ниже операции векторизованы, в то время как groupby.apply с пользовательской функцией, конечно, нет.

Настройка

print(df)

   pic_code  weight  mpe_wgt
0      1234      45       34
1      1234      32       23
2     45344      54       35
3       234      76       98
4       234      65       12

Решение

# calculate difference
df['diff'] = (df['weight'] - df['mpe_wgt']).abs()

# sort by pic_code, then by diff
df = df.sort_values(['pic_code', 'diff'])

# define keep column as True only for non-duplicates by pic_code
df['keep'] = ~df.duplicated('pic_code')

Результат

print(df)

   pic_code  weight  mpe_wgt  diff   keep
3       234      76       98    22   True
4       234      65       12    53  False
1      1234      32       23     9   True
0      1234      45       34    11  False
2     45344      54       35    19   True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...