Как установить правильные значения времени для оси (tsplot) x-axis [duplicate]

Я не могу ручаться за производительность, но вот трюк, вдохновленный ограничениями Microsoft Excel. У него есть некоторые хорошие функции

GOOD STUFF

  • Он должен принудительно вернуть только одну «максимальную запись», даже если есть галстук (иногда полезный)
  • Он не требует соединения

ПОДХОД

Это немного уродливо и требует, чтобы вы знали что-то о диапазоне допустимых значений rev . Предположим, что мы знаем, что столбец rev - это число от 0,00 до 999, включая десятичные числа, но что только две цифры справа от десятичной точки (например, 34.17 будет действительным значением) .

Суть заключается в том, что вы создаете единый синтетический столбец путем конкатенации / упаковки первичного поля сравнения вместе с данными, которые вы хотите. Таким образом, вы можете заставить агрегированную функцию SQL MAX () возвращать все данные (поскольку она была упакована в один столбец). Затем вам нужно распаковать данные.

Вот как это выглядит с помощью приведенного выше примера, написанного на SQL

SELECT id, 
       CAST(SUBSTRING(max(packed_col) FROM 2 FOR 6) AS float) as max_rev,
       SUBSTRING(max(packed_col) FROM 11) AS content_for_max_rev 
FROM  (SELECT id, 
       CAST(1000 + rev + .001 as CHAR) || '---' || CAST(content AS char) AS packed_col
       FROM yourtable
      ) 
GROUP BY id

Насыщение начинается с принудительного rev , чтобы быть числом известной длины символа, независимо от значения rev , так что, например,

  • 3.2 становится 1003.201
  • 57 становится 1057,001
  • 923.88 становится 1923.881

Если вы сделаете это правильно, сравнение строк двух чисел должно дать то же самое «max», что и числовое сравнение двух чисел, и легко конвертировать обратно в исходное число, используя функцию подстроки (которая доступна в той или иной форме практически везде).

11
задан sedavidw 6 July 2015 в 21:26
поделиться

3 ответа

Matplotlib представляет даты как числа с плавающей запятой (в днях), поэтому, если вы (или панды или морские) не говорите, что ваши значения представляют даты, они не будут отформатировать тики в качестве дат. Я не эксперт по морскому дну, но похоже, что он (или панды) преобразует объекты datetime в даты matplotlib, но затем не назначает правильные локаторы и форматирующие элементы для осей. Вот почему вы получаете эти странные числа , которые на самом деле являются только днями с 0001.01.01.

Таким образом, вам придется назначить локатор даты , который решает, где поставить тики, и форматировщик даты , который затем отформатирует строки для меток тика.

import datetime
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# build up the data
df = []
start_date = datetime.datetime(2015, 7, 1)
for i in range(10):
    for j in [1,2]:
        unit = 'Ones' if j == 1 else 'Twos'
        date = start_date + datetime.timedelta(days=i)

        # I believe it makes more sense to directly convert the datetime to a
        # "matplotlib"-date (float), instead of creating strings and then let
        # pandas parse the string again
        df.append({
                'Date': mdates.date2num(date),
                'Value': i * j,
                'Unit': unit
            })
df = pd.DataFrame(df)

# build the figure
fig, ax = plt.subplots()
sns.tsplot(df, time='Date', value='Value', unit='Unit', ax=ax)

# assign locator and formatter for the xaxis ticks.
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y.%m.%d'))

# put the labels at 45deg since they tend to be too long
fig.autofmt_xdate()
plt.show()

Результат:

enter image description here [/g3]

11
ответ дан hitzg 28 August 2018 в 20:30
поделиться

Для меня ответ @ hitzg приводит к тому, что «OverflowError: signed integer больше максимального» в глубинах DateFormatter.

. Посмотрев на мою фреймворк, мои индексы имеют datetime64, а не datetime. Панда преобразует их красиво. Для меня отлично работает:

import matplotlib as mpl

def myFormatter(x, pos):
    return pd.to_datetime(x)

[ . . . ]

ax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(myFormatter))
11
ответ дан foobarbecue 28 August 2018 в 20:30
поделиться

Вот потенциально неэлегантное решение, но это единственное, что у меня есть ... Надеюсь, это поможет!

    g = sns.pointplot(x, y, data=df, ci=False);

    unique_dates = sorted(list(df['Date'].drop_duplicates()))
    date_ticks = range(0, len(unique_dates), 5)

    g.set_xticks(date_ticks);
    g.set_xticklabels([unique_dates[i].strftime('%d %b') for i in date_ticks], rotation='vertical');
    g.set_xlabel('Date');

Дайте мне знать, если вы видите какие-либо проблемы!

0
ответ дан ltjds 28 August 2018 в 20:30
поделиться
Другие вопросы по тегам:

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