【发布时间】:2021-09-28 19:27:21
【问题描述】:
我正在编写一个程序来监控和记录前台应用程序的使用时间并将它们保存在 SQL 数据库中。然后,我想检索前几天的数据并将其全部编译成堆叠条形图。在这里,x 轴将记录使用记录的不同天数,每个条形中的各种堆栈将代表使用的每个应用程序。
在我的程序中,我创建了 2 个表,一个用于记录每天的应用使用情况(每天的数据具有不同的主键 ID),另一个用于记录每天的主键。
表 1:
| _id | Application | usage_time |
|---|---|---|
| 0 | Google Chrome | 245.283942928347 |
| 0 | Finder | 123.384234239734 |
| 0 | PyCharm | 100.484829432934 |
| 1 | PyCharm | 1646.46116232872 |
| 1 | SQLiteStudio | 160.25696277618408 |
| 1 | Google Chrome | 1756.8145654201508 |
| 1 | Microsoft Teams | 150.2583293914795 |
表 2:
| Date | daily_id |
|---|---|
| 2021-07-18 07:25:25.376734 | 0 |
| 2021-07-18 07:27:57.419574 | 1 |
在我的堆积条形图程序中,我想出了这段代码来细化要放入堆积条形图中的数据:
conn = sqlite3.connect('daily_usage_monitor.sqlite', detect_types=sqlite3.PARSE_DECLTYPES)
all_app_data = conn.execute('SELECT all_usage_information.date, monitor.application, monitor.usage_time '
'FROM all_usage_information '
'INNER JOIN monitor ON all_usage_information.daily_id = monitor._id '
'ORDER BY all_usage_information.date, monitor.usage_time ASC').fetchall()
for date, app, usage_time in all_app_data:
print(f'{date} - {app}: {usage_time}')
conn.close()
daily_data = {}
# Create nested dictionary - key = each date, value = dictionary of different apps & their time usage durations
for date, app, time in all_app_data:
conditions = [date not in daily_data, app != 'loginwindow']
if all(conditions):
daily_data[date] = {app: time}
elif not conditions[0] and conditions[1]:
daily_data[date].update({app: time})
print(daily_data) # TODO: REMOVE AFTER TESTING
total_time = 0
# Club any applications that account for <5% of total time into 1 category called 'Other'
for date, app_usages in daily_data.items():
total_time = sum(time for app, time in app_usages.items())
refined_data = {}
for key, value in app_usages.items():
if value/total_time < 0.05:
refined_data['Others'] = refined_data.setdefault('Others', 0) + value
else:
refined_data[key] = value
daily_data[date] = refined_data
print(daily_data) # TODO: REMOVE AFTER TESTING
# Add key:value pairs initializing apps to 0 which are either used in past and never used again
# or used in future but not in past
used_apps = set()
counter = 0
for date, app_usages in reversed(daily_data.items()):
for app, time in app_usages.items():
used_apps.add(app)
counter += 1
if counter != 1:
for used_app in used_apps:
if used_app not in app_usages.keys():
app_usages[used_app] = 0
used_apps = set()
counter = 0
for date, app_usages in daily_data.items():
for app, time in app_usages.items():
used_apps.add(app)
counter += 1
if counter != 1:
for used_app in used_apps:
if used_app not in app_usages.keys():
app_usages[used_app] = 0
print(daily_data) # TODO: REMOVE AFTER TESTING
# Takes the nested dictionary and breaks it into a labels list and a dictionary with apps & time usages for each day
# Sorts data so it can be used to create composite bar chart
final_data = {}
labels = []
for date, app_usages in daily_data.items():
labels.append(date.strftime('%d/%m/%Y'))
for app, time in app_usages.items():
# time = datetime.timedelta(seconds=time) # TODO: CHECK WHAT TO DO
if app not in final_data:
final_data[app] = [time]
else:
final_data[app].append(time)
print(final_data)
final_data = dict(sorted(final_data.items(), key=lambda x: x[1], reverse=True))
print(final_data) # TODO: REMOVE AFTER TESTING
这个处理给出这个输出: {'Google Chrome':[245.283942928347,1756.8145654201508]'Finder':[123.3842342397347,0],'Pycharm':[100.4848294329348,1646.46129348,1646.46116232872],'其他':[0,310.5152921676636]}
然后,为了创建堆积条形图,这是我写的代码:
width = 0.5
counter = 0
fig, ax = plt.subplots()
for key, value in final_data.items():
if counter == 0:
ax.bar(labels, value, width=width, label=key)
else:
ax.bar(labels, value, width=width, bottom=bottom, label=key)
bottom = value
counter += 1
ax.set_ylabel('Time usage on applications')
ax.set_xlabel('Dates (DD-MM-YYYY)')
ax.set_title('Time Usage Trend')
ax.legend()
plt.show()
但是,这是我得到的输出:
如您所见,第一个栏有重叠,第二个堆叠栏缺少 Google Chrome 栏,Finder 栏非常小,尽管与其他数据相比并没有那么小。
关于如何修复此堆积条形图的任何想法?还希望对如何改进数据处理提出建议
【问题讨论】:
标签: python python-3.x matplotlib bar-chart stacked-chart