Как выполнить операцию между разными столбцами после группирования столбца в пандах? - PullRequest
2 голосов
/ 21 апреля 2019

Я не уверен, что я сделал, но я ожидал одинакового результата для этих двух методов, чтобы вычислить среднее значение удара для бейсболистов из набора данных Lahmans Baseball:

import numpy as np
import pandas as pd

batting = pd.read_csv('https://github.com/bhishanpdl/Datasets/blob/master/Lahman_batting.csv?raw=true')

# create new col
batting['ba'] = batting['H'] / batting['AB']

# groupby for each baseball player
print(batting.groupby('playerID')[['ba','AB']]
             .sum().head().reset_index())

Это дает:

    playerID        ba     AB
0  aardsda01  0.000000      4
1  aaronha01  6.924731  12364
2  aaronto01  1.544619    944
3   aasedo01  0.000000      5
4   abadan01  0.117647     21

Но, глядя только на второго игрока, результат неправильный.

# sanity check for aaronha01
a = batting.query(""" playerID == 'aaronha01'  """)['H'].sum()
b = batting.query(""" playerID == 'aaronha01'  """)['AB'].sum()
a,b,a/b
(3771, 12364, 0.30499838240051763)

Как исправить результат?

Для второго игрока по имени aaronha01,результат должен быть 0.30499838240051763, но groupby дает 6.924731.

Обновление
В R мы получаем правильное значение, но я искал путь в Пандах:

library(Lahman)

batting = as_tibble(Lahman::Batting)
batters = batting  %>%  
    group_by(playerID) %>%  
    summarize(
      ba = sum(H, na.rm = TRUE) / sum(AB, na.rm = TRUE),
      ab = sum(AB, na.rm = TRUE)
    )

head(batters)

playerID    ba  ab
aardsda01   0.0000000   4
aaronha01   0.3049984   12364
aaronto01   0.2288136   944
aasedo01    0.0000000   5
abadan01    0.0952381   21
abadfe01    0.1111111   9

1 Ответ

2 голосов
/ 21 апреля 2019

Вы можете суммировать оба столбца, а затем рассчитать среднее значение по группам:

gp = batting.groupby('playerID')[['H', 'AB']].sum()
gp['ba'] = gp.H/gp.AB
print(gp)

#              H     AB        ba
#playerID                        
#aardsda01     0      4  0.000000
#aaronha01  3771  12364  0.304998
#aaronto01   216    944  0.228814
#aasedo01      0      5  0.000000
#abadan01      2     21  0.095238
#abadfe01      1      9  0.111111
#abadijo01    11     49  0.224490

Если вы хотите, чтобы все это было на одной линии, можете связать с eval:

batting.groupby('playerID')[['H', 'AB']].sum().eval('ab = H / AB')

Чтобы объяснить исходную проблему, выше приведено среднее значение, в котором каждому АБ присвоен одинаковый вес. В вашей первоначальной формулировке, сначала вычисляя 'ba' для каждого ряда, а затем беря среднее значение, вы придаете равный вес каждому наблюдению (в данном случае, в основном, каждый год) вместо каждого человека в летучей мыши. Если бы вы взвесили это среднее число по числу АБ в каждом ряду, вы бы получили тот же ответ, что и выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...