【发布时间】:2019-02-11 22:59:48
【问题描述】:
我对编程相当陌生,正在寻找一种更 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 groupby:
master = df.groupby(['Customer','Category','Sub-Category','Product',pd.Grouper(key='Date',freq='A')])['Units_Sold'].sum()\
.unstack()
从那里,我使用 .groupby(level=) 函数执行各种分组,以我正在寻找的方式聚合信息。我通常在每个级别做一个总结。此外,我使用以下代码的一些变体在每个级别创建小计。
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')\
这只是一个示例 - 我可以执行相同的练习,但以不同的顺序执行 groupby。例如 - 接下来我可能想按“类别”、“产品”和“客户”分组,所以我必须这样做: master.groupby(level=[1,3,0).sum()
然后我将不得不重复上述小计的整个练习。我还经常更改时间段 - 可能是特定月份的年终,可能是年初至今,可能是季度等。
根据我目前在编程中学到的知识(很明显,这很少见!),您应该在每次重复代码时编写一个函数。显然我在这个例子中一遍又一遍地重复代码。
有没有一种方法可以构建一个函数,您可以在其中向 Groupby 提供级别以及时间范围,同时创建一个用于对每个级别进行小计的函数?
在此先感谢您提供任何指导。这是非常赞赏。
【问题讨论】:
-
你的
y2真的是你的意思吗,还是应该有level=[0]? -
您是对的,我已经对其进行了编辑以反映这一点。谢谢!
标签: python python-3.x pandas