Как сделать смешанные статистические сюжеты с использованием сюжета в Python? - PullRequest
3 голосов
/ 08 ноября 2019

У меня есть некоторый набор данных в CSV-файлах (всего 3), и я должен представлять его по-разному. Это обязательно линейные графики, коробочные графики и гистограмма с kde (оценка плотности ядра).

Я знаю, как составлять их по отдельности, но чтобы сделать их более удобными, мне нужно объединить их в один вывод. После ознакомления со ссылкой я написал некоторый код, но он не запустился.

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import numpy as np

y1 = np.random.randn(200) - 1
y2 = np.random.randn(200)
y3 = np.random.randn(200) + 1
x = np.linspace(0, 1, 200)

fig = make_subplots(
    rows=3, cols=2,
    column_widths=[0.6, 0.4],
    row_heights=[0.3, 0.6],
    specs=[[{"type": "scatter"}, {"type": "box"}],
           [{"type": "scatter"}, {"type": "dist", "rowspan": 2}]
           [{"type": "scatter"},            None           ]])

fig.add_trace(
    go.Scatter(x = x, 
                y = y1,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='rgb(0, 0, 0)',
                width=1),
                showlegend=False,
                )
    row=1, col=1
)

fig.add_trace(
    go.Scatter(x = x, 
                y = y2,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='rgb(246, 52, 16)',
                width=1),
                showlegend=False,
                )
    row=2, col=1
)

fig.add_trace(
    go.Scatter(x = x, 
                y = y3,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='rgb(16, 154, 246)',
                width=1),
                showlegend=False,
                )
    row=3, col=1
)

fig.add_trace(
    go.Box(x=y1)
    go.Box(x=y2)
    go.Box(x=y3)
    row=1, col=2
)

hist_data = [y1, y2, y3]

fig.add_trace(
    ff.create_distplot(hist_data,
                         bin_size=.02, show_rug=False)

    row=2, col=2
)

fig.show()

Что не так с кодом выше или как я могу построить эти диаграммы с уникальным выводом?

PS Для лучшей визуализации линейные графики должны быть разделены.

Ответы [ 3 ]

1 голос
/ 11 ноября 2019

Вторая попытка после диалога в комментариях.

Следующее - лучшее, что я мог сделать. Это подход, при котором я создаю ff.create_distplot как в вашем примере кода, а затем «краду» данные и использую их в комбинации объектов go.Histogram, go.Scatter и go.Box для эмуляции графиков распределения и коврика избывший.

Участок:

enter image description here

Код:

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import numpy as np
import pandas as pd

# data
y1 = np.random.randn(200) - 1
y2 = np.random.randn(200)
y3 = np.random.randn(200) + 1
x = np.linspace(0, 1, 200)

# subplot setupt
fig = make_subplots(
    rows=3, cols=2
)

# Line [1,1]
fig.add_trace(go.Scatter(x = x, 
                        y = y1,
                        hoverinfo = 'x+y',
                        mode='lines',
                        line=dict(color='rgb(0, 0, 0)',width=1),
                        showlegend=False,
                        name = 'series 1'
                        ),
             row=1, col=1
)

# Line [2,1]
fig.add_trace(
    go.Scatter(x = x, 
                y = y2,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='rgb(246, 52, 16)',
                width=1),
                showlegend=False,
                ),
    row=2, col=1
)

# Line [2,1]
fig.add_trace(
    go.Scatter(x = x, 
                y = y3,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='rgb(16, 154, 246)',
                width=1),
                showlegend=False,
                ),
    row=3, col=1
)

fig.update_layout(showlegend=False)

# box plots [1,1]
fig.add_trace(go.Box(x=y3, marker_color='rgb(16, 154, 246)'),
    row=1, col=2
)

fig.add_trace(go.Box(x=y2, marker_color='rgb(246, 52, 16)'),
    row=1, col=2
)

fig.add_trace(go.Box(x=y1, marker_color='rgb(0, 0, 0)'),
    row=1, col=2
)

# density plots [2,2]
hist_data = [y1, y2, y3]
group_labels = ['Group 1', 'Group 2', 'Group 3']

# fig 2 is only there to produce the numbers to fill
# in later go.Histogram and go.Scatter
fig2 = ff.create_distplot(hist_data, group_labels)

fig.add_trace(go.Histogram(fig2['data'][0],
                           marker_color='rgb(0, 0, 0)',
                           showlegend=False
                          ), row=2, col=2)

fig.add_trace(go.Histogram(fig2['data'][1],
                           marker_color='rgb(246, 52, 16)'
                          ), row=2, col=2)

fig.add_trace(go.Histogram(fig2['data'][2],
                           marker_color='rgb(16, 154, 246)'
                          ), row=2, col=2)

fig.add_trace(go.Scatter(fig2['data'][3],
                         line=dict(color='rgb(0, 0, 0)', width=0.5)
                        ), row=2, col=2)

fig.add_trace(go.Scatter(fig2['data'][4],
                         line=dict(color='rgb(246, 52, 16)', width=0.5)
                        ), row=2, col=2)

fig.add_trace(go.Scatter(fig2['data'][5],
                         line=dict(color='rgb(16, 154, 246)', width=0.5)
                        ), row=2, col=2)

# sorry excuse for a rugplot [3,2]
df = pd.DataFrame({'y1':y1, 'y2':y2, 'y3':y3}, index = x)
df['rug1'] = 1.2
df['rug2'] = 1.1
df['rug3'] = 1
df.tail()
#f=go.Figure()
fig.add_trace(go.Scatter(x=df['y1'], y = df['rug1'],
                       mode = 'markers',
                       marker=dict(color = 'rgb(0, 0, 0)', symbol='line-ns-open')
                        ), row=3, col=2)

fig.add_trace(go.Scatter(x=df['y2'], y = df['rug2'],
                       mode = 'markers',
                       marker=dict(color = 'rgb(246, 52, 16)', symbol='line-ns-open')
                        ), row=3, col=2)

fig.add_trace(go.Scatter(x=df['y3'], y = df['rug3'],
                       mode = 'markers',
                       marker=dict(color = 'rgb(16, 154, 246)', symbol='line-ns-open')
                        ), row=3, col=2)

# some manual adjustments on the rugplot
fig.update_yaxes(range=[0.9,1.3], tickfont=dict(color='rgba(0,0,0,0)', size=14), row=3, col=2)
fig.update_layout(title ='Mixed statistical subplots', showlegend=False)

fig.show()

РЕДАКТИРОВАТЬ - Первая попытка:

Начнем с этого:

Что не так с кодом выше [...]?

Это зависит от того, что вы собираетесь здесь делать. Но прежде всего вы пропускаете много запятых в таких местах:

fig.add_trace(
    go.Scatter(x = x, 
                y = y3,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='rgb(16, 154, 246)',
                width=1),
                showlegend=False,
                ) # <==================== insert missing comma !!!
    row=3, col=1
)

Следующий фрагмент оставляет меня озадаченным:

fig.add_trace(
    go.Box(x=y1)
    go.Box(x=y2)
    go.Box(x=y3)
    row=1, col=2
)

Там как минимум one здесь запятая отсутствует, но мне все еще не очень понятно, что вы пытаетесь сделать. Мне кажется, что вы хотели бы поместить все поля в один и тот же график и нанести его на верхнюю часть второго столбца, но я не думаю, что это имело бы смысл с остальной частью установки. И впереди еще много беспокойств, потому что не похоже, что вы вообще сможете включить ваш ff.create_distplot() в свои настройки.

Лучшее, что я могу сделать для вас вв настоящее время для каждой серии устанавливаются графики с go.Scatter() в первом столбце и соответствующим go.Box() в правом столбце, например:

Сюжет 1:

enter image description here

Возможно, это не 100% то, что вы ищете, но, по крайней мере, я думаю, что имеет смысл посмотреть на ваши данные таким образом.

Код 1:

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import numpy as np

# data
y1 = np.random.randn(200) - 1
y2 = np.random.randn(200)
y3 = np.random.randn(200) + 1
x = np.linspace(0, 1, 200)

# subplot setupt
fig = make_subplots(
    rows=3, cols=2
)

# raw data with go.Scatter
fig.add_trace(go.Scatter(x = x, 
                        y = y1,
                        hoverinfo = 'x+y',
                        mode='lines',
                        line=dict(color='rgb(0, 0, 0)',width=1),
                        showlegend=False,
                        ),
             row=1, col=1
)

fig.add_trace(
    go.Scatter(x = x, 
                y = y2,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='rgb(246, 52, 16)',
                width=1),
                showlegend=False,
                ),
    row=2, col=1
)

fig.add_trace(
    go.Scatter(x = x, 
                y = y3,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='rgb(16, 154, 246)',
                width=1),
                showlegend=False,
                ),
    row=3, col=1
)

# box plots
fig.add_trace(go.Box(x=y1),
    row=1, col=2
)

fig.add_trace(go.Box(x=y1),
    row=2, col=2
)

fig.add_trace(go.Box(x=y1),
    row=3, col=2
)

fig.show()

И затем вы можете показать распределение всех серий вместе следующим образом:

График 2:

enter image description here

Код 2:

hist_data = [y1, y2, y3]
group_labels = ['Group 1', 'Group 2', 'Group 3']
fig2 = ff.create_distplot(hist_data, group_labels)
fig2.show()
1 голос
/ 13 ноября 2019

Я отправил этот же вопрос на сюжетный форум, и пользователь empet ответил изящно.

Как я и подозревал, make_subplots () не может обработатьОбъект рисунка, путь состоит в том, чтобы «добавлять данные рисунка как одну трассу за раз».

Сюжет: mixed-statistical-subplots Код:

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import numpy as np

y1 = np.random.randn(200) - 1
y2 = np.random.randn(200)
y3 = np.random.randn(200) + 1
x = np.linspace(0, 1, 200)

colors = ['#3f3f3f', '#00bfff', '#ff7f00']

fig = make_subplots(
    rows=3, cols=2,
    column_widths=[0.55, 0.45],
    row_heights=[1., 1., 1.],
    specs=[[{"type": "scatter"}, {"type": "xy"}],
           [{"type": "scatter"}, {"type": "xy", "rowspan": 2}],
           [{"type": "scatter"},            None           ]])

fig.add_trace(
    go.Scatter(x = x, 
                y = y1,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='#3f3f3f',
                width=1),
                showlegend=False,
                ),
    row=1, col=1
)

fig.add_trace(
    go.Scatter(x = x, 
                y = y2,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='#00bfff',
                width=1),
                showlegend=False,
                ),
    row=2, col=1
)

fig.add_trace(
    go.Scatter(x = x, 
                y = y3,
                hoverinfo = 'x+y',
                mode='lines',
                line=dict(color='#ff7f00',
                width=1),
                showlegend=False,
                ),
    row=3, col=1
)

boxfig= go.Figure(data=[go.Box(x=y1, showlegend=False, notched=True, marker_color="#3f3f3f", name='3'),
                        go.Box(x=y2, showlegend=False, notched=True, marker_color="#00bfff", name='2'),
                        go.Box(x=y3, showlegend=False, notched=True, marker_color="#ff7f00", name='1')])

for k in range(len(boxfig.data)):
     fig.add_trace(boxfig.data[k], row=1, col=2)

group_labels = ['Group 1', 'Group 2', 'Group 3']
hist_data = [y1, y2, y3]

distplfig = ff.create_distplot(hist_data, group_labels, colors=colors,
                         bin_size=.2, show_rug=False)

for k in range(len(distplfig.data)):
    fig.add_trace(distplfig.data[k],
    row=2, col=2
)
fig.update_layout(barmode='overlay')
fig.show()
0 голосов
/ 09 ноября 2019

Если вы хотите использовать matplotlib для объединения всех графиков в одном и том же выводе, вы можете использовать вспомогательные сюжеты, я не знаю, является ли это тем, что вы хотите.

import matplotlib.pyplot as plt
import numpy as np

y1 = np.random.randn(200) - 1
y2 = np.random.randn(200)
y3 = np.random.randn(200) + 1
x = np.linspace(0, 1, 200)

def scatter_plot(ax,x,y):
    ax.scatter(x,y)
    ax.locator_params(nbins=3)
    ax.set_xlabel('x-label')
    ax.set_ylabel('y-label')
    ax.set_title('Title')

def box_plot(ax,y):
    ax.boxplot(y)
    ax.locator_params(nbins=3)
    ax.set_xlabel('x-label')
    ax.set_ylabel('y-label')
    ax.set_title('Title')

def hist_plot(ax,y):
    ax.hist(y)
    ax.locator_params(nbins=3)
    ax.set_xlabel('x-label')
    ax.set_ylabel('y-label')
    ax.set_title('Title')

fig, ((ax1, ax2), (ax3, ax4), (ax5,ax6)) = plt.subplots(nrows=3, ncols=2)
scatter_plot(ax1,x,y1)
scatter_plot(ax2,x,y2)
scatter_plot(ax3,x,y3)
hist_plot(ax4,y1)
plt.tight_layout()
plt.show()

Сюжет:

enter image description here

...