我正在处理我的第一个项目,我正在使用Pygal来显示数据库中的一些数据。
我使用的是最新版本的Python(3.6.5),Flask,Pygal,我的IDE是Pycharm
该项目是一个简单的预算应用程序,其中一个人输入每月支出的计划预算,然后输入该费用/项目的实际金额(例如,每月汽车费用,如汽油)。
我使用Pygal来显示2个条形图。第一个(按预期工作)显示总计划金额与总实际金额:
第二张图表显示了计划与实际每项费用/项目(例如,每月汽车费用,如汽油)
我面临的问题是图表会混淆标签和金额。它们根据输入的顺序显示在图表中,而不是根据项目类型显示。
例如:
在上图中,共有3个项目:Masina(汽车),Salariu(薪水)和Economii(储蓄)。
蓝色列表示的金额(实际金额)应显示在标签Economii下,而不是Masina下,我输入数据作为数据库中的第一个实际数据并不重要。
此外,在数据库中为相同的费用项目(在我们的例子中为Economii)添加更多实际金额只会添加更多列,并且不会在同一列上汇总:
这是我正在使用的数据库查询功能:
def GraphData():
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
db_path = os.path.join(BASE_DIR, 'budget_db.db')
with sqlite3.connect(db_path) as db:
c = db.cursor()
d = db.cursor()
c.execute('SELECT title, category, name, planned_amount_month FROM Post')
d.execute('SELECT title_actual, category_actual, actual_amount_name, actual_amount FROM ActualPost')
data_planned = c.fetchall()
data_actual = d.fetchall()
return data_planned, data_actual
以下是我为这两个图表创建的路线。标签是从title_planned
列表中提取的,我感觉我面临的问题是因为我正在创建列表而我正在追加它们。
我想我应该创建词典,但我不知道如何不搞乱其他一切:
@posts.route("/home")
def graphing():
data_planned, data_actual = GraphData()
title_planned = []
value_planned = []
title_actual = []
value_actual = []
for planned_row in data_planned:
title_planned.append(planned_row[2])
value_planned.append(planned_row[3])
for actual_row in data_actual:
title_actual.append(actual_row[2])
value_actual.append(actual_row[3])
graph = pygal.Bar(title=u'Total Planned Values vs Total Actual Values')
graph.add('Planned', [{'value': sum(value_planned), 'label': 'Total for Planned Budget:'}])
graph.add('Actual', [{'value': sum(value_actual), 'label': 'Total for Actual Amounts:'}])
graph_data = graph.render_data_uri()
graph_all = pygal.Bar(title=u'Planned Budget per item vs Actual Amounts per item')
graph_all.x_labels = title_planned
graph_all.add('Planned', value_planned)
graph_all.add('Actual', value_actual)
graph_all_data = graph_all.render_data_uri()
return render_template('home.html', graph_data=graph_data, graph_all_data=graph_all_data)
修改
我一直尝试在路线中使用2个词典,费用项目为dict键(title_planned_sum
/ title_actual_sum
),金额为dict值(value_planned_sum
/ { {1}}):
value_actual_sum
以下是完整路线:
tv_planned = dict(zip(title_planned, value_planned))
tv_planned_sum = {title_planned_sum: sum(value_planned_sum) for title_planned_sum, value_planned_sum in tv_planned.items()}
tv_actual = dict(zip(title_actual, value_actual))
tv_actual_sum = {title_actual_sum: sum(value_actual_sum) for title_actual_sum, value_actual_sum in tv_actual.items()}
但是,当然,现在我收到了这个调试错误:
@posts.route("/home") def graphing(): data_planned, data_actual = GraphData() title_planned = [] value_planned = [] title_actual = [] value_actual = [] for planned_row in data_planned: title_planned.append(planned_row[2]) value_planned.append(planned_row[3]) for actual_row in data_actual: title_actual.append(actual_row[2]) value_actual.append(actual_row[3]) tv_planned = dict(zip(title_planned, value_planned)) tv_planned_sum = {title_planned_sum: sum(value_planned_sum) for title_planned_sum, value_planned_sum in tv_planned.items()} tv_actual = dict(zip(title_actual, value_actual)) tv_actual_sum = {title_actual_sum: sum(value_actual_sum) for title_actual_sum, value_actual_sum in tv_actual.items()} graph = pygal.Bar(title=u'Total Planned Values vs Total Actual Values') graph.add('Planned', [{'value': sum(value_planned), 'label': 'Total for Planned Budget:'}]) graph.add('Actual', [{'value': sum(value_actual), 'label': 'Total for Actual Amounts:'}]) graph_data = graph.render_data_uri() graph_all = pygal.Bar(title=u'Planned Budget per item vs Actual Amounts per item') graph_all.x_labels = title_planned graph_all.add('Planned', tv_planned_sum) graph_all.add('Actual', tv_actual_sum) graph_all_data = graph_all.render_data_uri() return render_template('home.html', graph_data=graph_data, graph_all_data=graph_all_data)
这是因为,在我尝试使用的2个词典中,我试图对使用 TypeError: 'float' object is not iterable
接收多个值的每个键的值求和。
答案 0 :(得分:0)
我开始工作了!
最后我意识到我的问题过于复杂,所以我拿出一支笔和纸,开始做一些伪代码看看我的代码中的第一步,我可以轻松地计算导致我头疼的浮点数。
步骤1:在我的路线中,我可以创建一个包含嵌套元组的列表(每个包含2个元素:str和float)
步骤2:现在,如果某些元组有索引[0]上的元素相同,如何对索引[1]上的浮点元素求和?
所以,我问this question on reddit.com/r/learnpython和用户 diech 给了我一个我可以成功使用的想法:导入itertools
包并从中导入groupby()
。
以下是我的路线代码现在的样子:
@posts.route("/home")
def graphing():
data_planned, data_actual = GraphData()
title_planned = []
value_planned = []
title_actual = []
value_actual = []
planned = []
actual = []
for planned_row in data_planned:
title_planned.append(planned_row[2])
value_planned.append(planned_row[3])
planned_list = zip(title_planned, value_planned)
for key, group in itertools.groupby(sorted(planned_list), lambda x: x[0]):
asum = 0
for i in group:
asum += i[1]
planned.append((key, asum))
planned_dict = dict(planned)
for actual_row in data_actual:
title_actual.append(actual_row[2])
value_actual.append(actual_row[3])
actual_list = zip(title_actual, value_actual)
for key, group in itertools.groupby(sorted(actual_list), lambda x: x[0]):
asum = 0
for i in group:
asum += i[1]
actual.append((key, asum))
actual_dict = dict(actual)
graph = pygal.Bar(title=u'Total Planned Values vs Total Actual Values')
graph.add('Planned', [{'value': sum(value_planned), 'label': 'Total for Planned Budget:'}])
graph.add('Actual', [{'value': sum(value_actual), 'label': 'Total for Actual Amounts:'}])
graph_data = graph.render_data_uri()
graph_all = pygal.Bar(title=u'Planned Budget per item vs Actual Amounts per item')
graph_all.x_labels = title_planned
graph_all.add('Planned', planned_dict)
graph_all.add('Actual', actual_dict)
graph_all_data = graph_all.render_data_uri()
return render_template('home.html', graph_data=graph_data, graph_all_data=graph_all_data)