如何从含字典列表的字典中指定数据(篮板/助攻/得分)绘图?
问题描述
我尝试通过绘图验证操作是否正确,但不确定具体实现方法。
我拥有如下字典:
k = {'Boston': [{'name': 'Jayson Tatum','rebounds': 8.0, 'assists': 4.4, 'points': 26.9}, {'name': 'Jaylen Brown','rebounds': 6.1, 'assists': 3.5, 'points': 23.6}, {'name': 'Marcus Smart', 'rebounds': 3.8, 'assists': 5.9, 'points': 12.1}], 'Phoenix': [{'name': 'Devin Booker', 'rebounds': 5.0, 'assists': 4.8, 'points': 26.8}, {'name': 'Deandre Ayton', 'rebounds': 10.2, 'assists': 1.4, 'points': 17.2}, {'name': 'Chris Paul', 'rebounds': 4.4, 'assists': 0.0, 'points': 14.7}], 'Philadelphia': [{'name': 'Tyrese Maxey', 'rebounds': 3.2, 'assists': 4.3, 'points': 17.5}, {'name': 'Tobias Harris', 'rebounds': 6.8, 'assists': 3.5, 'points': 17.2}, {'name': 'Georges Niang','rebounds': 2.7, 'assists': 1.3, 'points': 9.2}], 'Milwaukee': [{'name': 'Giannis Antetokounmpo', 'rebounds': 11.6, 'assists': 5.8, 'points': 29.9}, {'name': 'Khris Middleton','rebounds': 5.4, 'assists': 5.4, 'points': 20.1}, {'name': 'Jrue Holiday','rebounds': 4.5, 'assists': 6.8, 'points': 18.3}], 'Golden State': [{'name': 'Stephen Curry', 'rebounds': 5.2, 'assists': 6.3, 'points': 25.5}, {'name': 'Klay Thompson', 'rebounds': 3.9, 'assists': 2.8, 'points': 20.4}, {'name': 'Jordan Poole', 'rebounds': 3.4, 'assists': 4.0, 'points': 18.5}], 'Miami': [{'name': 'Jimmy Butler', 'rebounds': 5.9, 'assists': 5.5, 'points': 21.4}, {'name': 'Tyler Herro', 'rebounds': 5.0, 'assists': 4.0, 'points': 20.7}, {'name': 'Bam Adebayo', 'rebounds': 10.1, 'assists': 3.4, 'points': 19.1}], 'Dallas': [{'name': 'Luka Dončić','rebounds': 9.1, 'assists': 8.7, 'points': 28.4}, {'name': 'Jalen Brunson', 'rebounds': 3.9, 'assists': 4.8, 'points': 16.3}, {'name': 'Tim Hardaway Jr.', 'rebounds': 3.7, 'assists': 2.2, 'points': 14.2}], 'Memphis': [{'name': 'Ja Morant', 'rebounds': 5.7, 'assists': 6.7, 'points': 27.4}, {'name': 'Dillon Brooks','rebounds': 3.2, 'assists': 2.8, 'points': 18.4}, {'name': 'Desmond Bane', 'rebounds': 4.4, 'assists': 2.7, 'points': 18.2}]}
注:已修正原字典中Dallas队两个球员的语法错误(缺少逗号和引号)
该字典以球队名为键,对应值为包含三个球员字典的列表,每个球员字典存储其姓名、rebounds(篮板)、assists(助攻)、points(得分)数据。
我想实现的是:选择绘制篮板、助攻或得分中的某一项数据,但不知道如何指定要绘制的数据。
我曾尝试将k转换为DataFrame,但行数据仍是字典列表,不知如何访问以用于绘图。
我还尝试了如下代码,但未成功:
for team in k: players = top_players_in_teams[team] names = list(players.keys()) values = [value[wantedType] for value in list(players.values())] team_bars = ax.bar(names, values, label=team, zorder=3) team_bars.set_label(team) ax.set_title("SOMETHING") ax.legend(title="TeaM", bbox_to_anchor=(1.05, 1)) plt.grid(b=True, which="major", axis="y", zorder=0) plt.xticks(rotation=90)
解决方案
方法一:直接遍历字典绘图
先明确要绘制的指标(比如wanted_type = 'rebounds'),然后遍历每个球队的球员列表,提取姓名和对应指标值,再分组绘制避免柱子重叠。
完整代码示例:
import matplotlib.pyplot as plt # 修正后的字典 k = {'Boston': [{'name': 'Jayson Tatum','rebounds': 8.0, 'assists': 4.4, 'points': 26.9}, {'name': 'Jaylen Brown','rebounds': 6.1, 'assists': 3.5, 'points': 23.6}, {'name': 'Marcus Smart', 'rebounds': 3.8, 'assists': 5.9, 'points': 12.1}], 'Phoenix': [{'name': 'Devin Booker', 'rebounds': 5.0, 'assists': 4.8, 'points': 26.8}, {'name': 'Deandre Ayton', 'rebounds': 10.2, 'assists': 1.4, 'points': 17.2}, {'name': 'Chris Paul', 'rebounds': 4.4, 'assists': 0.0, 'points': 14.7}], 'Philadelphia': [{'name': 'Tyrese Maxey', 'rebounds': 3.2, 'assists': 4.3, 'points': 17.5}, {'name': 'Tobias Harris', 'rebounds': 6.8, 'assists': 3.5, 'points': 17.2}, {'name': 'Georges Niang','rebounds': 2.7, 'assists': 1.3, 'points': 9.2}], 'Milwaukee': [{'name': 'Giannis Antetokounmpo', 'rebounds': 11.6, 'assists': 5.8, 'points': 29.9}, {'name': 'Khris Middleton','rebounds': 5.4, 'assists': 5.4, 'points': 20.1}, {'name': 'Jrue Holiday','rebounds': 4.5, 'assists': 6.8, 'points': 18.3}], 'Golden State': [{'name': 'Stephen Curry', 'rebounds': 5.2, 'assists': 6.3, 'points': 25.5}, {'name': 'Klay Thompson', 'rebounds': 3.9, 'assists': 2.8, 'points': 20.4}, {'name': 'Jordan Poole', 'rebounds': 3.4, 'assists': 4.0, 'points': 18.5}], 'Miami': [{'name': 'Jimmy Butler', 'rebounds': 5.9, 'assists': 5.5, 'points': 21.4}, {'name': 'Tyler Herro', 'rebounds': 5.0, 'assists': 4.0, 'points': 20.7}, {'name': 'Bam Adebayo', 'rebounds': 10.1, 'assists': 3.4, 'points': 19.1}], 'Dallas': [{'name': 'Luka Dončić','rebounds': 9.1, 'assists': 8.7, 'points': 28.4}, {'name': 'Jalen Brunson', 'rebounds': 3.9, 'assists': 4.8, 'points': 16.3}, {'name': 'Tim Hardaway Jr.', 'rebounds': 3.7, 'assists': 2.2, 'points': 14.2}], 'Memphis': [{'name': 'Ja Morant', 'rebounds': 5.7, 'assists': 6.7, 'points': 27.4}, {'name': 'Dillon Brooks','rebounds': 3.2, 'assists': 2.8, 'points': 18.4}, {'name': 'Desmond Bane', 'rebounds': 4.4, 'assists': 2.7, 'points': 18.2}]} # 指定要绘制的指标:rebounds/assists/points wanted_type = 'rebounds' # 设置绘图参数 fig, ax = plt.subplots(figsize=(12, 6)) bar_width = 0.1 teams = list(k.keys()) x = range(len(teams)) # 遍历每个球队,绘制每个球员的指标 for i, team in enumerate(teams): players = k[team] # 提取球员姓名和对应指标值 player_names = [p['name'] for p in players] player_values = [p[wanted_type] for p in players] # 为每个球员设置x轴位置(错开不同球队的柱子) player_x = [i + j*bar_width for j in range(len(player_names))] # 绘制柱子 bars = ax.bar(player_x, player_values, width=bar_width) # 给每个柱子添加数值标签 for bar, name in zip(bars, player_names): height = bar.get_height() ax.text(bar.get_x() + bar.get_width()/2., height, f'{name}\n{height:.1f}', ha='center', va='bottom', fontsize=8) # 设置x轴刻度和标签 ax.set_xticks([i + bar_width for i in x]) ax.set_xticklabels(teams) # 设置标题和轴标签 ax.set_title(f'NBA Players {wanted_type.capitalize()} by Team') ax.set_ylabel(wanted_type.capitalize()) ax.set_xlabel('Teams') plt.grid(b=True, which="major", axis="y", zorder=0) plt.tight_layout() plt.show()
方法二:转换为DataFrame后绘图
先把字典展开成扁平的DataFrame,利用pandas或seaborn的绘图功能更便捷:
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # 修正后的字典 k = {'Boston': [{'name': 'Jayson Tatum','rebounds': 8.0, 'assists': 4.4, 'points': 26.9}, {'name': 'Jaylen Brown','rebounds': 6.1, 'assists': 3.5, 'points': 23.6}, {'name': 'Marcus Smart', 'rebounds': 3.8, 'assists': 5.9, 'points': 12.1}], 'Phoenix': [{'name': 'Devin Booker', 'rebounds': 5.0, 'assists': 4.8, 'points': 26.8}, {'name': 'Deandre Ayton', 'rebounds': 10.2, 'assists': 1.4, 'points': 17.2}, {'name': 'Chris Paul', 'rebounds': 4.4, 'assists': 0.0, 'points': 14.7}], 'Philadelphia': [{'name': 'Tyrese Maxey', 'rebounds': 3.2, 'assists': 4.3, 'points': 17.5}, {'name': 'Tobias Harris', 'rebounds': 6.8, 'assists': 3.5, 'points': 17.2}, {'name': 'Georges Niang','rebounds': 2.7, 'assists': 1.3, 'points': 9.2}], 'Milwaukee': [{'name': 'Giannis Antetokounmpo', 'rebounds': 11.6, 'assists': 5.8, 'points': 29.9}, {'name': 'Khris Middleton','rebounds': 5.4, 'assists': 5.4, 'points': 20.1}, {'name': 'Jrue Holiday','rebounds': 4.5, 'assists': 6.8, 'points': 18.3}], 'Golden State': [{'name': 'Stephen Curry', 'rebounds': 5.2, 'assists': 6.3, 'points': 25.5}, {'name': 'Klay Thompson', 'rebounds': 3.9, 'assists': 2.8, 'points': 20.4}, {'name': 'Jordan Poole', 'rebounds': 3.4, 'assists': 4.0, 'points': 18.5}], 'Miami': [{'name': 'Jimmy Butler', 'rebounds': 5.9, 'assists': 5.5, 'points': 21.4}, {'name': 'Tyler Herro', 'rebounds': 5.0, 'assists': 4.0, 'points': 20.7}, {'name': 'Bam Adebayo', 'rebounds': 10.1, 'assists': 3.4, 'points': 19.1}], 'Dallas': [{'name': 'Luka Dončić','rebounds': 9.1, 'assists': 8.7, 'points': 28.4}, {'name': 'Jalen Brunson', 'rebounds': 3.9, 'assists': 4.8, 'points': 16.3}, {'name': 'Tim Hardaway Jr.', 'rebounds': 3.7, 'assists': 2.2, 'points': 14.2}], 'Memphis': [{'name': 'Ja Morant', 'rebounds': 5.7, 'assists': 6.7, 'points': 27.4}, {'name': 'Dillon Brooks','rebounds': 3.2, 'assists': 2.8, 'points': 18.4}, {'name': 'Desmond Bane', 'rebounds': 4.4, 'assists': 2.7, 'points': 18.2}]} # 展开字典为DataFrame data = [] for team, players in k.items(): for player in players: row = player.copy() row['team'] = team data.append(row) df = pd.DataFrame(data) # 指定要绘制的指标 wanted_type = 'points' # 绘图:按球队分组,每个球员的指标值 fig, ax = plt.subplots(figsize=(12, 6)) sns.barplot(data=df, x='team', y=wanted_type, hue='name', ax=ax) # 设置标题和标签 ax.set_title(f'NBA Players {wanted_type.capitalize()} by Team') ax.set_ylabel(wanted_type.capitalize()) ax.set_xlabel('Teams') # 调整图例位置 ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.grid(b=True, which="major", axis="y", zorder=0) plt.xticks(rotation=45) plt.tight_layout() plt.show()
原代码问题分析
- 变量名错误:
top_players_in_teams未定义,应替换为k - 数据结构误解:
players是列表而非字典,不能用players.keys(),需遍历列表中的球员字典提取数据 - 柱子位置重叠:直接用球队名作为x轴会导致不同球队的柱子重叠,需调整x轴坐标错开位置
内容的提问来源于stack exchange,提问作者ili
相关产品推荐
相关产品推荐

