Saya memiliki kerangka data yang terlihat seperti ini:

import pandas as pd
foo = pd.DataFrame({'var_name': ['r1','r2','r3','var', 'r1','r2','r3','var'],
                    'group': ['a','a','a','a','b','b','b','b'],
                    'value': [1,2,3,4,6,7,8,9]})

Saya ingin kolom baru dalam kerangka data ini, yang akan berisi 1 jika value lebih besar dari median kolom value dari baris di mana var_name berada di ['r1','r2','r3'] oleh group, jika tidak 0

Kerangka data keluaran akan terlihat seperti:

foo = pd.DataFrame({'var_name': ['r1','r2','r3','var', 'r1','r2','r3','var'],
                        'group': ['a','a','a','a','b','b','b','b'],
                        'value': [1,2,3,4,6,7,8,9],
                        'test': [0,0,1,1,0,0,1,1]})

Penjelasan kerangka data keluaran: Median dari r1,r2,r3 untuk group a adalah 2, jadi baris r3 & var mendapatkan 1 di kolom test

Apakah ada cara Pythonic untuk melakukan itu?

1
quant 9 April 2020, 13:26

1 menjawab

Jawaban Terbaik

Ide pertama adalah memfilter hanya baris yang cocok dengan nilai r dengan boolean indexing, agregat median dan Series.map menurut grup dengan Series.lt dan konversi terakhir ke nilai 0,1 oleh Series.view:

s = foo[foo['var_name'].isin(['r1','r2','r3'])].groupby('group')['value'].median()

foo['test'] = foo['group'].map(s).lt(foo['value']).view('i1')

Atau ide lain dengan Series.where< /a> untuk mengganti nilai yang tidak cocok ke NaNs dan kemudian dibuat Series baru untuk dibandingkan dengan GroupBy.transform dan median:

foo['test'] = (foo['value'].where(foo['var_name'].isin(['r1','r2','r3']))
                           .groupby(foo['group'])
                           .transform('median')
                           .lt(foo['value'])
                           .view('i1'))

print (foo)

  var_name group  value  test
0       r1     a      1     0
1       r2     a      2     0
2       r3     a      3     1
3      var     a      4     1
4       r1     b      6     0
5       r2     b      7     0
6       r3     b      8     1
7      var     b      9     1
3
jezrael 9 April 2020, 10:49