在Pandas中按月和任意属性求和和绘图

问题描述 投票:1回答:1

我目前正在进行数据分析,正在构建一个会计应用程序来跟踪我的开支。

我的目标是在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
...

但是调用summed_df.plot()呈现这个情节:enter image description here

显然,Panda使用日期和类别的组合索引作为x轴,将amount列作为单个数据系列。如上所述,这不是我想要的。

因此,我必须以另一种方式进行求和或以某种方式从索引中删除类别并再次将其作为常规列,但我不知道如何处理此问题。

一些熊猫可以帮我解决吗?

python pandas matplotlib
1个回答
0
投票

考虑将您的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()

Plot Output

© www.soinside.com 2019 - 2024. All rights reserved.