Plotly: как сделать линейный график из кадра данных pandas с длинным или широким форматом? - PullRequest
2 голосов
/ 26 мая 2020

(Это сообщение с самоответом, чтобы помочь другим сократить свои ответы на подробные вопросы, не объясняя, как plotly лучше всего обрабатывает данные длинного и широкого формата)


Я хотел бы построить графическую фигуру на основе кадра данных pandas в как можно меньшем количестве строк. Я знаю, что вы можете сделать это, используя plotly. express, но это не подходит для того, что я бы назвал стандартным pandas dataframe; индекс, описывающий порядок строк и имена столбцов, описывающие имена значений в кадре данных:

Пример кадра данных:

    a           b           c
0   100.000000  100.000000  100.000000
1   98.493705   99.421400   101.651437
2   96.067026   98.992487   102.917373
3   95.200286   98.313601   102.822664
4   96.691675   97.674699   102.378682

Попытка:

fig=px.line(x=df.index, y = df.columns)

Это вызывает ошибку:

ValueError: все аргументы должны иметь одинаковую длину. Длина аргумента y равна 3, тогда как длина предыдущих аргументов ['x'] составляет 100`

Ответы [ 2 ]

4 голосов
/ 26 мая 2020

Здесь вы пытались использовать pandas фрейм данных широкого формата в качестве источника для px.line. И plotly.express предназначен для использования с фреймами данных длинного формата , часто называемого tidy data , пожалуйста, взгляните на это. Нет один объясняет это лучше, чем Уикхэм). Многим, особенно тем, кто пострадал в результате многолетней борьбы с Excel, часто легче организовать данные в широком формате. Так в чем разница?

Широкий формат:

  • данные представлены с каждой переменной данных в отдельном столбце
  • каждый столбец имеет только один тип данных
  • пропущенные значения часто представлены как np.nan
  • лучше всего работает с plotly.graphobjects (go)
  • линии часто добавляются к фигуре с помощью fid.add_traces()
  • цветов обычно назначаются каждой кривой

Пример:

            a          b           c
0   -1.085631    0.997345   0.282978
1   -2.591925    0.418745   1.934415
2   -5.018605   -0.010167   3.200351
3   -5.885345   -0.689054   3.105642
4   -4.393955   -1.327956   2.661660
5   -4.828307    0.877975   4.848446
6   -3.824253    1.264161   5.585815
7   -2.333521    0.328327   6.761644
8   -3.587401   -0.309424   7.668749
9   -5.016082   -0.449493   6.806994

Длинный формат:

  • данные представлены в одном столбце, содержащем все значения, а в другом столбце перечислен контекст значения
  • отсутствующие значения просто не включаются в набор данных.
  • лучше всего работает с plotly. express (px)
  • цвета задаются цветовым циклом по умолчанию и присваиваются каждой уникальной переменной

Пример:

    id  variable    value
0   0   a        -1.085631
1   1   a        -2.591925
2   2   a        -5.018605
3   3   a        -5.885345
4   4   a        -4.393955
... ... ... ...
295 95  c        -4.259035
296 96  c        -5.333802
297 97  c        -6.211415
298 98  c        -4.335615
299 99  c        -3.515854

Как go от длинного к широкому ?

df = pd.melt(df, id_vars='id', value_vars=df.columns[:-1])

Эти два фрагмента должны быть low создаст тот же самый график:

enter image description here

Как использовать px для построения длинных данных?

fig = px.line(df, x='id', y='value', color='variable')

Как использовать go для построения широких данных?

colors = px.colors.qualitative.Plotly
fig = go.Figure()
fig.add_traces(go.Scatter(x=df['id'], y = df['a'], mode = 'lines', line=dict(color=colors[0])))
fig.add_traces(go.Scatter(x=df['id'], y = df['b'], mode = 'lines', line=dict(color=colors[1])))
fig.add_traces(go.Scatter(x=df['id'], y = df['c'], mode = 'lines', line=dict(color=colors[2])))
fig.show()

Судя по всему, go более сложен и предлагает, возможно, большую гибкость? Ну да. И нет. Вы можете легко построить фигуру, используя px, и добавить любой go объект, какой захотите!

Complete go snippet:

import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

# dataframe of a wide format
np.random.seed(123)
X = np.random.randn(100,3)  
df=pd.DataFrame(X, columns=['a','b','c'])
df=df.cumsum()
df['id']=df.index

# plotly.graph_objects
colors = px.colors.qualitative.Plotly
fig = go.Figure()
fig.add_traces(go.Scatter(x=df['id'], y = df['a'], mode = 'lines', line=dict(color=colors[0])))
fig.add_traces(go.Scatter(x=df['id'], y = df['b'], mode = 'lines', line=dict(color=colors[1])))
fig.add_traces(go.Scatter(x=df['id'], y = df['c'], mode = 'lines', line=dict(color=colors[2])))
fig.show()

Полный фрагмент в пикселях:

import numpy as np
import pandas as pd
import plotly.express as px
from plotly.offline import iplot

# dataframe of a wide format
np.random.seed(123)
X = np.random.randn(100,3)  
df=pd.DataFrame(X, columns=['a','b','c'])
df=df.cumsum()
df['id']=df.index

# dataframe of a long format
df = pd.melt(df, id_vars='id', value_vars=df.columns[:-1])

# plotly express
fig = px.line(df, x='id', y='value', color='variable')
fig.show()
2 голосов
/ 26 мая 2020

Я собираюсь добавить это в качестве ответа, чтобы оно было доказано. Прежде всего, спасибо @vestland за это. Это вопрос, который повторяется снова и снова, поэтому хорошо, если он решен, и было бы проще пометить повторяющийся вопрос.

Plotly Express теперь принимает данные в широкой и смешанной форме как вы можете проверить в этом сообщении .

...