如何创建堆积条形图?

Angad_K

我正在编写一个程序来监视和记录前台应用程序的使用时间并将它们保存在 SQL 数据库中。然后我想检索前几天的数据,并将它们全部编译成堆积条形图。在这里,x 轴将记录使用情况的不同天数,每个条形中的不同堆栈将代表使用的每个应用程序。

在我的程序中,我创建了 2 个表,一个记录每天的应用程序使用情况(每个新一天的数据具有不同的主键 ID),另一个表记录每天的主键。

表格1:

_ID 应用 使用时间
0 谷歌浏览器 245.283942928347
0 发现者 123.384234239734
0 PyCharm 100.484829432934
1 PyCharm 1646.46116232872
1 SQLiteStudio 160.25696277618408
1 谷歌浏览器 1756.8145654201508
1 微软团队 150.2583293914795

表 2:

日期 每日 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

该处理是给这个输出:{ '谷歌浏览器':[245.283942928347,1756.8145654201508], '搜索':[123.3842342397347,0], 'PyCharm':[100.4848294329348,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()

但是,这是我得到的输出:

在此处输入图片说明

As you can see, the 1st bar has an overlap, the Google Chrome bar is missing from the 2nd stacked bar, and the Finder bar is extremely small, even though it is not that small comparative to the other data.

Any ideas on how I could fix this stacked bar chart? Would also appreciate suggestions on how to refine the data processing

Coup

Troubleshooting matplotlib stacked bar charts

It looks like your problem is the for loop. You are iterating through the keys and values, and plotting the values each iteration.

for key, value in final_data.items():
    print(key, value)

Google Chrome [245.283942928347, 1756.8145654201508]
Finder [123.3842342397347, 0]
PyCharm [100.4848294329348, 1646.46116232872]
Others [0, 310.5152921676636]

您打算做的是在每次迭代中绘制每个 LABEL。您可以更改 for 循环,但我建议您将 dict 放入 pandas 数据帧并使用pandas DataFrame.plot.bar(stacked=True)为堆积条形图设置“底部”或“左侧”需要很多麻烦。

final_data = pd.DataFrame({
    'Google Chrome': [245.283942928347, 1756.8145654201508], 
    'Finder': [123.3842342397347, 0], 
    'PyCharm': [100.4848294329348, 1646.46116232872], 
    'Others': [0, 310.5152921676636]}
)

final_data.plot.bar(stacked=True)

在此处输入图片说明

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章