Ответ 1
Не настоящий ответ, но обходной путь, предложенный Томом Аугспургером, заключается в том, что вы можете просто использовать тип графика рабочей линии и указать точки вместо строк:
df.plot(x='x', y='y', style=".")
У меня есть dataframe с двумя столбцами datetime.time's. Я хотел бы рассказать о них. Мне также хотелось бы, чтобы топоры отображали время, в идеале. Но
df.plot(kind='scatter', x='T1', y='T2')
сбрасывает кучу внутренних ошибок построения, заканчивающихся KeyError на 'T1'.
В качестве альтернативы я пытаюсь
plt.plot_date(x=df.loc[:,'T1'], y=df.loc[:,'T2'])
plt.show()
и я получаю "Исключение в обратном вызове Tkinter" с длинным обходом стека в
return _from_ordinalf(x, tz)
File "/usr/lib/python3/dist-packages/matplotlib/dates.py", line 224, in _from_ordinalf
microsecond, tzinfo=UTC).astimezone(tz)
TypeError: tzinfo argument must be None or of a tzinfo subclass, not type 'str'
Любые указатели?
Не настоящий ответ, но обходной путь, предложенный Томом Аугспургером, заключается в том, что вы можете просто использовать тип графика рабочей линии и указать точки вместо строк:
df.plot(x='x', y='y', style=".")
Не ответ, но я не могу отредактировать вопрос или поместить это в комментарий, я думаю.
Вот пример воспроизводимости:
from datetime import datetime
import pandas as pd
df = pd.DataFrame({'x': [datetime.now() for _ in range(10)], 'y': range(10)})
df.plot(x='x', y='y', kind='scatter')
Это дает KeyError: 'x'
.
Интересно, что вы получаете сюжет только с df.plot(x='x', y='y')
; он выбирает плохо для диапазона x по умолчанию, потому что время всего лишь наносекунд, что странно, но это отдельная проблема. Кажется, что если вы можете сделать линейный график, вы также сможете сделать диаграмму рассеяния.
pandas проблема github об этой проблеме, но по какой-то причине она была закрыта. Я собираюсь оставить там комментарий и посмотреть, можем ли мы снова начать этот разговор.
Есть ли какая-то умная работа для этого? Если да, то что?
Вот основная работа, чтобы вы начали.
import matplotlib, datetime
import matplotlib.pyplot as plt
def scatter_date(df, x, y, datetimeformat):
if not isinstance(y, list):
y = [y]
for yi in y:
plt.plot_date(df[x].apply(
lambda z: matplotlib.dates.date2num(
datetime.datetime.strptime(z, datetimeformat))), df[yi], label=yi)
plt.legend()
plt.xlabel(x)
# Example Usage
scatter_date(data, x='date', y=['col1', 'col2'], datetimeformat='%Y-%m-%d')
Это некрасиво, но в качестве быстрого взлома вы можете преобразовать DateTime в метку времени с помощью .timestamp()
перед загрузкой в Pandas, а рассеиватели будут работать нормально (хотя полностью непригодная ось x).
построение на Mike N отвечает... конвертируйте в unix-время, чтобы правильно разбросать, а затем преобразуйте метки оси из int64s в строки:
type(df.ts1[0])
pandas.tslib.Timestamp
df['t1'] = df.ts1.astype(np.int64)
df['t2'] = df.ts2.astype(np.int64)
fig, ax = plt.subplots(figsize=(10,6))
df.plot(x='t1', y='t2', kind='scatter', ax=ax)
ax.set_xticklabels([datetime.fromtimestamp(ts / 1e9).strftime('%H:%M:%S') for ts in ax.get_xticks()])
ax.set_yticklabels([datetime.fromtimestamp(ts / 1e9).strftime('%H:%M:%S') for ts in ax.get_yticks()])
plt.show()