假设我有一个名为df
的数据框:
import pandas as pd
df = pd.DataFrame({"user_id": [2124, 18420],
"on_pm_at": [pd.Timestamp("2018-06-21 11:06:33.620913"),
pd.Timestamp("2018-02-24 04:56:48.175177")]})
+---------+----------------------------+
| user_id | on_pm_at |
+---------+----------------------------+
| 2124 | 2018-06-21 11:06:33.620913 |
| 18420 | 2018-02-24 04:56:48.175177 |
+---------+----------------------------+
我想创建一个新的数据框(假设new_df
),其中每个用户都具有直到当前月份为止的月底日期的时间戳。例如,今天是7月13日,这个月底是7月31日,因此:
+---------+------------+
| user_id | months |
+---------+------------+
| 2124 | 2018-06-30 |
| 2124 | 2018-07-31 |
| 18420 | 2018-02-28 |
| 18420 | 2018-03-31 |
| 18420 | 2018-04-30 |
| 18420 | 2018-05-31 |
| 18420 | 2018-06-30 |
| 18420 | 2018-07-31 |
+---------+------------+
到目前为止,我最好的尝试(但看起来很丑)是:
df.groupby(["user_id", pd.Grouper(key = "on_pm_at", freq = 'M')]).agg({"user_id": "size"}).rename(columns={"user_id": "size"}).reset_index().drop(columns="size")
+---------+------------+
| user_id | on_pm_at |
+---------+------------+
| 2124 | 2018-06-30 |
| 18420 | 2018-02-28 |
+---------+------------+
它为我提供了每个用户的起点,但我不知道如何进行。我见过datetime.timedelta
,但不能有几个月的变化。有什么办法可以达到我期望的数据帧?不必从我以前的尝试开始。
答案 0 :(得分:2)
月周期解决方案:
首先将months
的列to_period
转换为Period
的{{1}},然后将itertuples
与period_range
一起使用,最后用于日期时间to_timestamp
:
now
Datetime的解决方案:
相似的方法,在一个月的最后一天转换为df['a'] = df['on_pm_at'].dt.to_period('m')
now = pd.Period(pd.datetime.now().strftime('%Y-%m'),freq='m')
print (now)
2018-07
df1 = pd.concat([pd.Series(r.user_id,pd.period_range(r.a, now, freq='m'))
for r in df.itertuples()]).reset_index()
df1.columns = ['months','user_id']
df1['months'] = df1['months'].dt.to_timestamp('m')
print (df1)
months user_id
0 2018-06-30 2124
1 2018-07-31 2124
2 2018-02-28 18420
3 2018-03-31 18420
4 2018-04-30 18420
5 2018-05-31 18420
6 2018-06-30 18420
7 2018-07-31 18420
,然后转换为month period
,并使用date_range
:
timestamp