Python:将开始日期和结束日期拆分为开始日期和结束日期之间的所有天数
我有一个名为“计划休假”的数据,其中包括“开始日期”、“结束日期”、“用户ID”和“休假类型” 我希望能够创建一个新的数据框,显示每个“用户ID”的开始日期和结束日期之间的所有日期 到目前为止,我只能创建一个日期列表,该列表提供开始日期和结束日期之间的一系列日期,但我找不到一种方法来为每个“用户ID”和“休假类型”包含该列表 以下是我目前的职能:Python:将开始日期和结束日期拆分为开始日期和结束日期之间的所有天数,python,pandas,numpy,datetime,data-science,Python,Pandas,Numpy,Datetime,Data Science,我有一个名为“计划休假”的数据,其中包括“开始日期”、“结束日期”、“用户ID”和“休假类型” 我希望能够创建一个新的数据框,显示每个“用户ID”的开始日期和结束日期之间的所有日期 到目前为止,我只能创建一个日期列表,该列表提供开始日期和结束日期之间的一系列日期,但我找不到一种方法来为每个“用户ID”和“休假类型”包含该列表 以下是我目前的职能: def datesplit(data): x = pd.DataFrame(columns=['Date']) for i in pl
def datesplit(data):
x = pd.DataFrame(columns=['Date'])
for i in plannedleave.iterrows():
start = data['Start Date'][i]
end = data['End Date'][i]
date_list = [start + dt.timedelta(days=x) for x in range((end-start).days)]
x.append(date_list)
return x
>>> datesplit(plannedleave)
>>> Value Error: Can only Tuple-index with a MultiIndex
以下是数据的样子:
>>> plannedleave.dtypes
>>>
Employee ID int64
First Name object
Last Name object
Leave Type object
Start Date datetime64[ns]
End Date datetime64[ns]
dtype: object
如果您能在这里找到解决方案,我将永远感激您!:-) 在我看来,光是日期栏是不够的。您的输出数据帧
还应包含至少一个员工ID,以了解该员工的身份
在指定的日期离开
要执行任务,请定义以下函数:
def datesplit(data):
parts = []
for idx, row in data.iterrows():
parts.append(pd.DataFrame(row['Employee ID'], columns=['Employee ID'],
index=pd.date_range(start=row['Start Date'], end=row['End Date'],
name='Date')))
return pd.concat(parts).reset_index()
此功能:
def datesplit(data):
parts = []
for idx, row in data.iterrows():
parts.append(pd.DataFrame(row['Employee ID'], columns=['Employee ID'],
index=pd.date_range(start=row['Start Date'], end=row['End Date'],
name='Date')))
return pd.concat(parts).reset_index()
- 对于每个源行,现在收集“部分数据帧”:
- 唯一一列是员工ID
- 索引是开始日期和结束日期之间的日期范围
- 给定的员工ID(单个值)实际上是 广播所有行(当前员工休假时每天)
- 在循环之后,连接它们并转换索引(日期) 进入“常规”列
result = datesplit(plannedleave)
为了测试我的代码,我将其用作源数据帧(plannedleave):
上述数据的结果为:
Date Employee ID
0 2020-05-10 1001
1 2020-05-11 1001
2 2020-05-12 1001
3 2020-05-13 1001
4 2020-05-14 1001
5 2020-05-15 1001
6 2020-05-18 1002
7 2020-05-19 1002
8 2020-05-20 1002
9 2020-05-21 1002
10 2020-05-22 1002
以下是必要的循环,因此我更喜欢列表中的理解:
def datesplit(df):
df1 = df.rename(columns={'Start Date':'sdate','End Date':'edate', 'Employee ID':'ID'})
return (pd.concat([pd.Series(r.ID,pd.date_range(r.sdate, r.edate))
for r in df1.itertuples()])
.rename_axis('Date')
.reset_index(name='Employee ID'))
df = datesplit(plannedleave)
print (df)
Date Employee ID
0 2020-05-10 1001
1 2020-05-11 1001
2 2020-05-12 1001
3 2020-05-13 1001
4 2020-05-14 1001
5 2020-05-15 1001
6 2020-05-18 1002
7 2020-05-19 1002
8 2020-05-20 1002
9 2020-05-21 1002
10 2020-05-22 1002
200行的性能:
plannedleave = pd.concat([plannedleave] * 100, ignore_index=True)
def datesplit(df):
df1 = df.rename(columns={'Start Date':'sdate','End Date':'edate', 'Employee ID':'ID'})
return (pd.concat([pd.Series(r.ID,pd.date_range(r.sdate, r.edate))
for r in df1.itertuples()])
.rename_axis('Date')
.reset_index(name='Employee ID'))
def datesplitvb(data):
parts = []
for idx, row in data.iterrows():
parts.append(pd.DataFrame(row['Employee ID'], columns=['Employee ID'],
index=pd.date_range(start=row['Start Date'], end=row['End Date'],
name='Date')))
return pd.concat(parts).reset_index()
In [152]: %timeit datesplit(plannedleave.copy())
98.2 ms ± 4.96 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [153]: %timeit datesplitvb(plannedleave.copy())
193 ms ± 30.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
你能创建吗?确定还需要什么其他信息吗?你可以检查。你认为在我的解决方案中使用你的样本数据公平吗?没问题,使用它。完美!非常感谢你Jezrael@DylanMcCullough-如果我的回答有用,别忘了。谢谢这对于任何数据来说都是非常重要的,因为在200行中,此解决方案的速度要快1.9倍。如果行数越多,差异就越大。这只提供了日期+一列(员工ID)。如何将所有列添加到生成的数据框中?@Vega-使用
.Index
like