Группировка и расчет данных

1

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

У меня есть набор данных о рабочем времени сотрудников, например (это слишком упрощенно, реальный материал - тысячи и тысячи записей)

    ID      Name    Date        Hour    Type
0   123     Bob     01/01/2018  09:00   In
1   123     Bob     01/01/2018  09:30   Out
2   123     Bob     01/01/2018  10:00   In
3   123     Bob     01/01/2018  12:00   Out
4   123     Bob     01/01/2018  13:00   In
5   123     Bob     01/01/2018  17:00   Out
6   456     Max     01/01/2018  09:00   In
7   456     Max     01/01/2018  12:00   Out
8   456     Max     01/01/2018  13:00   In
9   456     Max     01/01/2018  17:00   Out
10  123     Bob     02/01/2018  09:00   In
11  123     Bob     02/01/2018  09:30   Out
12  123     Bob     02/01/2018  10:00   In
13  123     Bob     02/01/2018  17:00   Out
14  456     Max     02/01/2018  10:00   In
15  456     Max     02/01/2018  17:00   Out

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

    ID      Name    Date        HourWorked
0   123     Bob     01/01/2018  06:30
1   456     Max     01/01/2018  07:00
2   123     Bob     02/01/2018  07:30
3   456     Max     02/01/2018  07:00

В конце концов, мне нужно (для каждого идентификатора сотрудника) вычислять часы/минуты, работающие на каждый день

Я смотрел много примеров GroupBy, но нашел что-нибудь полезное.

ТИА

Теги:
pandas
dataframe
pandas-groupby

3 ответа

4
Лучший ответ

Конвертируйте часы в datetime, groupby In и Outs и принимайте разницу. Позже суммируйте разностную группировку по 'ID' и 'Date' т.е.

df['Hour'] = pd.to_datetime(df['Hour'])

df['diff'] = df.groupby((df['Type'] == 'In').cumsum())['Hour'].diff()

df_new = df.groupby(['ID','Name','Date'])['diff'].sum().to_frame('Hours Worked')

                    Hours Worked
ID  Name Date                   
123 Bob  01/01/2018     06:30:00
         02/01/2018     07:30:00
456 Max  01/01/2018     07:00:00
         02/01/2018     07:00:00
  • 1
    Да, я не мог думать об использовании timedelta :)
  • 0
    спасибо, это работает как шарм :) Единственная странная вещь, когда я пытаюсь написать с помощью df_new.to_excel (), все отработанные часы равны = 0
Показать ещё 2 комментария
2

С помощью groupby + пользовательская функция. Это предполагает, что ваши "In" и "Out" времена правильно спарены и упорядочены.

# convert series to timedelta
df['Hour'] = pd.to_timedelta(df['Hour']+':00')

# define total time calculation
def total_time(x):
    return (x.iloc[1::2].values - x.iloc[::2].values).sum()

# apply groupby and convert to dataframe
res = df.groupby(['ID', 'Name', 'Date'])['Hour'].apply(total_time)\
        .to_frame('Hours Worked').reset_index()

print(res)

    ID Name        Date  Hours Worked
0  123  Bob  01/01/2018      06:30:00
1  123  Bob  02/01/2018      07:30:00
2  456  Max  01/01/2018      07:00:00
3  456  Max  02/01/2018      07:00:00
0

Это решение предполагает, однако, что ваш Type всегда находится в порядке "In-Out"

df = pd.DataFrame({"ID": [123,123,123,123,456,456, 123,123, 456,456],
                   "Date": ["01/01/2018","01/01/2018", "01/01/2018", "01/01/2018", "01/01/2018", "01/01/2018", 
                       "02/01/2018", "02/01/2018", "02/01/2018", "02/01/2018"],
                   "Hour": ["09:00","09:30","10:00","12:00","13:00","17:00", "10:00","12:00","13:00","17:00"],
                   "Type": ["In","Out","In","Out","In","Out", "In","Out","In","Out"]})
df["DateTime"] = pd.to_datetime(df["Hour"] + " " + df["Date"])
df.groupby(["ID", "Date"])["DateTime"].apply(list).\
                                       apply(lambda x: [x[i+1] - x[i] for i in range(len(x) - 1)]).str[0::2].\
                                       apply(lambda x: np.sum(x))     

Ещё вопросы

Сообщество Overcoder
Наверх
Меню