我有一个日期列表,大约是30日-2日,我想将所有这些日期都舍入到该月的第一天(30日/ 31日向上取整,而1/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]