python - 将年、月、日的单独系列转换为单个日期时间系列
问题描述
我有年、月和日的熊猫系列:
year = [2016]
months = [6,7]
days = [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 1, 2, 3, 4, 5, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
它们来自同一个 Dataframe,因此索引匹配。例如,2016 年的索引,6, 1 匹配,7 和第二个 1 从天系列匹配的索引。
如何将其转换/组合为单个系列作为日期时间?
喜欢,
date = [2016-06-01, 2016-06-03, ..., 2016-06-30, 2016-07-01]
由于日子都在一个系列中,我很难将它们按月分开。
解决方案
从您的数据开始:
years = [2016]
months = [6,7]
days = [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 1, 2, 3, 4, 5, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
解决方案 1
我们可以这样做:
import pandas as pd
from datetime import datetime
def date_cleanup(days, months, years):
res = []
last_day = 0
cmp = 0
for year in years:
for month in months:
for day in days:
if day > last_day:
res.append(datetime(year, month, day))
cmp += 1
last_day = day
else:
last_day = 0
days = days[cmp:]
break
return pd.Series(res)
我们在这里所做的是在和years
上进行多重循环。当我们得到比前一天小的一天时,我们从列表中删除所有已经使用的元素,并通过 for 循环更改月份。
你得到预期的结果:months
days
days
>>> date_cleanup(days, months, years)
0 2016-06-01
1 2016-06-03
2 2016-06-04
3 2016-06-05
4 2016-06-06
5 2016-06-07
6 2016-06-08
7 2016-06-09
8 2016-06-10
9 2016-06-11
10 2016-06-12
11 2016-06-29
12 2016-06-30
13 2016-07-01
14 2016-07-02
15 2016-07-03
16 2016-07-04
17 2016-07-05
18 2016-07-07
19 2016-07-12
20 2016-07-13
21 2016-07-14
22 2016-07-15
23 2016-07-16
24 2016-07-17
25 2016-07-18
26 2016-07-19
27 2016-07-20
28 2016-07-21
29 2016-07-22
30 2016-07-23
31 2016-07-24
32 2016-07-25
33 2016-07-26
34 2016-07-27
35 2016-07-28
36 2016-07-29
37 2016-07-30
dtype: datetime64[ns]
解决方案 2
感谢@Vishnudev 的评论,我根据 Pandas 和 Numpy 的强大功能推送了答案,以获得更优雅的解决方案:
>>> years = [2006]
>>> months = [6, 7]
>>> days = [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 1, 2, 3, 4, 5, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
>>> df = pd.DataFrame(days, columns=['day'])
我们使用该方法找到变化的月份diff
,并使用布尔值来标记差异何时为负(例如从 30 到 1)。然后我们cumsum
在此列上应用 a 以匹配 列表的索引months
。
>>> df['switch'] = np.where((df['day'].diff()>0) | (df['day'].diff().isna()), 0, 1)
>>> df['indice'] = df['switch'].cumsum()
>>> df['month'] = [months[i] for i in df['indice'].tolist()]
>>> df
day switch indice month
0 1 0 0 6
1 3 0 0 6
2 4 0 0 6
3 5 0 0 6
4 6 0 0 6
5 7 0 0 6
6 8 0 0 6
7 9 0 0 6
8 10 0 0 6
9 11 0 0 6
10 12 0 0 6
11 29 0 0 6
12 30 0 0 6
13 1 1 1 7
14 2 0 1 7
15 3 0 1 7
16 4 0 1 7
17 5 0 1 7
18 7 0 1 7
19 12 0 1 7
20 13 0 1 7
21 14 0 1 7
22 15 0 1 7
23 16 0 1 7
24 17 0 1 7
25 18 0 1 7
26 19 0 1 7
27 20 0 1 7
28 21 0 1 7
29 22 0 1 7
30 23 0 1 7
31 24 0 1 7
32 25 0 1 7
33 26 0 1 7
34 27 0 1 7
35 28 0 1 7
36 29 0 1 7
37 30 0 1 7
现在,我们从列表中添加年份years
并删除不必要的列,我们得到预期的结果:
>>> df['year'] = years[0]
>>> df.drop(['switch', 'indice'], axis=1)
>>> df
day month year
0 1 6 2006
1 3 6 2006
2 4 6 2006
3 5 6 2006
4 6 6 2006
5 7 6 2006
6 8 6 2006
7 9 6 2006
8 10 6 2006
9 11 6 2006
10 12 6 2006
11 29 6 2006
12 30 6 2006
13 1 7 2006
14 2 7 2006
15 3 7 2006
16 4 7 2006
17 5 7 2006
18 7 7 2006
19 12 7 2006
20 13 7 2006
21 14 7 2006
22 15 7 2006
23 16 7 2006
24 17 7 2006
25 18 7 2006
26 19 7 2006
27 20 7 2006
28 21 7 2006
29 22 7 2006
30 23 7 2006
31 24 7 2006
32 25 7 2006
33 26 7 2006
34 27 7 2006
35 28 7 2006
36 29 7 2006
37 30 7 2006
更新
正如您在评论@donnyan 中指定的那样,您能够提供一组长度相同的数据,我们可以按照@HenryEcker 和@Vishnudev 的建议,使用Pandas 的强大功能并直接使用@HenryEcker 解决方案:
pd.to_datetime(pd.DataFrame({'year': years, 'month': months, 'day': days})