Как я могу применить лямбда-функцию к 2 значениям подряд (лямбда> пропускает 1 обязательный аргумент)? - PullRequest
0 голосов
/ 23 октября 2019

У меня есть набор данных из 2 столбцов: age_group, target (0,1). Я хочу создать 3-й столбец "count" (значение count для age_group). Он должен посмотреть, если цель хороша и плоха, и поставить соответствующий счетчик.

5 корзин для возрастов:

df['age_group'] = pd.cut(df['age'], [17,22,26,32,45,50,60])

40 строк:

age_group       target
0   (45, 50]    bad
1   (45, 50]    bad
2   (32, 45]    good
3   (32, 45]    good
4   (50, 60]    bad
5   (32, 45]    bad
6   (26, 32]    good
7   (50, 60]    good
8   (32, 45]    bad
9   (17, 22]    good
10  (32, 45]    good

Я могу группировать по цели:

df.groupby('target').age_group.value_counts().to_frame()

                          age_group
target       age_group  
bad          (32, 45]      7
             (26, 32]      3
             (45, 50]      3
             (50, 60]      3
             (17, 22]      2
good         (32, 45]      8
             (17, 22]      4
             (50, 60]      4
             (45, 50]      3
             (26, 32]      2
             (22, 26]      1

, но в этомтолько для dataframe age_group является основным доступным столбцом. Я не могу получить доступ к столбцу 'target' и определенным значениям для хорошей, плохой цели.

Я хочу просмотреть каждую возрастную группу И ее цель и поместить соответствующее значение в столбец "count".

так что я делаю эту уродливую обходную функцию.

def get_value_count_for_age_group_category(age_group, target):
    bad_vals = df[df['bad']==1]['age_group'].value_counts().sort_index()
    good_vals = df[df['good']==1]['age_group'].value_counts().sort_index()
    values = age_freq.values.tolist()
    keys = age_freq.keys()
    if target == 'bad':
        for k in keys:        
            if age_group == pd.Interval(32,45):            
                return bad_vals[0]    
            elif age_group == pd.Interval(50, 60):
                return bad_vals[1]
            elif age_group == pd.Interval(45, 50):
                return bad_vals[2]
            elif age_group == pd.Interval(26, 32):
                return bad_vals[3]
            elif age_group == pd.Interval(22, 26):
                return bad_vals[4]
            elif age_group == pd.Interval(17,22):
                return bad_vals[5]
    else:
        for k in keys:        
            if age_group == pd.Interval(32,45):            
                return good_vals[0]    
            elif age_group == pd.Interval(50, 60):
                return good_vals[1]
            elif age_group == pd.Interval(45, 50):
                return good_vals[2]
            elif age_group == pd.Interval(26, 32):
                return good_vals[3]
            elif age_group == pd.Interval(22, 26):
                return good_vals[4]
            elif age_group == pd.Interval(17,22):
                return good_vals[5]

это не работает, передавая 2 значения - age_group и его цель лямбда-функции:

n['count'] = n[['age_group', 'target']].apply(lambda num:get_value_count_for_age_group_category(num, target) )

лямбда> () отсутствует 1 обязательный позиционный аргумент:

1 Ответ

1 голос
/ 23 октября 2019

Это работает для вас?

df.groupby('target').age_group.value_counts().reset_index(name='count')

Вход

age_group   target
0   (45, 50)    bad
1   (45, 50)    bad
2   (32, 45)    good
3   (32, 45)    good
4   (50, 60)    bad
5   (32, 45)    bad
6   (26, 32)    good
7   (50, 60)    good
8   (32, 45)    bad
9   (17, 22)    good
10  (32, 45)    good

Выход

  target    age_group   count
0   bad     (32, 45)    2
1   bad     (45, 50)    2
2   bad     (50, 60)    1
3   good    (32, 45)    3
4   good    (17, 22)    1
5   good    (26, 32)    1
6   good    (50, 60)    1

Если «нулевые» вейлы необходимы, используйте plesae ниже

df1=df.groupby('target').age_group.value_counts().reset_index(name='count')
df1.set_index(['target','age_group']).unstack(fill_value=0).stack().reset_index()

output

  target    age_group   count
0   bad     (17, 22)    0
1   bad     (26, 32)    0
2   bad     (32, 45)    2
3   bad     (45, 50)    2
4   bad     (50, 60)    1
5   good    (17, 22)    1
6   good    (26, 32)    1
7   good    (32, 45)    3
8   good    (45, 50)    0
9   good    (50, 60)    1
...