python - 如何使用最快的方法对数据框进行分组并将列生成为数字序列?
问题描述
如何使用最快的方法对数据框进行分组并将列生成为数字序列?我的代码步骤如下:
- 首先生成日期数据框
date
- 生成
code
数据框 - 生成和的
Cartesian product
dfdate
code
- 删除多余的列
['a','level_1','order']
- 按列分组,每组内按顺序
date
生成一order
列values
我的问题:
- 这些步骤感觉太麻烦了,有没有简单的方法?
- 第四步如何避免生成
level_1
andorder
列 - 如何优化代码,现在执行需要5秒
我的代码如下:
import pandas as pd
import numpy as np
def add_order(df):
df = df.reset_index(drop=True).reset_index()
df = df.drop(columns='date')
return df
def generate_data():
np.random.seed(202107)
date = pd.date_range(start='20150101', end='20210723', freq='D')
date = date.to_pydatetime()
date = np.vectorize(lambda s: s.strftime('%Y-%m-%d'))(date)
date = pd.DataFrame(date, columns=['date'])
date['a'] = 1
code = pd.DataFrame(range(50), columns=['code'])
code['a'] = 1
df = pd.merge(date, code, how='outer')
df['value'] = np.random.random(len(df)) * 1000
return df
def get_result(df):
df = df.sort_values(by='value', ascending=False)
df = df.groupby('date').apply(add_order)
df = df.reset_index().sort_values(by=['date', 'code']).reset_index(drop=True)
df = df.rename(columns={'index': 'order'})
col = ['date', 'code', 'value', 'order']
df = df[col]
# print(df)
return df
def main():
df = generate_data()
df = get_result(df)
%timeit main()
5.25 s ± 130 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
结果是:
date code value order
0 2015-01-01 0 227.190649 39
1 2015-01-01 1 543.938036 26
2 2015-01-01 2 175.707748 43
3 2015-01-01 3 789.146427 9
4 2015-01-01 4 585.727841 24
... ... ... ... ...
119795 2021-07-23 45 92.698866 43
119796 2021-07-23 46 111.500843 40
119797 2021-07-23 47 700.675634 12
119798 2021-07-23 48 933.134534 4
119799 2021-07-23 49 108.004811 42
解决方案
似乎该a
列是不必要的,因此生成可以变为:
def generate_data_mod():
np.random.seed(202107)
df = pd.MultiIndex.from_product(
[pd.date_range(
start='20150101', end='20210723', freq='D'
).strftime('%Y-%m-%d'),
np.arange(50)],
names=['date', 'code']
).to_frame(index=False)
df['value'] = np.random.random(len(df)) * 1000
# df['a'] = 1 # (If it is needed)
return df
然后我们可以使用sort_values
by value
。然后用于groupby cumcount
枚举组。然后sort_index
恢复顺序:
def get_result_mod(df):
# df = df.drop(columns='a') # If df has the a column
df = df.sort_values(by='value', ascending=False)
df['order'] = df.groupby('date').cumcount()
df = df.sort_index()
return df
健全性检查:
def main():
df = generate_data()
df_mod = generate_data_mod()
# True (note df_mod has no A column)
print(df.drop(columns='a').eq(df_mod).all(None))
# True
print(get_result(df).eq(get_result_mod(df_mod)).all(None))
时间信息:
生成数据大致相同(merge
非常有效):
%timeit generate_data()
21 ms ± 507 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit generate_data_mod()
20.2 ms ± 428 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
get_result这样快得多:
df = generate_data()
%timeit get_result(df)
1.77 s ± 28.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit get_result_mod(df)
51 ms ± 4.17 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
推荐阅读
- python - 如何用文本和 matplotlib 图构建网页
- php - 当一个人尝试直接从 URL 访问网页时如何重定向,但在通过按钮单击访问时应该可以工作
- asp.net - 我可以为 ObjectDataSource 更新参数使用默认值吗?
- ios - Firebase 的 ref().child(pathString: String) 没有按预期工作;返回父级及其邻居而不是我要求的节点
- vba - 根据从 MS Access 数据库读取的数据在 Microsoft Word VBA 中隐藏或显示文本
- ruby-on-rails - caxlsx gem: 生成的 excel 文件显示 #
- css - 小部件中的摘要文本有问题。在同一垂直位置制作第二行
- javascript - 如何在adonis js中将base 64字符串图像保存在数据库中
- routes - 我需要在实时服务器上添加 codeigniter4 数据问题的帮助吗?
- python - 使用 python 对文件中的 url 进行截图只需要一个截图