真的很感激这方面的一些帮助
对于以下数据集:
StartDate EndDate Days 0 2018-03-20 00:36:00 2018-05-01 00:42:00 42.004167 1 2018-05-01 00:42:00 2018-06-04 17:15:38 34.690023 2 2018-04-07 15:06:00 2018-05-09 17:01:00 32.079861 3 2018-03-21 04:36:00 2018-05-14 04:00:00 53.975000 4 2018-03-15 15:30:00 2018-05-08 08:30:00 53.708333 5 2018-05-08 08:30:00 2018-06-09 10:40:09 32.090382 6 2018-03-21 09:00:00 2018-05-16 13:40:00 56.194444 7 2018-03-31 06:00:00 2018-05-26 16:30:00 56.437500 8 2018-03-14 18:18:00 2018-04-27 01:00:00 43.279167 9 2018-04-07 15:00:00 2018-06-01 09:25:50 54.767940 10 2018-03-22 07:30:00 2018-05-20 19:00:00 59.479167
我能够找到开始日期和结束日期之间的差异,并像这样创建新列“天”:
df['StartDate'] = pd.to_datetime(df['StartDate'])
df['EndDate'] = pd.to_datetime(df['EndDate'])
df['Days'] = df['EndDate'].sub(df['StartDate'], axis=0)
df['Days'] = df['Days'] / np.timedelta64(1, 'D')
但是我需要找到它:
对于每一行,每个月的天数以及他们所在的特定月份。
我认为最好的方法是为所有可能的月份创建列,并将日期归因于各自的列。但我来自excel背景,并且可能有更聪明的方法。
原因是;根据开始日期和结束日期之间的工作天数正确支付客户,并在此基础上对其进行归因。完整的数据集非常大,因此脚本必须以有效的方式处理各种日期差异。
black.mamba
答案 0 :(得分:2)
让我们尝试一下。
首先使用pd.date_range
为每条记录创建一系列日期,包括StartDate和EndDate。接下来使用dt
日期时间访问器来获取月份。使用value_counts
计算每条记录的总月数。最后,将结果加入原始数据框。另外,import calendar
通过rename
使用calendar.month_names
创建的字典来获取月份名称与号码。
import calendar
df.join(df.apply(lambda x:
pd.Series(pd.date_range(x.StartDate,
x.EndDate,
freq='D')).dt.month,1)
.apply(lambda x:
x.value_counts(),1)
.rename(columns=dict(enumerate(calendar.month_name))))
输出:
StartDate EndDate Days March April May June
0 2018-03-20 00:36:00 2018-05-01 00:42:00 42.004167 12.0 30.0 1.0 NaN
1 2018-05-01 00:42:00 2018-06-04 17:15:38 34.690023 NaN NaN 31.0 4.0
2 2018-04-07 15:06:00 2018-05-09 17:01:00 32.079861 NaN 24.0 9.0 NaN
3 2018-03-21 04:36:00 2018-05-14 04:00:00 53.975000 11.0 30.0 13.0 NaN
4 2018-03-15 15:30:00 2018-05-08 08:30:00 53.708333 17.0 30.0 7.0 NaN
5 2018-05-08 08:30:00 2018-06-09 10:40:09 32.090382 NaN NaN 24.0 9.0
6 2018-03-21 09:00:00 2018-05-16 13:40:00 56.194444 11.0 30.0 16.0 NaN
7 2018-03-31 06:00:00 2018-05-26 16:30:00 56.437500 1.0 30.0 26.0 NaN
8 2018-03-14 18:18:00 2018-04-27 01:00:00 43.279167 18.0 26.0 NaN NaN
9 2018-04-07 15:00:00 2018-06-01 09:25:50 54.767940 NaN 24.0 31.0 NaN
10 2018-03-22 07:30:00 2018-05-20 19:00:00 59.479167 10.0 30.0 20.0 NaN
答案 1 :(得分:1)
通过将dt.month更改为dt.strftime
,我能够将其过滤到显示月份和年份的要求df.join(df.apply(lambda x:
pd.Series(pd.date_range(x.StartDate,
x.EndDate,
freq='D')).dt.strftime('%b-%y'),1)
.apply(lambda x:
x.value_counts(),1)
.rename(columns=dict(enumerate(calendar.month_abbr))))
然而,输出现在按字母顺序列出列,而不是按年份顺序列出Jan到Dec。
欢迎任何有关如何实现这一目标的想法
首先,您的上述声明,您不需要重命名部分,因为当您从日期系列转换为%m时,您已经在重命名。
现在,当您取出返回用于排序的“月号”的.dt.month时,此方法会出现问题。当您更改使用月份名称时,现在您正在进行词典排序。因此,让我们切换回月份数(用于排序)并执行一些lambda函数将列号从月号转换为名称。
df.join(df.apply(lambda x:
pd.Series(pd.date_range(x.StartDate,
x.EndDate,
freq='D')).dt.strftime('%m-%y'),1)
.apply(lambda x:
x.value_counts(),1)
.rename(columns=lambda x:
pd.to_datetime(x, format='%m-%y').strftime('%b-%y')))
输出:
StartDate EndDate Days Mar-18 Apr-18 May-18 Jun-18
0 2018-03-20 00:36:00 2018-05-01 00:42:00 42.004167 12.0 30.0 1.0 NaN
1 2018-05-01 00:42:00 2018-06-04 17:15:38 34.690023 NaN NaN 31.0 4.0
2 2018-04-07 15:06:00 2018-05-09 17:01:00 32.079861 NaN 24.0 9.0 NaN
3 2018-03-21 04:36:00 2018-05-14 04:00:00 53.975000 11.0 30.0 13.0 NaN
4 2018-03-15 15:30:00 2018-05-08 08:30:00 53.708333 17.0 30.0 7.0 NaN
5 2018-05-08 08:30:00 2018-06-09 10:40:09 32.090382 NaN NaN 24.0 9.0
6 2018-03-21 09:00:00 2018-05-16 13:40:00 56.194444 11.0 30.0 16.0 NaN
7 2018-03-31 06:00:00 2018-05-26 16:30:00 56.437500 1.0 30.0 26.0 NaN
8 2018-03-14 18:18:00 2018-04-27 01:00:00 43.279167 18.0 26.0 NaN NaN
9 2018-04-07 15:00:00 2018-06-01 09:25:50 54.767940 NaN 24.0 31.0 NaN
10 2018-03-22 07:30:00 2018-05-20 19:00:00 59.479167 10.0 30.0 20.0 NaN