我有一个像下面这样的人

Date Name In/Out Time
2024-01-01 Homer IN 07:10
2024-01-01 Homer OUT 09:30
2024-01-01 Homer IN 10:00
2024-01-01 Homer OUT 16:00
2024-01-01 Marge In 07:15
2024-01-01 Marge Out 16:10
2024-01-01 Bart In 07:14
2024-01-01 Bart Out 10:00
2024-01-01 Bart In 10:15
2024-01-01 Bart Out 12:00
2024-01-01 Bart In 12:30
2024-01-01 Bart Out 17:00

我的最终目标是计算中间IN/OUT次的总timedelta(total_seconds()),如突出显示的.预期输出如下.

Date Name TimeDelta
2024-01-01 Homer 1800
2024-01-01 Bart 2700

我还不知道从哪里开始,也找不到任何其他地方的例子?

示例:

example_df = pd.DataFrame([
    ['2024-01-01', 'Homer', 'in', '07:30'],
    ['2024-01-01', 'Homer', 'out' ,'09:00'],
    ['2024-01-01', 'Homer', 'in' ,'09:30'],
    ['2024-01-01', 'Homer', 'out' ,'16:00'],
    ['2024-01-01', 'Marge', 'in' , '06:20'],
    ['2024-01-01', 'Marge', 'out' ,'16:00'],
    ['2024-01-01', 'Bart', 'in' ,'07:10'],
    ['2024-01-01', 'Bart', 'out' ,'08:00'],
    ['2024-01-01', 'Bart', 'in' ,'08:20'],
    ['2024-01-01', 'Bart', 'out' ,'17:00'],
    ['2024-01-01', 'Barney', 'in' ,'08:10'],
    ['2024-01-01', 'Lisa', 'in' ,'08:05'],
    ['2024-01-01', 'Lisa', 'out' ,'14:00'],
    ['2024-01-01', 'Lisa', 'in' ,'14:15'],
    ['2024-01-01', 'Lisa', 'out' ,'18:10'],
    ['2024-01-01', 'Millhouse', 'out' ,'19:10'],
    ['2024-02-01', 'Homer', 'in', '07:30'],
    ['2024-02-01', 'Homer', 'out' ,'09:00'],
    ['2024-02-01', 'Marge', 'in' , '06:30'],
    ['2024-02-01', 'Marge', 'out' ,'09:10'],
    ['2024-02-01', 'Marge', 'in' ,'10:10'],
    ['2024-02-01', 'Marge', 'out' ,'16:10'],
    ['2024-02-01', 'Bart', 'in' ,'07:10'],
    ['2024-02-01', 'Bart', 'out' ,'15:00'],
    ['2024-02-01', 'Barney', 'in' ,'08:10'],
    ['2024-02-01', 'Lisa', 'in' ,'08:05'],
    ['2024-02-01', 'Lisa', 'out' ,'16:00'],
    ['2024-02-01', 'Millhouse', 'in' ,'08:10'],
    ['2024-02-01', 'Millhouse', 'in' ,'08:10'],
    ['2024-02-01', 'Millhouse', 'in' ,'16:15']],
    columns=['Date', 'Name', 'In/Out', 'Time'])

推荐答案

假设Time在一个组中排序,第一个In/Out总是In,并且In/Out总是交替的.

你可以转换乘to_datetime,然后用groupby.apply计算乘diff,忽略第一个/最后一个值(用iloc),然后再转换成total_seconds:

# cleanup IN/OUT format
df['In/Out'] = df['In/Out'].str.upper()

out = (df
  .assign(dt=pd.to_datetime(df['Time'], format='%H:%M'))
  .groupby(['Date', 'Name'])
  .apply(lambda g: 
         g['dt'].diff().iloc[1:-1]
         [g['In/Out'].eq('IN')]
         .sum().total_seconds())
  .reset_index(name='TimeDelta')
  .query('TimeDelta>0') # optional: remove rows with null TimeDelta
)

输出:

         Date       Name  TimeDelta
1  2024-01-01   J Bloggs     1800.0
2  2024-01-01  M Simpson     2700.0

NB. If any of the initial assumptions is incorrect, you just need to pre-process the data to sort it and remove invalid rows.

示例:

# cleanup IN/OUT format
df['In/Out'] = df['In/Out'].str.upper()

m1 = df.sort_values(by='Time').groupby(['Date', 'Name'])['In/Out'].shift(-1).ne(df['In/Out'])

out = (df[m1]
  .assign(dt=pd.to_datetime(df.loc[m1, 'Time'], format='%H:%M'))
  .groupby(['Date', 'Name'])
  .apply(lambda g: 
         g['dt'].diff().iloc[1:-1]
         [g['In/Out'].eq('IN')]
         .sum().total_seconds())
  .reset_index(name='TimeDelta')
  .query('TimeDelta>0') # optional: remove rows with null TimeDelta
)

输出:

          Date   Name  TimeDelta
1   2024-01-01   Bart     1200.0
2   2024-01-01  Homer     1800.0
3   2024-01-01   Lisa      900.0
10  2024-02-01  Marge     3600.0

Python相关问答推荐

通过优化空间在Python中的饼图中添加标签

'discord.ext. commanders.cog没有属性监听器'

Pandas 有条件轮班操作

如何在python xsModel库中定义一个可选[December]字段,以产生受约束的SON模式

如何在WSL2中更新Python到最新版本(3.12.2)?

海上重叠直方图

如何使用scipy的curve_fit与约束,其中拟合的曲线总是在观测值之下?

如何在Pyplot表中舍入值

如何创建引用列表并分配值的Systemrame列

如何获得3D点的平移和旋转,给定的点已经旋转?

需要帮助使用Python中的Google的People API更新联系人的多个字段'

应用指定的规则构建数组

Pandas数据框上的滚动平均值,其中平均值的中心基于另一数据框的时间

read_csv分隔符正在创建无关的空列

操作布尔值的Series时出现索引问题

Pythonquests.get(Url)返回Colab中的空内容

如果列包含空值,则PANAS查询不起作用

使用pythonminidom过滤XML文件

当lambda函数作为参数传递时,pyo3执行

将参数从另一个python脚本中传递给main(argv