对于编程我还是一个新手,我正在寻找一种更Python化的方式来实现一些代码。这是虚拟数据:
df = pd.DataFrame({
'Category':np.random.choice( ['Group A','Group B'], 10000),
'Sub-Category':np.random.choice( ['X','Y','Z'], 10000),
'Sub-Category-2':np.random.choice( ['G','F','I'], 10000),
'Product':np.random.choice( ['Product 1','Product 2','Product 3'], 10000),
'Units_Sold':np.random.randint(1,100, size=(10000)),
'Dollars_Sold':np.random.randint(100,1000, size=10000),
'Customer':np.random.choice(pd.util.testing.rands_array(10,25,dtype='str'),10000),
'Date':np.random.choice( pd.date_range('1/1/2016','12/31/2018',
freq='D'), 10000)})
我有很多交易数据,就像我执行各种Groupby一样。我当前的解决方案是像这样创建一个主分组:
master = df.groupby(['Customer','Category','Sub-Category','Product',pd.Grouper(key='Date',freq='A')])['Units_Sold'].sum()\
.unstack()
从那里,我使用.groupby(level =)函数执行各种groupby,以按照所需的方式汇总信息。我通常在每个级别上进行总结。另外,我使用以下代码的一些变体在每个级别创建小计。
y = master.groupby(level=[0,1,2]).sum()
y.index = pd.MultiIndex.from_arrays([
y.index.get_level_values(0),
y.index.get_level_values(1),
y.index.get_level_values(2) + ' Total',
len(y.index)*['']
])
y1 = master.groupby(level=[0,1]).sum()
y1.index = pd.MultiIndex.from_arrays([
y1.index.get_level_values(0),
y1.index.get_level_values(1)+ ' Total',
len(y1.index)*[''],
len(y1.index)*['']
])
y2 = master.groupby(level=[0]).sum()
y2.index = pd.MultiIndex.from_arrays([
y2.index.get_level_values(0)+ ' Total',
len(y2.index)*[''],
len(y2.index)*[''],
len(y2.index)*['']
])
pd.concat([master,y,y1,y2]).sort_index()\
.assign(Diff = lambda x: x.iloc[:,-1] - x.iloc[:,-2])\
.assign(Diff_Perc = lambda x: (x.iloc[:,-2] / x.iloc[:,-3])- 1)\
.dropna(how='all')\
这只是一个例子-我可能执行相同的练习,但是以不同的顺序执行分组。例如-接下来,我可能想按“类别”,“产品”,然后是“客户”进行分组,所以我必须这样做: master.groupby(level = [1,3,0).sum()
然后,我将不得不对上述小计重复整个练习。我还经常更改时间段-可以是特定月份的年末,可以是年初至今,也可以按季度等。
从我到目前为止在编程中学到的知识(很明显,这是最少的),您应该在每次重复代码时都编写一个函数。显然,在此示例中,我将一遍又一遍地重复代码。
是否有一种构造函数的方式,您可以在为每个分组提供总和的功能的同时,向Groupby提供级别,并提供时间?
在此先感谢您提供任何指导。这是非常赞赏。
答案 0 :(得分:2)
对于DRY-er解决方案,请考虑将当前方法推广到已定义的模块中,该模块按日期范围过滤原始数据帧并运行汇总,并接收传入的group_by
级别和日期范围(后期为可选)参数:
方法
def multiple_agg(mylevels, start_date='2016-01-01', end_date='2018-12-31'):
filter_df = df[df['Date'].between(start_date, end_date)]
master = (filter_df.groupby(['Customer', 'Category', 'Sub-Category', 'Product',
pd.Grouper(key='Date',freq='A')])['Units_Sold']
.sum()
.unstack()
)
y = master.groupby(level=mylevels[:-1]).sum()
y.index = pd.MultiIndex.from_arrays([
y.index.get_level_values(0),
y.index.get_level_values(1),
y.index.get_level_values(2) + ' Total',
len(y.index)*['']
])
y1 = master.groupby(level=mylevels[0:2]).sum()
y1.index = pd.MultiIndex.from_arrays([
y1.index.get_level_values(0),
y1.index.get_level_values(1)+ ' Total',
len(y1.index)*[''],
len(y1.index)*['']
])
y2 = master.groupby(level=mylevels[0]).sum()
y2.index = pd.MultiIndex.from_arrays([
y2.index.get_level_values(0)+ ' Total',
len(y2.index)*[''],
len(y2.index)*[''],
len(y2.index)*['']
])
final_df = (pd.concat([master,y,y1,y2])
.sort_index()
.assign(Diff = lambda x: x.iloc[:,-1] - x.iloc[:,-2])
.assign(Diff_Perc = lambda x: (x.iloc[:,-2] / x.iloc[:,-3])- 1)
.dropna(how='all')
.reorder_levels(mylevels)
)
return final_df
汇总运行 (具有不同级别和日期范围)
agg_df1 = multiple_agg([0,1,2,3])
agg_df2 = multiple_agg([1,3,0,2], '2016-01-01', '2017-12-31')
agg_df3 = multiple_agg([2,3,1,0], start_date='2017-01-01', end_date='2018-12-31')
测试 ({final_df
是OP的pd.concat()
输出)
# EQUALITY TESTING OF FIRST 10 ROWS
print(final_df.head(10).eq(agg_df1.head(10)))
# Date 2016-12-31 00:00:00 2017-12-31 00:00:00 2018-12-31 00:00:00 Diff Diff_Perc
# Customer Category Sub-Category Product
# 45mhn4PU1O Group A X Product 1 True True True True True
# Product 2 True True True True True
# Product 3 True True True True True
# X Total True True True True True
# Y Product 1 True True True True True
# Product 2 True True True True True
# Product 3 True True True True True
# Y Total True True True True True
# Z Product 1 True True True True True
# Product 2 True True True True True
答案 1 :(得分:0)
我认为您可以将Product.objects.create(..)
与def home_view(request,slug,*args,**kwargs):
try:
productobject=Product.objects.get(id=1)
except Product.DoesNotExist:
raise Http404
if request.method = 'POST':
form = ProductForm(request.POST)
if form.is_valid():
form.instance.title = "jose"
form.save()
return redirect('home') # name of the view
else:
form = ProductForm()
context= {
"sampletext": "text",
"form": form,
"productobject":productobject,
}
return render(request, "home.html",context)
参数一起使用:
sum
输出:
level