如何更改Plotly子图的大小和间距?

0 投票
1 回答
46 浏览
提问于 2025-04-12 15:57

如何调整行之间的间距(比如增加前两行和最后两行之间的空间)以及图表的大小(比如让饼图变大)呢?

在我的例子中,我想用 plotly 的 FigureWidgetmake_subplots 来可视化来自Telco 客户流失数据集下载 176kB)的多个数据列。enter image description here

这段代码会循环遍历8列数据,为每一列添加一个饼图和一个条形图。

import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# Read data
df = pd.read_csv("./WA_Fn-UseC_-Telco-Customer-Churn.csv")
df['SeniorCitizen'] = df['SeniorCitizen'].map({0: 'No', 1: 'Yes'})

# Define subplot titles and data columns
data_cols = ['PhoneService' ,'MultipleLines' ,'InternetService' ,'OnlineBackup' ,'DeviceProtection' ,'TechSupport' ,'StreamingTV' ,'StreamingMovies']
titles = ['Phone Service' ,'Multiple Lines' ,'Internet Service' ,'Online Backup' ,'Device Protection' ,'Tech Support' ,'Streaming TV' ,'Streaming Movies']

fig = go.FigureWidget(make_subplots(rows=4, cols=4, specs=[
                                                        [{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}],
                                                        [{'type':'xy'}, {'type':'xy'}, {'type':'xy'}, {'type':'xy'}],
                                                        [{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}],
                                                        [{'type':'xy'}, {'type':'xy'}, {'type':'xy'}, {'type':'xy'}]]))

row, col = 1, 0
for i, (title, data_col) in enumerate(zip(titles, data_cols)):
    row, col = divmod(i, 4)
    row = row * 2
    
    # Get value counts for pie chart
    value_counts = df[data_col].value_counts()
    # Create pie chart trace and add to subplot
    pie_chart = go.Pie(labels=value_counts.index, values=value_counts.to_numpy(), name=title, title=title)
    fig.add_trace(pie_chart, row=row+1, col=col+1)
 
    # get churn rates
    churn_counts = df.groupby([data_col, 'Churn'])['Churn'].count().unstack()
    # Create stacked bar charts
    t1 = go.Bar(name='Churn (yes)', x=churn_counts['Yes'].index, y=churn_counts['Yes'])
    t2 = go.Bar(name='Churn (no)', x=churn_counts['No'].index, y=churn_counts['No'], marker_color='indianred')
    fig.add_trace(t1, row=row+2, col=col+1)
    fig.add_trace(t2, row=row+2, col=col+1)


fig.update_layout(title="Distribution of Customer Services", barmode='stack', showlegend=False)
fig.show()

编辑:即使将列数减少到两个,这个问题也没有解决。这是在一个大宽屏上的图表:enter image description here

import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# Read data
df = pd.read_csv("./WA_Fn-UseC_-Telco-Customer-Churn.csv")
df['SeniorCitizen'] = df['SeniorCitizen'].map({0: 'No', 1: 'Yes'})

# Define subplot titles and data columns
data_cols = ['PhoneService' ,'MultipleLines' ,'InternetService' ,'OnlineBackup' ,'DeviceProtection' ,'TechSupport' ,'StreamingTV' ,'StreamingMovies']
titles = ['Phone Service' ,'Multiple Lines' ,'Internet Service' ,'Online Backup' ,'Device Protection' ,'Tech Support' ,'Streaming TV' ,'Streaming Movies']

fig = go.FigureWidget(make_subplots(rows=8, cols=2, specs=[
                                                        [{'type':'domain'}, {'type':'domain'}],
                                                        [{'type':'xy'}, {'type':'xy'}],
                                                        [{'type':'domain'}, {'type':'domain'}],
                                                        [{'type':'xy'}, {'type':'xy'}],
                                                        [{'type':'domain'}, {'type':'domain'}],
                                                        [{'type':'xy'}, {'type':'xy'}],
                                                        [{'type':'domain'}, {'type':'domain'}],
                                                        [{'type':'xy'}, {'type':'xy'}]]))

row, col = 1, 0
for i, (title, data_col) in enumerate(zip(titles, data_cols)):
    row, col = divmod(i, 2)
    row = row * 2

    # Get value counts for pie chart
    value_counts = df[data_col].value_counts()
    # Create pie chart trace and add to subplot
    pie_chart = go.Pie(labels=value_counts.index, values=value_counts.to_numpy(), name=title, title=title)
    fig.add_trace(pie_chart, row=row+1, col=col+1)

    # get churn rates
    churn_counts = df.groupby([data_col, 'Churn'])['Churn'].count().unstack()
    # Create stacked bar charts
    t1 = go.Bar(name='Churn (yes)', x=churn_counts['Yes'].index, y=churn_counts['Yes'])
    t2 = go.Bar(name='Churn (no)', x=churn_counts['No'].index, y=churn_counts['No'], marker_color='indianred')
    fig.add_trace(t1, row=row+2, col=col+1)
    fig.add_trace(t2, row=row+2, col=col+1)


fig.update_layout(title="Distribution of Customer Services", barmode='stack', showlegend=False)
fig.show()

1 个回答

0

你可以通过 vertical_spacinghorizontal_spacing 这两个参数来调整行和列之间的间距。它们的值可以是0到 1/(size -1) 之间的小数。找到适合你的最佳值可能需要一些尝试。为了让图表在整个图形中占据更大的空间,你可以在 fig.update_layout 的调用中更新 margin 参数。四个边的设置用一个字典来表示,字典的键分别是: t(上)、b(下)、l(左)和 r(右)。

下面的代码是你原始代码的一个修改版,使用了这些参数。

import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# Read data
df = pd.read_csv("C:/Users/joost/Downloads/WA_Fn-UseC_-Telco-Customer-Churn.csv")
df['SeniorCitizen'] = df['SeniorCitizen'].map({0: 'No', 1: 'Yes'})

# Define subplot titles and data columns
data_cols = ['PhoneService' ,'MultipleLines' ,'InternetService' ,'OnlineBackup' ,'DeviceProtection' ,'TechSupport' ,'StreamingTV' ,'StreamingMovies']
titles = ['Phone Service' ,'Multiple Lines' ,'Internet Service' ,'Online Backup' ,'Device Protection' ,'Tech Support' ,'Streaming TV' ,'Streaming Movies']

hor_space = 0.02
ver_space = 0.02

fig = go.FigureWidget(make_subplots(rows=4,
                                    cols=4,
                                    specs=[[{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}],
                                           [{'type':'xy'}, {'type':'xy'}, {'type':'xy'}, {'type':'xy'}],
                                           [{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}],
                                           [{'type':'xy'}, {'type':'xy'}, {'type':'xy'}, {'type':'xy'}]
                                           ],
                                    horizontal_spacing=hor_space, # in range 0 to 1/(cols-1)
                                    vertical_spacing=ver_space # in range 0 to 1/(rows-1)
                                    )
                      )

row, col = 1, 0
for i, (title, data_col) in enumerate(zip(titles, data_cols)):
    row, col = divmod(i, 4)
    row = row * 2
    
    # Get value counts for pie chart
    value_counts = df[data_col].value_counts()
    # Create pie chart trace and add to subplot
    pie_chart = go.Pie(labels=value_counts.index, values=value_counts.to_numpy(), name=title, title=title)
    fig.add_trace(pie_chart, row=row+1, col=col+1)
 
    # get churn rates
    churn_counts = df.groupby([data_col, 'Churn'])['Churn'].count().unstack()
    # Create stacked bar charts
    t1 = go.Bar(name='Churn (yes)', x=churn_counts['Yes'].index, y=churn_counts['Yes'])
    t2 = go.Bar(name='Churn (no)', x=churn_counts['No'].index, y=churn_counts['No'], marker_color='indianred')
    fig.add_trace(t1, row=row+2, col=col+1)
    fig.add_trace(t2, row=row+2, col=col+1)


fig.update_layout(title="Distribution of Customer Services",
                  barmode='stack',
                  showlegend=False,
                   margin={"l":25,
                           "r":25,
                           "t":25,
                           "b":25}
                  )
fig.show()

以下是一些来自plotly文档的背景信息:

撰写回答