基础数据
从Excel表格中读取数据
获取信息
#读取数据
links = pd.read_excel("...\\2020苹果现金流桑基图分析\\sankey_diagram_Apple_cashflow_2020_links.xlsx")
nodes = pd.read_excel("...\\sankey_diagram_Apple_cashflow_2020_nodes.xlsx")
# 将DataFrame转换为列表
nodes_list = [nodes.columns.values.tolist()] + nodes.values.tolist()
links_list = [links.columns.values.tolist()] + links.values.tolist()
# 检索表头并构建DataFrame
nodes_headers = nodes_list.pop(0)
links_headers = links_list.pop(0)
df_nodes = pd.DataFrame(nodes_list, columns = nodes_headers)
df_links = pd.DataFrame(links_list, columns = links_headers)
桑基图布局设置
layout_w_buttons = dict(
title = "Apple: Still squeezing juice from the iPhone<br><span style='font-size:0.6em;color:gray'>Link and reference <a href='https://www.reddit.com/r/dataisbeautiful/comments/albi5w/apples_latest_quarterly_income_statement/'>here.</a></span><span style='font-size:0.6em;color:gray'> Hover over diagram for more info on each flow.</span>",
font = dict(
size = 12
),
height=750,
width = 1200,
updatemenus= [
dict(
y=1,
buttons=[
dict(
label='Light',
method='relayout',
args=['paper_bgcolor', 'white']
),
dict(
label='Dark',
method='relayout',
args=['paper_bgcolor', 'black']
)
]
),
dict(
y=0.9,
buttons=[
dict(
label='Thin',
method='restyle',
args=['node.thickness', 7]
),
dict(
label='Medium',
method='restyle',
args=['node.thickness', 12]
),
dict(
label='Thick',
method='restyle',
args=['node.thickness', 20]
)
]
),
dict(
y=0.8,
buttons=[
dict(
label='Small gap',
method='restyle',
args=['node.pad', 20]
),
dict(
label='Large gap',
method='restyle',
args=['node.pad', 50]
)
]
),
dict(
y=0.7,
buttons=[
dict(
label='Snap',
method='restyle',
args=['arrangement', 'snap']
),
dict(
label='Perpendicular',
method='restyle',
args=['arrangement', 'perpendicular']
),
dict(
label='Freeform',
method='restyle',
args=['arrangement', 'freeform']
),
dict(
label='Fixed',
method='restyle',
args=['arrangement', 'fixed']
)
]
),
dict(
y=0.6,
buttons=[
dict(
label='Horizontal',
method='restyle',
args=['orientation', 'h']
),
dict(
label='Vertical',
method='restyle',
args=['orientation', 'v']
)
]
)
]
)
生成桑基图
# 假设data_trace和layout_w_buttons已经被正确定义
fig1 = go.Figure(data=[data_trace], layout=layout_w_buttons)
fig1.show()
# 直接使用文件名,因为脚本和目标文件将在同一个文件夹
fig1.write_html("Apple_Cashflow_2020.html")
完整代码
import pandas as pd
import plotly.graph_objects as go
#读取数据
links = pd.read_excel("...\\2020苹果现金流桑基图分析\\sankey_diagram_Apple_cashflow_2020_links.xlsx")
nodes = pd.read_excel("...\\sankey_diagram_Apple_cashflow_2020_nodes.xlsx")
# 将DataFrame转换为列表
nodes_list = [nodes.columns.values.tolist()] + nodes.values.tolist()
links_list = [links.columns.values.tolist()] + links.values.tolist()
# 检索表头并构建DataFrame
nodes_headers = nodes_list.pop(0)
links_headers = links_list.pop(0)
df_nodes = pd.DataFrame(nodes_list, columns = nodes_headers)
df_links = pd.DataFrame(links_list, columns = links_headers)
# 桑基图设置
data_trace = dict(
type='sankey', # Sankey Plot type
domain = dict(
x = [0,1],
y = [0,1]
),
orientation = "h", # 'h' = horizontal sankey plot, 'v' = vertical sankey plot
arrangement = "snap",
valueformat = "${,}", # Formats the value shown with a dollar sign out front (ex. value = 726 -> ouput = $726)
node = dict(
# pad = 30, # The bigger the number the more space between each line vertically
thickness = 10, # The width of the vertical lines/nodes
line = dict(
color = "black",
width = 0
),
label = df_nodes['label'].dropna(axis=0, how='any'), # Name of the node
x = df_nodes['x'].dropna(axis=0, how='any'), # Horizontal position of the node's center (from left to right)
y = df_nodes['y'].dropna(axis=0, how='any'), # Vertical position of the node's center (from top to bottom)
color = df_nodes['color'] # Color of the node
),
link = dict(
source = df_links['source'].dropna(axis=0, how='any'), # Link starting from this node
target = df_links['target'].dropna(axis=0, how='any'), # Link going to this node
value = df_links['value'].dropna(axis=0, how='any'),
color = df_links['color'].dropna(axis=0, how='any'),
)
)
layout_w_buttons = dict(
title = "Apple: Still squeezing juice from the iPhone<br><span style='font-size:0.6em;color:gray'>Link and reference <a href='https://www.reddit.com/r/dataisbeautiful/comments/albi5w/apples_latest_quarterly_income_statement/'>here.</a></span><span style='font-size:0.6em;color:gray'> Hover over diagram for more info on each flow.</span>",
font = dict(
size = 12
),
height=750,
width = 1200,
updatemenus= [
dict(
y=1,
buttons=[
dict(
label='Light',
method='relayout',
args=['paper_bgcolor', 'white']
),
dict(
label='Dark',
method='relayout',
args=['paper_bgcolor', 'black']
)
]
),
dict(
y=0.9,
buttons=[
dict(
label='Thin',
method='restyle',
args=['node.thickness', 7]
),
dict(
label='Medium',
method='restyle',
args=['node.thickness', 12]
),
dict(
label='Thick',
method='restyle',
args=['node.thickness', 20]
)
]
),
dict(
y=0.8,
buttons=[
dict(
label='Small gap',
method='restyle',
args=['node.pad', 20]
),
dict(
label='Large gap',
method='restyle',
args=['node.pad', 50]
)
]
),
dict(
y=0.7,
buttons=[
dict(
label='Snap',
method='restyle',
args=['arrangement', 'snap']
),
dict(
label='Perpendicular',
method='restyle',
args=['arrangement', 'perpendicular']
),
dict(
label='Freeform',
method='restyle',
args=['arrangement', 'freeform']
),
dict(
label='Fixed',
method='restyle',
args=['arrangement', 'fixed']
)
]
),
dict(
y=0.6,
buttons=[
dict(
label='Horizontal',
method='restyle',
args=['orientation', 'h']
),
dict(
label='Vertical',
method='restyle',
args=['orientation', 'v']
)
]
)
]
)
# 假设data_trace和layout_w_buttons已经被正确定义
fig1 = go.Figure(data=[data_trace], layout=layout_w_buttons)
fig1.show()
# 直接使用文件名,因为脚本和目标文件将在同一个文件夹
fig1.write_html("Apple_Cashflow_2020.html")
生成的桑基图如下: