熊猫舍入本月初

时间:2020-05-12 03:19:33

标签: python python-3.x pandas

我有一个日期列表,大约是30日-2日,我想将所有这些日期都舍入到该月的第一天(30日/ 31日向上取整,而1/2/2日向下取整,依此类推)。

我如何在熊猫数据框中执行此操作?

2 个答案:

答案 0 :(得分:1)

首先请确保您的“日期”列数据类型为日期类型。例如,

df['date'] = pd.to_datetime(df['date'])

会将“日期”列的dtype更改为datetime64 [ns]。

接下来考虑问题的范围。您要更改2月28日/ 29日吗?我假设您只想更改指定的日期。这可以很容易地分为两个部分。首先找到较早的日期,然后将其向前移动,然后再找到较晚的日期,并将它们向后移动。

要向前移动早期日期,请创建一个掩码,以选择有问题的行。

mask1 = (df['birth_date'].dt.day >= 30)

然后使用pandas .apply()方法和专门定制的函数更改日期。应该对其进行矢量化处理,并因此应该相当快。

from dateutil.relativedelta import relativedelta
df.loc[mask1, 'birth_date'] = df.loc[mask1, 'birth_date'].apply(lambda date_in: (date_in + relativedelta(months=+1)).replace(day=1))

同样,对于需要提前移动的日期(恰好是day = 2的日期),我们有以下内容。

mask2 = (df['birth_date'].dt.day == 2)
df.loc[mask2, 'birth_date'] = df.loc[mask2, 'birth_date'].apply(lambda date_in: (date_in).replace(day=1))

例如:

输入:

raw_data = {'name': ['Willard Morris', 'Al Jennings', 'Omar Mullins', 'Spencer McDaniel'],
'age': [20, 19, 22, 21],
'favorite_color': ['blue', 'red', 'yellow', "green"],
'grade': [88, 92, 95, 70],
'birth_date': ['01-02-1996', '08-05-1997', '04-30-1996', '12-16-1995']}
df = pd.DataFrame(raw_data, index = ['Willard Morris', 'Al Jennings', 'Omar Mullins', 'Spencer McDaniel'])
df['birth_date'] = pd.to_datetime(df['birth_date'])
df

输出:

name                age    favorite_color    grade    birth_date('%y%m%d')

Willard Morris      20     blue              88       1996-01-02
Al Jennings         19     red               92       1997-08-05
Omar Mullins        22     yellow            95       1996-04-30
Spencer McDaniel    21     green             70       1995-12-16

输入:

mask1 = (df['birth_date'].dt.day >= 30)
mask2 = (df['birth_date'].dt.day == 2)
df.loc[mask1, 'birth_date'] = df.loc[mask1, 'birth_date'].apply(lambda date_in: (date_in + relativedelta(months=+1)).replace(day=1))
df.loc[mask2, 'birth_date'] = df.loc[mask2, 'birth_date'].apply(lambda date_in: date_in.replace(day=1))
df

输出:

name                age    favorite_color    grade    birth_date('%y%m%d')

Willard Morris      20     blue              88       1996-01-01
Al Jennings         19     red               92       1997-08-05
Omar Mullins        22     yellow            95       1996-05-01
Spencer McDaniel    21     green             70       1995-12-16

答案 1 :(得分:0)

如果您要对最接近月初的日期进行四舍五入,则可以分两步进行:

rng = pd.date_range('1/25/2018 11:59:00', periods=14, freq='D')
s = pd.Series(rng)

# round down 
s.where(((s.dt.day == 1) | (s.dt.day > 2)), 
        lambda x: x + pd.offsets.MonthBegin(-1), inplace=True)

# round up 
s.where(s.dt.day < 30, lambda x: x + pd.offsets.MonthBegin(0), inplace=True)  

结果:

In [317]: s
Out[317]: 
0    2018-01-25 11:59:00
1    2018-01-26 11:59:00
2    2018-01-27 11:59:00
3    2018-01-28 11:59:00
4    2018-01-29 11:59:00
5    2018-02-01 11:59:00
6    2018-02-01 11:59:00
7    2018-02-01 11:59:00
8    2018-02-01 11:59:00
9    2018-02-03 11:59:00
10   2018-02-04 11:59:00
11   2018-02-05 11:59:00
12   2018-02-06 11:59:00
13   2018-02-07 11:59:00
dtype: datetime64[ns]