我目前正在进行数据分析,正在构建一个会计应用程序来跟踪我的开支。
我的目标是在Django应用程序中跟踪我的费用,使用Pandas进行一些分析并使用Matplotlib进行可视化。
我的数据基础来自Django ORM查询,如下所示:
qs = MyExpenses.objects.values('date', 'amount', 'category')
然后我使用Pandas的from_records
方法创建索引的DataFrame:
df = pd.DataFrame.from_records(qs, index='date', coerce_float=True)
df.index = pd.to_datetime(df.index) # manually make index a proper DateTimeIndex, datetime.date objects don't seem to be converted automatically
使用df.head()
检查DataFrame的内容:
amount category
date
2017-12-29 14.90 Food
2017-12-27 2.98 Household
2017-12-27 9.72 Food
2017-12-24 2.00 Food
2017-12-23 1.49 Household
到目前为止看起来不错
此时我不知道如何正确地进行。我希望每个类别的费用总计为每月一次。
这个groupby操作:
summed_df = df.groupby([pd.Grouper(freq='1M'), 'category']).sum()
返回正确聚合的数据:
amount
date category
2016-02-29 Cosmetics 2.45
Food 376.41
Household 43.82
Leisure 630.13
2016-03-31 Food 345.41
Household 14.76
Leisure 553.35
...
显然,Panda使用日期和类别的组合索引作为x轴,将amount列作为单个数据系列。如上所述,这不是我想要的。
因此,我必须以另一种方式进行求和或以某种方式从索引中删除类别并再次将其作为常规列,但我不知道如何处理此问题。
一些熊猫可以帮我解决吗?
考虑将您的groupby旋转到每个类别成为他们自己的列的单独行。下面用随机数据进行演示(种子重复性):
数据
import numpy as np
import pandas as pd
import datetime as dt
import time
import matplotlib.pyplot as plt
epoch_time = int(time.time())
np.random.seed(55)
df = pd.DataFrame({'date': [dt.datetime.fromtimestamp(np.random.randint(1450000000, epoch_time))
for _ in range(500)],
'category': ["".join(np.random.choice(['Cosmetics', 'Food', 'Household', 'Leisure'],1))
for _ in range(500)],
'amount': abs(np.random.randn(500))*100}).set_index('date')
print(df.head(10))
# amount category
# date
# 2016-12-23 10:30:18 10.711083 Household
# 2016-05-05 15:40:07 176.670986 Cosmetics
# 2017-04-24 17:55:04 16.700308 Cosmetics
# 2018-01-02 06:41:33 242.877311 Food
# 2017-12-15 00:06:29 95.990759 Household
# 2016-07-30 18:22:13 45.610068 Food
# 2016-07-13 16:00:11 60.704399 Leisure
# 2017-04-15 20:28:03 12.410939 Food
# 2017-12-07 19:33:18 61.599076 Cosmetics
# 2017-10-29 20:20:07 117.341928 Leisure
Groupby和Plot
summed_df = df.groupby([pd.Grouper(freq='1M'), 'category']).sum()\
.reset_index().pivot(index='date', columns='category', values='amount')
summed_df.plot()