我目前正在从R切换到python,想知道我是否可以加快以下数据帧操作的速度。我有一个包含50万行和17列的销售数据集,在将它们放入仪表板之前,需要对其进行一些计算。我的数据如下:
location time product sales
store1 2017 brandA 10
store1 2017 brandB 17
store1 2017 brandC 15
store1 2017 brandD 19
store1 2017 catTot 86
store2 2017 brandA 8
store2 2017 brandB 23
store2 2017 brandC 5
store2 2017 brandD 12
store2 2017 catTot 76
. . . .
. . . .
. . . .
. . . .
catTot是我从原始数据集中获得的预先汇总,该原始数据集显示了给定商店在给定时间段内的总销售额。如您所见,其他产品仅占总数的一小部分,从不相加,但是它们却包含在总数中。由于我想反映给定位置的总销售额而不显示所有产品(由于仪表板中的性能问题),因此我需要将catTot
值替换为实际上是当前值减去总和的总计其他产品。
当前,我遍历嵌套的for
循环以进行更改。代码如下:
df['location'] = df.location.astype('category')
df['time'] = df.time.astype('category')
var_geo = []
var_time = []
for var_time in df.time.cat.categories:
for var_geo in df.location.cat.categories:
df_tmp = []
fct_eur = []
df_tmp = df[(df['location'] == var_geo) & (df['time'] == var_time)]
fct_eur = df_tmp.iloc[len(df_tmp)-1,3] df_tmp.iloc[0:len(df_tmp)-2,3].sum()
df.loc[(df['location'] == var_geo) & (df['time'] == var_time) & (df['product'] == 'catTot'), ['sales']] = fct_eur
如您所见,catTot
始终是被屏蔽数据帧中的最后一行。现在,此操作每次大约需要9分钟,因为我有23个商店位置,大约880种产品,30个时间段和5种不同的度量,因此大约有50万行。有没有更优雅或更不快的方法来进行这种操作?
答案 0 :(得分:1)
您可以创建一个分组密钥,其中所有非“ catTot”都设置为“ sales”,然后pivot_table
聚合sales
列,例如:
agg = df.pivot_table(
index=['location', 'time'],
columns=np.where(df['product'] == 'catTot', 'catTot', 'sales'),
values='sales',
aggfunc='sum'
)
这会给你:
catTot sales
location time
store1 2017 86 61
store2 2017 76 48
然后您可以执行new_total = agg['catTot'] - agg['sales']
:
location time
store1 2017 25
store2 2017 28
dtype: int64
答案 1 :(得分:0)
一个朋友实际上提出了解决我的问题的这种方式。这段代码也是他的代码,它构建了一个嵌套目录,并将度量添加到每一行的键中,但是除catTot之外的所有内容都乘以-1。因此,最后将仅保留其余部分。
for row in data:
safe_add(mapping, row[0], int(row[1]), row[2], int(row[3]))
def safe_add(mapping, store, year, brand, count):
if not store in mapping:
mapping[store] = {}
if not year in mapping[store]:
mapping[store][year] = 0
if brand != 'catTot':
count = count * -1
new_count = count + mapping[store][year]
mapping[store][year] = new_count
获取嵌套目录后,我遍历字典一次,以获取需要写出的行数。我这样做是为了能够预先填充一个空的df并将其填充。
counter=0
for geo in mapping.keys():
for time in mapping[store].keys():
counter +=1
df_annex = pd.DataFrame(data=None, index=np.arange(0, counter), columns=df.columns)
for geo in mapping.keys():
for time in mapping[store].keys():
df_annex.iloc[counterb, 0] = geo
.
.
写完字典后,我简单地从df中提取了旧的总计,并将其与附件合并。结果是7.88s与9分钟的时间。