Plotly: Как изменить формат значений для оси x? - PullRequest
1 голос
/ 20 января 2020

Мне нужно создать график из данных с python.

Я черпал вдохновение из различных веб-сайтов и создал этот скрипт:

import plotly.express as px
import plotly.graph_objs as go
import statsmodels.api as sm

value = [1, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8]
date = [ 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020]

fig = px.scatter(x=date, y=value )
fig.add_trace(go.Scatter(x=date, y=value, mode='lines',name='MB Used' ))

trend = sm.OLS(value,sm.add_constant(date)).fit().fittedvalues

fig.add_traces(go.Scatter(x=date, y=trend,mode = 'lines', name='trendline'))
fig

Этот скрипт позволяет сгенерировать этот график: enter image description here

Для оси X я хотел бы отобразить значение, подобное этому 2020-01-01-06:00, но когда я изменяю свой список следующим образом:

date = [ 2020-01-01-06:00, 2020-01-01-12:00, 2020-01-01-18:00, 2020-01-02-06:00, 2020-01-02-12:00, 2020-01-02-18:00, 2020-01-03-06:00, 2020-01-03-12:00, 2020-01-03-18:00, 2020-01-04-06:00, 2020-01-04-12:00 ]

Ошибка:

File "<ipython-input-13-4958920545c3>", line 6
    date = [ 2020-01-01-06:00, 2020-01-01-12:00, 2020-01-01-18:00, 2020-01-02-06:00, 2020-01-02-12:00, 2020-01-02-18:00, 2020-01-03-06:00, 2020-01-03-12:00, 2020-01-03-18:00, 2020-01-04-06:00, 2020-01-04-12:00 ]
                   ^
SyntaxError: invalid token

Если я попробую это:

date = [ '2020-01-01-06:00', '2020-01-01-12:00', '2020-01-01-18:00', '2020-01-02-06:00', '2020-01-02-12:00', '2020-01-02-18:00', '2020-01-03-06:00', '2020-01-03-12:00', '2020-01-03-18:00', '2020-01-04-06:00', '2020-01-04-12:00' ]

Ошибка:


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-e06e438ca2eb> in <module>
     10 fig.add_trace(go.Scatter(x=date, y=value, mode='lines',name='MB Used' ))
     11 
---> 12 trend = sm.OLS(value,sm.add_constant(date)).fit().fittedvalues
     13 
     14 fig.add_traces(go.Scatter(x=date, y=trend,mode = 'lines', name='trendline'))

~/.local/lib/python3.6/site-packages/statsmodels/tools/tools.py in add_constant(data, prepend, has_constant)
    303         raise ValueError('Only implementd 2-dimensional arrays')
    304 
--> 305     is_nonzero_const = np.ptp(x, axis=0) == 0
    306     is_nonzero_const &= np.all(x != 0.0, axis=0)
    307     if is_nonzero_const.any():

<__array_function__ internals> in ptp(*args, **kwargs)

~/.local/lib/python3.6/site-packages/numpy/core/fromnumeric.py in ptp(a, axis, out, keepdims)
   2541         else:
   2542             return ptp(axis=axis, out=out, **kwargs)
-> 2543     return _methods._ptp(a, axis=axis, out=out, **kwargs)
   2544 
   2545 

~/.local/lib/python3.6/site-packages/numpy/core/_methods.py in _ptp(a, axis, out, keepdims)
    228 def _ptp(a, axis=None, out=None, keepdims=False):
    229     return um.subtract(
--> 230         umr_maximum(a, axis, None, out, keepdims),
    231         umr_minimum(a, axis, None, None, keepdims),
    232         out

TypeError: cannot perform reduce with flexible type

Пожалуйста, не могли бы вы показать мне как это изменить?

1 Ответ

1 голос
/ 21 января 2020

Ответ:

В следующем фрагменте кода я заменил ваши даты числами с плавающей запятой после этого подхода для сериализации отметок времени. Таким образом, вы можете использовать даты как в качестве входных данных для sm.OLS, так и в качестве одного из нескольких дополнительных шагов, чтобы ваши даты отображались на рисунке в нужном формате.

Сюжет:

enter image description here

Подробности:

Существует несколько причин, по которым вы не получаете желаемый результат в своем предоставленный фрагмент кода. Прежде всего, ни одна из попыток составления списков значений даты и времени не может быть легко распознана функциями, которые вы здесь применяете. В date = [ '2020-01-01-06:00', '2020-01-01-12:00',...] вы должны удалить один из дефисов, чтобы получить ['2020-01-01 06:00', '2020-01-01 12:00'...]. Но даже с более широко узнаваемым списком временных меток, насколько мне известно, statsmodels не примет те, что указаны в sm.OLS(). И, наконец, применение разумных меток к нестандартным отметкам оси X может стать (одной из очень немногих) реальными проблемами в сюжете.

Обратите внимание, что нерегулярные появления линий сетки отражают структуру ваших данных. Вы пропускаете наблюдения для отметок времени, которые заканчиваются на 00-00-00, чтобы представить 24-часовой цикл.

Код:

# imports
import plotly.express as px
import plotly.graph_objs as go
import statsmodels.api as sm
import datetime as dt

# data
value = [1, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8]
date = [ 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020]
date_h = ['2020-01-01 06:00', '2020-01-01 12:00', '2020-01-01 18:00', '2020-01-02 06:00', '2020-01-02 12:00', '2020-01-02 18:00', '2020-01-03 06:00', '2020-01-03 12:00', '2020-01-03 18:00', '2020-01-04 06:00', '2020-01-04 12:00' ]

# organize data in a pandas dataframe
df = pd.DataFrame({'value':value,
                   'date':date,
                    'date_h':pd.to_datetime(date_h)})

# function to serilaize irregular timestmps
def serial_date(date1):
    temp = dt.datetime(1899, 12, 30)    # Note, not 31st Dec but 30th!
    delta = date1 - temp
    return float(delta.days) + (float(delta.seconds) / 86400)

df['date_s'] = [serial_date(d) for d in df['date_h']]

# set up base figure
fig = px.scatter(x=df['date_s'], y=df['value'] )
fig.add_trace(go.Scatter(x=df['date_s'], y=df['value'], mode='lines',name='MB Used' ))

# setup for linear regression using sm.OLS
Y=df['value']
independent=['date_s']
X=df[independent]
X=sm.add_constant(X)

# estimate trend
trend = sm.OLS(Y,X).fit().fittedvalues

# add trendline to figure
fig.add_traces(go.Scatter(x=df['date_s'], y=trend,mode = 'lines', name='trendline'))

# specify tick0, tickvals and ticktext to achiece desired x-axis format
fig.update_layout(yaxis=dict(title=''),
                  xaxis=dict(title='',
                  tick0= df['date_s'].iloc[0],
                  tickvals= df['date_s'],
                  ticktext = df['date_h'])
                 )

fig.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...