我有一个DataFrame,每行都标识了一个客人及其预订编号、姓名、到达日期、离开日期和停留天数。
df = pd.DataFrame({'Booking_ID': ['34532', '43242', '43242', '32414'],
'Name': ['Me', 'Myself', 'You', 'I'],
'Start_Date': ['Jan 1, 2022', 'Mar 31, 2022', 'Mar 31, 2022', 'Jun 1, 2022'],
'End_Date': ['Jan 5, 2022', 'Apr 3, 2022', 'Apr 3, 2022', 'Jun 5, 2022'],
'Nights': [4, 3, 3, 4]})
一些客户在两个月内作为客人入住。出于统计原因,我需要将这些行分成两个不同的行:一个是第一个月的夜晚,另一个是第二个月的夜晚。
我想要得到的是:
预订编号 | 姓名 | 开始日期 | 结束日期 | 晚数 |
---|---|---|---|---|
34532 | 我 | 2022年1月1日 | 2022年1月5日 | 4 |
43242 | 我自己 | 2022年3月31日 | 2022年4月1日 | 1 |
43242 | 我自己 | 2022年4月1日 | 2022年4月3日 | 2 |
43242 | 你 | 2022年3月31日 | 2022年4月1日 | 1 |
43242 | 你 | 2022年4月1日 | 2022年4月3日 | 2 |
32414 | 我 | 2022年6月1日 | 2022年6月5日 | 4 |
我修改了之前链接中的代码:
import pandas as pd
import datetime as dt
df = pd.DataFrame({'Booking_ID': ['34532', '43242', '43242', '3241413'],
'Name': ['Me', 'Myself', 'You', 'I'],
'Start_Date': ['Jan 1, 2022', 'Mar 31, 2022', 'Mar 31, 2022', 'Jun 1, 2022'],
'End_Date': ['Jan 5, 2022', 'Apr 3, 2022', 'Apr 3, 2022', 'Jun 5, 2022'],
'Nights': [4, 3, 3, 4]})
df['Start_Date'] = pd.to_datetime(df['Start_Date'])
df['End_Date'] = pd.to_datetime(df['End_Date'])
df[['Start_Date', 'End_Date']] = df.apply(lambda x: (pd.date_range(x['Start_Date'], x['End_Date'] - dt.timedelta(days=1), freq='D'), pd.date_range(x['Start_Date'] + dt.timedelta(days=1), x['End_Date'], freq='D')) if x['Start_Date'].month != x['End_Date'].month else (pd.date_range(x['Start_Date'], x['Start_Date'], freq='D'), pd.date_range(x['End_Date'], x['End_Date'], freq='D')), axis=1, result_type='expand')
df = df.explode(['Start_Date', 'End_Date']).reset_index(drop=True)
df['Nights'] = df.groupby(['Booking_ID', 'Name', df.Start_Date.dt.month], as_index=False)['Nights'].transform(lambda x: x/len(x)).astype(int)
我拥有的是这个:
Booking_ID Name Start_Date End_Date Nights
0 34532 Me 2022-01-01 2022-01-05 4
1 43242 Myself 2022-03-31 2022-04-01 3
2 43242 Myself 2022-04-01 2022-04-02 1
3 43242 Myself 2022-04-02 2022-04-03 1
4 43242 You 2022-03-31 2022-04-01 3
5 43242 You 2022-04-01 2022-04-02 1
6 43242 You 2022-04-02 2022-04-03 1
7 32414 I 2022-06-01 2022-06-05 4
这部分是我想要的。
日期格式并不是很重要,因为可以轻松更改。
df['Start_Date'] = df['Start_Date'].dt.strftime('%b %#d, %Y')
df['End_Date'] = df['End_Date'].dt.strftime('%b %#d, %Y')
但是我真的需要:
将所有具有相同预订 ID、名称和 Start_Date 月份的行聚合成一个带有 Nights 列的行。这会导致聚合行的总晚数,并且 Start_Date/End_Date 对结果为聚合行的第一个 Start_Date 和最后一个 End_Date。
如果有一行起源于前一行由日期范围拆分而来,其 Start_Date 和 End_Date 之间有 1 天的距离,但原始夜数,则 Nights 值必须更改为 1。
rows.append(new_row)'
- Mondonauta