首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >利用径向柱图探索星球大战数据

利用径向柱图探索星球大战数据

作者头像
HsuHeinrich
发布2025-11-20 11:42:29
发布2025-11-20 11:42:29
260
举报
文章被收录于专栏:HsuHeinrichHsuHeinrich

利用径向柱图探索星球大战数据

代码语言:javascript
复制
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from matplotlib.lines import Line2D
from matplotlib import font_manager

import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning) 

数据探索

以下数据如果有需要的同学可关注公众号HsuHeinrich,回复【数据可视化】自动获取~

代码语言:javascript
复制
# 导入数据
df = pd.read_csv('https://raw.githubusercontent.com/Lisa-Ho/small-data-projects/main/2023/2308-star-wars-scripts/episode1_each_line_of_anakin_clean.csv')

df.head()
image-20240129181218963
image-20240129181218963

image-20240129181218963

《星球大战》阿纳金对话数据: to:对话角色名称 number:数量

基本径向柱图

代码语言:javascript
复制
# 计算每个bar的位置(角度)
x_max = 2*np.pi
df['angular_pos'] = np.linspace(0, x_max, len(df), endpoint=False)

# 自定义颜色
chart_colors = {'bg': '#0C081F', 'QUI-GON': '#F271A7', 'PADME': '#40B8E1', 'OBI-WAN':'#75EAB6',
                'R2D2': '#F4E55E', 'other': '#444A68'}

# 将颜色映射给'to'字段
df['colors'] = df['to'].map(chart_colors)

# 缺失值填充
df['colors'] = df['colors'].fillna(chart_colors['other'])

# 查看调色板
sns.palplot(list(chart_colors.values()))
output_7_0
output_7_0

output_7_0

代码语言:javascript
复制
# 初始化布局
fig, ax = plt.subplots(figsize=(10, 10), subplot_kw={'projection': 'polar'})

# 条形图
ax.bar(df['angular_pos'], df['number'], alpha=1, color=df['colors'] , linewidth=0, width=0.052, zorder=3)

# 自定义轴
max_value = 50
r_offset = -10      
ax.set_rlim(0, max_value)
ax.set_rorigin(r_offset)

# 从顶部开始顺时针绘制条形图
ax.set_theta_zero_location('N')     
ax.set_theta_direction(-1)      

# 标题+著作信息
plt.figtext(0.5,1.03, 'Star Wars Episode I', fontfamily='Mandalore', fontsize=55, ha='center')
plt.figtext(0.5,0.98, 'Each line of Anakin', fontfamily='Ubuntu',fontsize=24, ha='center')
plt.figtext(0.5,0.08, 'Data: jcwieme/data-scripts-star-wars  |  Design: Lisa Hornung',       
            fontfamily='Mandalore',fontsize=8, ha='center', alpha=0.75)

plt.show()
output_8_0
output_8_0

output_8_0

自定义布局

代码语言:javascript
复制
# 自定义缩放y轴
max_value = 50
r_offset = -10
r2 = max_value - r_offset
alpha = r2 - r_offset
v_offset = r_offset**2 / alpha
forward = lambda value: ((value + v_offset) * alpha)**0.5 + r_offset
reverse = lambda radius: (radius - r_offset) ** 2 / alpha - v_offset
ax.set_rlim(0, max_value)
ax.set_rorigin(r_offset)
ax.set_yscale('function', functions=(
    lambda value: np.where(value >= 0, forward(value), value),
    lambda radius: np.where(radius > 0, reverse(radius), radius)))

# 自定义标签
ax.set_rlabel_position(0)
ax.set_yticks([10,20,30,40])
ax.set_yticklabels([10,20,30,40],fontsize=9)

# 自定义网格线
ax.set_thetagrids(angles=[])
ax.grid(visible=True, axis='y', zorder=2, linewidth=0.75)

# 移除边框
ax.spines[:].set_visible(False)

fig
output_10_0
output_10_0

output_10_0

最终的图

代码语言:javascript
复制
# 初始化极坐标图
fig, ax = plt.subplots(figsize=(10, 10), 
                       subplot_kw={'projection': 'polar'})

# 背景色
ax.set_facecolor(chart_colors['bg'])
fig.set_facecolor(chart_colors['bg'])

# 添加条形图
ax.bar(df['angular_pos'], df['number'], alpha=1, color=df['colors'], 
       linewidth=0, width=0.052, zorder=3)

# 从顶部开始顺时针绘制条形图
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)   

# 自定义y轴缩放
max_value = 50
r_offset = -10
r2 = max_value - r_offset
alpha = r2 - r_offset
v_offset = r_offset**2 / alpha
forward = lambda value: ((value + v_offset) * alpha)**0.5 + r_offset
reverse = lambda radius: (radius - r_offset) ** 2 / alpha - v_offset
ax.set_rlim(0, max_value)
ax.set_rorigin(r_offset)
ax.set_yscale('function', functions=(
    lambda value: np.where(value >= 0, forward(value), value),
    lambda radius: np.where(radius > 0, reverse(radius), radius)))

# 自定义轴标签
ax.set_rlabel_position(0)
ax.set_yticks([10,20,30,40])
ax.set_yticklabels([10,20,30,40],fontsize=9, color='white',alpha=0.35)

# 自定义网格线
ax.set_thetagrids(angles=[])
ax.grid(visible=True, axis='y', zorder=2, color='white',
        linewidth=0.75, alpha=0.2)

# 移除边框
ax.spines[:].set_visible(False)

# 自定义图例
# 添加图例轴
lgd = fig.add_axes([0.75,0.71, 0.15, 0.25]) 

# 图例元素
kw = dict(marker='o', color=chart_colors['bg'], markersize=8, alpha=1, 
          markeredgecolor='None', linewidth=0)
legend_elements =[Line2D([0],[0], 
                          markerfacecolor=chart_colors['PADME'],
                          label='Padme', 
                          **kw), 
                  Line2D([0], [0], 
                         markerfacecolor=chart_colors['QUI-GON'],
                         label='Qui-Gon', 
                         **kw), 
                  Line2D([0], [0], 
                         markerfacecolor=chart_colors['R2D2'], 
                         label='R2D2', 
                         **kw), 
                  Line2D([0], [0], 
                         markerfacecolor=chart_colors['OBI-WAN'], 
                         label='Obi-Wan', 
                         **kw), 
                  Line2D([0], [0], 
                         markerfacecolor=chart_colors['other'], 
                         label='Other', 
                         **kw)] 

# 移除图例边框
L = lgd.legend(frameon=False, handles=legend_elements, loc='center', 
               ncol=1, handletextpad=0.2, labelspacing=1)
plt.setp(L.texts, va='baseline', color='white', size=12, 
         fontfamily='Ubuntu')    
lgd.axis('off')

# 注释
# 新增一个内圆:用于指示绘制方向
circ = fig.add_axes([0.453, 0.435, 0.12, 0.12],polar=True) 
line_angular_pos = df['angular_pos'][1:-5]
line_r = [5] * len(line_angular_pos)

# 绘制开始和结束的标记
circ.plot(line_angular_pos, line_r, zorder=5, color='white', 
          linewidth=0.75, alpha=0.4)
circ.plot(line_angular_pos.to_list()[0], line_r[0], zorder=5, color='white', 
          linewidth=0,marker='o', markersize=3,alpha=0.4)
circ.plot(line_angular_pos.to_list()[-1], line_r[-1], zorder=5, color='white', 
          linewidth=0,marker='>', markersize=3,alpha=0.4)

# 自定义轴:从顶部开始顺时针绘制条形图
circ.set_theta_zero_location('N')
circ.set_theta_direction(-1)  
circ.axis('off')

# 文本注释
ax.annotate('1 line', xy=(0.1, 48), xycoords='data', xytext=(40, 20), 
            textcoords='offset points', 
            fontsize=10, fontfamily='Ubuntu',
            ha='left', va='baseline', 
            annotation_clip=False, 
            color='#ababab',
            arrowprops=dict(arrowstyle='->',edgecolor='#ababab', 
                            connectionstyle='arc3,rad=.5', alpha=0.75))
ax.annotate('Words\nper line', xy=(-0.05, 22), xycoords='data', xytext=(0, 0), 
            textcoords='offset points', 
            fontsize=10, fontfamily='Ubuntu',
            ha='right', va='baseline', 
            annotation_clip=False, 
            color='#ababab')
ax.annotate('', xy=(-0.02, 38), xycoords='data', xytext=(0, -105), 
            textcoords='offset points', 
            fontsize=10, fontfamily='Ubuntu',
            ha='right', va='baseline', 
            annotation_clip=False, 
            color='#ababab',
            arrowprops=dict(arrowstyle='<->',edgecolor='#ababab', linewidth=0.75,
                            connectionstyle='arc3,rad=0', alpha=0.75 ))
lgd.annotate('Talking to', xy=(0.35, 0.78), xycoords='data', xytext=(-18, 14), 
             textcoords='offset points', 
            fontsize=10, fontfamily='Ubuntu',
            ha='right', va='center', 
            annotation_clip=False, 
            color='#ababab',
            arrowprops=dict(arrowstyle='->',edgecolor='#ababab', 
                            connectionstyle='arc3,rad=-.5', alpha=0.75))

# 标题+制作信息
plt.figtext(0.5,1.03, 'Star Wars Episode I', 
            fontfamily='Mandalore', 
            fontsize=55, color='white', ha='center')
plt.figtext(0.5,0.98, 'Each line of Anakin', 
            fontfamily='Ubuntu',
            fontsize=24, color='white', ha='center')
plt.figtext(0.5,0.1, 'Data: jcwieme/data-scripts-star-wars  |  Design: Lisa Hornung', 
            fontfamily='Ubuntu',
            fontsize=8, color='white', ha='center', alpha=0.75)


plt.show()
output_12_0
output_12_0

output_12_0

参考:Customized circular bar plot in matplotlib[1]

共勉~

参考资料

[1]

Customized circular bar plot in matplotlib: https://python-graph-gallery.com/532-customizing-circular-barplot-in-matplotlib/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HsuHeinrich 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 利用径向柱图探索星球大战数据
    • 数据探索
    • 基本径向柱图
    • 自定义布局
    • 最终的图
      • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档