python - 如何为数据框中的每个唯一 ID 创建一个特定的 date_range?
问题描述
我想为数据集中的每个客户创建一个日期范围。每个客户都有自己的范围。如果没有 for 循环,如何做到这一点?
样本数据:
import pandas as pd
dates = ['2018-01', '2018-04', '2018-10', '2018-11', '2018-12', '2018-01', '2018-04']
customers = ['A', 'A', 'A', 'A', 'A', 'B', 'B']
df = pd.DataFrame({'customers':customers, 'date':dates})
df.head(10)
现在我希望每个客户的每一行都有一个月的时间,分别是他们的最小和最大日期,以获得:
import pandas as pd
dates = ['2018-01', '2018-02', '2018-03', '2018-04', '2018-05', '2018-06', '2018-07', '2018-08', '2018-09', '2018-10', '2018-11', '2018-12', '2018-01', '2018-02', '2018-03', '2018-04']
customers = ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B','B']
df1 = pd.DataFrame({'customers':customers, 'date':dates})
df1.head(16)
我的尝试是使用 for 循环,遍历每个客户,但它太慢了。如何让它更快?
def get_date_frame(start_date, end_date):
date_frame = pd.date_range(start=start_date, end=end_date, freq='MS')
date_frame = pd.DataFrame(pd.DataFrame(date_frame.astype(str))[0].str[:7])
date_frame.columns = ['date']
return date_frame
for idx, jk in (enumerate(['A', 'B'])):
guy = df[df['customers']==jk]['date'] #get the data for that customer
guy.reset_index(drop=True, inplace=True) #reset
start = guy[0] #first date
end = guy[len(guy)-1] #last date
dframe = get_date_frame(start, end) #get range of dates
dframe['customer'] = jk #add customer id
if idx == 0:
out = dframe.copy()
else:
out = pd.concat((out, dframe.copy()), axis = 0) #concat outputs
解决方案
df['date'] = pd.to_datetime(df['date'], format='%Y-%d')
df2 = df.groupby(['customers']).apply(
lambda x: x.set_index('date')
.reindex(pd.date_range(start = x['date'].min(), end = x['date'].max()))
.ffill()
.rename_axis('date')
.reset_index())
print(df2)
date customers
customers
A 0 2018-01-01 A
1 2018-01-02 A
2 2018-01-03 A
3 2018-01-04 A
4 2018-01-05 A
5 2018-01-06 A
6 2018-01-07 A
7 2018-01-08 A
8 2018-01-09 A
9 2018-01-10 A
10 2018-01-11 A
11 2018-01-12 A
B 0 2018-01-01 B
1 2018-01-02 B
2 2018-01-03 B
3 2018-01-04 B
此外,如果您想转换日期列,那么
df2 = df2.droplevel('customers') #drop the index customer
df2['date'] = df2['date'].dt.year.astype(str) +'-'+ df2['date'].dt.day.astype(str)
date customers
0 2018-1 A
1 2018-2 A
2 2018-3 A
3 2018-4 A
4 2018-5 A
5 2018-6 A
6 2018-7 A
7 2018-8 A
8 2018-9 A
9 2018-10 A
10 2018-11 A
11 2018-12 A
0 2018-1 B
1 2018-2 B
2 2018-3 B
3 2018-4 B
推荐阅读
- python - 有人知道如何使用 python 上的 instaloader 包只获取图片而不是视频吗?
- python - 将频道提及转换为不和谐文本频道对象
- javascript - React:ReactToPrint 如何打印适合任何页面大小的动态宽度
- sql - 如何在SQL中提取关键字并在数据库记录中搜索?
- python - 在 Python 多处理进程中运行较慢的 OpenCV 代码片段
- python - 如何在 Django Slug 中获取最后插入的 id?
- php - 如何使用 react native expo image 将图像上传到我的本地服务器 PHP / Database MySQL
- java - Android 通过应用程序保存和共享数据的最佳方式
- ios - 自定义 Stripe UI 集成以保存和获取用户卡信息
- database-migration - 没有关于如何在 SQLDelight 中迁移现有数据库的适当文档