Гистограмма: Как я могу получить тот же формат даты на оси x, что и в диаграмме временных рядов? [Дубликат]

Вопрос был:

Как вернуть ответ от асинхронного вызова?

blockquote>

, который может быть интерпретирован как:

Как сделать синхронный асинхронный код синхронным?

blockquote>

Решение будет состоять в том, чтобы избежать обратных вызовов и использовать комбинацию Promises и async / await.

Я хотел бы привести пример для запроса Ajax.

(Хотя он может быть записан в Javascript, я предпочитаю писать его на Python и компилировать его в Javascript, используя Transcrypt . Это будет достаточно ясно.)

Позволяет сначала включить использование JQuery, чтобы $ был доступен как S:

__pragma__ ('alias', 'S', '$')

Определить функцию, которая возвращает Promise, в этом случае вызов Ajax:

def read(url: str):
    deferred = S.Deferred()
    S.ajax({'type': "POST", 'url': url, 'data': { },
        'success': lambda d: deferred.resolve(d),
        'error': lambda e: deferred.reject(e)
    })
    return deferred.promise()

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

async def readALot():
    try:
        result1 = await read("url_1")
        result2 = await read("url_2")
    except Exception:
        console.warn("Reading a lot failed")

30
задан Ted Petrou 8 May 2015 в 21:50
поделиться

2 ответа

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

ax.xaxis.set_major_formatter(formatter)

pandas.tseries.converter.TimeSeries_DateFormatter, который Pandas использует для форматирования дат в «хорошем» сюжете, хорошо работает с графическими строками когда значения x являются датами. Однако с графиком bar значения x (по крайней мере, полученные TimeSeries_DateFormatter.__call__) являются целыми числами , начиная с нуля . Если вы попытаетесь использовать TimeSeries_DateFormatter со строкой, все метки, таким образом, начнутся в эпоху, 1970-1-1 UTC, так как это дата, которая соответствует нулю. Таким образом, форматтер, используемый для линейных графиков, к сожалению, бесполезен для барных графиков (по крайней мере, насколько я вижу).

Самый простой способ, который я вижу для создания желаемого форматирования, - это создать и установить ярлыки явно:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.ticker as ticker

start = pd.to_datetime("5-1-2012")
idx = pd.date_range(start, periods= 365)
df = pd.DataFrame({'A':np.random.random(365), 'B':np.random.random(365)})
df.index = idx
df_ts = df.resample('W', how= 'max')

ax = df_ts.plot(kind='bar', x=df_ts.index, stacked=True)

# Make most of the ticklabels empty so the labels don't get too crowded
ticklabels = ['']*len(df_ts.index)
# Every 4th ticklable shows the month and day
ticklabels[::4] = [item.strftime('%b %d') for item in df_ts.index[::4]]
# Every 12th ticklabel includes the year
ticklabels[::12] = [item.strftime('%b %d\n%Y') for item in df_ts.index[::12]]
ax.xaxis.set_major_formatter(ticker.FixedFormatter(ticklabels))
plt.gcf().autofmt_xdate()

plt.show()

дает


Для тех, кто ищет простой пример штрихового графика с датами:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker

dates = pd.date_range('2012-1-1', '2017-1-1', freq='M')
df = pd.DataFrame({'A':np.random.random(len(dates)), 'Date':dates})
fig, ax = plt.subplots()
df.plot.bar(x='Date', y='A', ax=ax)
ticklabels = ['']*len(df)
skip = len(df)//12
ticklabels[::skip] = df['Date'].iloc[::skip].dt.strftime('%Y-%m-%d')
ax.xaxis.set_major_formatter(mticker.FixedFormatter(ticklabels))
fig.autofmt_xdate()

# fixes the tracker
# https://matplotlib.org/users/recipes.html
def fmt(x, pos=0, max_i=len(ticklabels)-1):
    i = int(x) 
    i = 0 if i < 0 else max_i if i > max_i else i
    return dates[i]
ax.fmt_xdata = fmt
plt.show()

31
ответ дан unutbu 28 August 2018 в 21:08
поделиться

Вот, возможно, более простой подход с использованием mdates, хотя вам нужно перебирать ваши столбцы, вызывая отображение бар из matplotlib. Вот пример, когда я рисую только один столбец и использую mdates для настраиваемых тиков и меток (EDIT). Добавлена ​​функция циклирования для построения всех столбцов):

import datetime
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

def format_x_date_month_day(ax):   
    # Standard date x-axis formatting block, labels each month and ticks each day
    days = mdates.DayLocator()
    months = mdates.MonthLocator()  # every month
    dayFmt = mdates.DateFormatter('%D')
    monthFmt = mdates.DateFormatter('%Y-%m')
    ax.figure.autofmt_xdate()
    ax.xaxis.set_major_locator(months) 
    ax.xaxis.set_major_formatter(monthFmt)
    ax.xaxis.set_minor_locator(days)

def df_stacked_bar_formattable(df, ax, **kwargs):
    P = []
    lastBar = None

    for col in df.columns:
        X = df.index
        Y = df[col]
        if lastBar is not None:
            P.append(ax.bar(X, Y, bottom=lastBar, **kwargs))
        else:
            P.append(ax.bar(X, Y, **kwargs))
        lastBar = Y
    plt.legend([p[0] for p in P], df.columns)

span_days = 90
start = pd.to_datetime("1-1-2012")
idx = pd.date_range(start, periods=span_days).tolist()
df=pd.DataFrame(index=idx, data={'A':np.random.random(span_days), 'B':np.random.random(span_days)})

plt.close('all')
fig, ax = plt.subplots(1)
df_stacked_bar_formattable(df, ax)
format_x_date_month_day(ax)
plt.show()

(Ссылка matplotlib.org , например, для создания стробированного графика штрихов.) Это дает нам

. Другой подход, который должен работать и быть намного проще, - использовать df.plot.bar(ax=ax, stacked=True), однако он не допускает форматирование оси даты с mdates и является предметом моего вопроса .

1
ответ дан eecharlie 28 August 2018 в 21:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: