带日期轴的 3D 散点图

问题描述 投票:0回答:1

我在绘制其中一个维度是日期的 3D 数据时遇到问题。我想知道如何解决它,因为对于这样一个常见的案例问题,我能想到的任何解决方案看起来都太复杂了。

我的解决方案是删除日期维度并将其替换为整数。我想将这个整数映射回日期。有什么想法最好的方法吗?

下面的代码可以工作,但如果需要,请将 N 调整为较小的数字。

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


N = 1000

bm = pd.DataFrame(
    index=pd.bdate_range(start='2012-01-01', periods=N, freq='B'), 
    data={x: np.random.randn(N) for x in range(1, 11)}
)

# Simulate some zeros
bm = pd.DataFrame(index=bm.index, columns=bm.columns, data=np.where(np.abs(bm.values) < 0.02, 0, bm.values))

# Set zeros to Nan so that I don't plot them
bm = bm.replace({0: np.nan})

# unstack dataframe
flat_bm = bm.reset_index(drop=True).unstack()  # DROP DATES AND REPLACE WITH INT
x = flat_bm.index.get_level_values(0)
y = flat_bm.index.get_level_values(1)
z = flat_bm.values


# Set up plot
fig = plt.figure(figsize = (15,10))
ax = plt.axes(projection ='3d')

# plotting
ax.scatter(x, y, z, '.', c=flat_bm.values, cmap='Reds')

最后,绘图有一个整数而不是日期标签。

python matplotlib plot
1个回答
0
投票

当您向

matplotlib
提供日期时,它会使用
date2num
在内部将它们转换为数字,并绘制这些数字。它们是特定数字,其中 0 为 1970-01-01 00:00:00。您看不到数字,因为它将它们格式化为月、年、星期几等。

在您的情况下,您需要手动将日期转换为数字,从中创建一个绘图网格,然后在绘图后将数字重新格式化为有意义的日期标签。

这些是我执行的操作:

from matplotlib import dates as mdates

#Convert dates to numbers
date_as_num = mdates.date2num(bm.index)

#Grid for plotting
x_grid, y_grid = np.meshgrid(date_as_num, bm.columns)

[plotting code here...]

# Format based on a layout you define:
ax.xaxis.set_major_formatter(mdates.DateFormatter(fmt='%Y-%b-%a'))

第一步是将日期转换为

matplotlib.dates
可以使用
date_as_num = mdates.date2num(bm.index)
的数字。它将您的日期映射为数字,即
date_as_num=[15341, ..., 15478]
,这只是自 1970-01-01 以来的天数。

然后创建 x 和 y 网格来绘制数据。数据的形状为

100x10
,因此网格需要与之匹配。
x_grid, y_grid = np.meshgrid(date_as_num, bm.columns)
- 复制每个 y 值的 x 轴(给出
x_grid
),以及每个 x 值的 y 轴(给出
y_grid
)。

最后,绘制数据,然后使用有意义的日期标记格式化数字日期轴。下面我将其格式化为年-月名称-日名称(有关各种选项,请参阅格式代码):

ax.xaxis.set_major_formatter(mdates.DateFormatter(fmt='%Y-%b-%a'))

其他日期格式选项的示例:

# AutoDateFormater, where locator= can be None, MonthLocator(), etc
ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(mdates.MonthLocator()))

# ConciseDateFormatter can choose a clean and informative layout:
ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(locator=None))

可用日期定位器列表(周、月等)。基于示例的阅读,了解使用

matplotlib
进行日期格式化。


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


N = 100

bm = pd.DataFrame(
    index=pd.bdate_range(start='2012-01-01', periods=N, freq='B'), 
    data={x: np.random.randn(N) for x in range(1, 11)}
)

# Simulate some zeros
bm = pd.DataFrame(index=bm.index, columns=bm.columns, data=np.where(np.abs(bm.values) < 0.02, 0, bm.values))

# Set zeros to Nan so that I don't plot them
bm = bm.replace({0: np.nan})

# Set up plot
fig = plt.figure(figsize = (15,10))
ax = plt.axes(projection ='3d')

#Dates to numbers, and create meshgrid
from matplotlib import dates as mdates
date_as_num = mdates.date2num(bm.index)

x_grid, y_grid = np.meshgrid(date_as_num, bm.columns)

# plotting
ax.scatter(x_grid, y_grid, z, '.', c=flat_bm.values, cmap='Reds')
# Format based on a layout you define:
ax.xaxis.set_major_formatter(mdates.DateFormatter(fmt='%Y-%b-%a'))

#Examples of alternative formatting options:
# AutoDateFormater, where locator= can be None, MonthLocator(), etc
# ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(mdates.MonthLocator()))
# ConciseDateFormatter can choose a clean and informative layout:
# ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(locator=None))
© www.soinside.com 2019 - 2024. All rights reserved.