热图中的日期轴 seaborn
Posted
技术标签:
【中文标题】热图中的日期轴 seaborn【英文标题】:Date axis in heatmap seaborn 【发布时间】:2017-04-16 23:10:44 【问题描述】:一点信息:我对编程很陌生,这是我第一个脚本的一小部分。这个特定部分的目标是显示一个海洋热图,其中 y 轴为垂直深度,x 轴为时间,科学测量的强度作为热函数。
如果这个问题已经在别处得到解答,我想道歉,但我的搜索能力一定让我失望了。
sns.set()
nametag = 'Well_4_all_depths_capf'
Dp = D[D.well == 'well4']
print(Dp.date)
heat = Dp.pivot("depth", "date", "capf")
### depth, date and capf are all columns of a pandas dataframe
plt.title(nametag)
sns.heatmap(heat, linewidths=.25)
plt.savefig('%s%s.png' % (pathheatcapf, nametag), dpi = 600)
这是从 ' print(Dp.date) ' 打印的内容 所以我很确定数据框的格式是我想要的格式,特别是年、日、月。
0 2016-08-09
1 2016-08-09
2 2016-08-09
3 2016-08-09
4 2016-08-09
5 2016-08-09
6 2016-08-09
...
但是,当我运行它时,日期轴总是打印出我不想要的空白时间(00:00 等)。 有没有办法从日期轴中删除这些?
问题是我在上面的一个单元格中使用此功能扫描文件名并用日期制作一列吗???使用 datetime 而不是仅使用 date 函数是错误的吗?
D['date']=pd.to_datetime(['%s-%s-%s' %(f[0:4],f[4:6],f[6:8]) for f in
D['filename']])
【问题讨论】:
【参考方案1】: 首先,'date'
列必须用pandas.to_datetime
转换为datetime dtype
如果想要的结果是只有日期(没有时间),那么最简单的解决方案是使用.dt
accessor 提取.date
组件。或者,使用dt.strftime
设置特定的字符串格式。
strftime()
and strptime()
Format Codes
df.date.dt.strftime('%H:%M')
会将小时和分钟提取到像 '14:29'
这样的字符串中
在下面的示例中,将提取的日期分配给同一列,但也可以将值分配为新列。
pandas.DataFrame.pivot_table
用于聚合一个函数,如果每个 index
的列中有多个值,如果只有一个值,则应使用 pandas.DataFrame.pivot
。
这比 .groupby
好,因为数据框的形状正确,易于绘制。
在python 3.8.11
、pandas 1.3.2
、matplotlib 3.4.3
、seaborn 0.11.2
中测试
import pandas as pd
import numpy as np
import seaborn as sns
# create sample data
dates = [f'2016-08-dT00:00:00.000000000' for d in range(9, 26, 2)] + ['2016-09-09T00:00:00.000000000']
depths = np.arange(1.25, 5.80, 0.25)
np.random.seed(365)
p1 = np.random.dirichlet(np.ones(10), size=1)[0] # random probabilities for random.choice
p2 = np.random.dirichlet(np.ones(19), size=1)[0] # random probabilities for random.choice
data = 'date': np.random.choice(dates, size=1000, p=p1), 'depth': np.random.choice(depths, size=1000, p=p2), 'capf': np.random.normal(0.3, 0.05, size=1000)
df = pd.DataFrame(data)
# display(df.head())
date depth capf
0 2016-08-19T00:00:00.000000000 4.75 0.339233
1 2016-08-19T00:00:00.000000000 3.00 0.370395
2 2016-08-21T00:00:00.000000000 5.75 0.332895
3 2016-08-23T00:00:00.000000000 1.75 0.237543
4 2016-08-23T00:00:00.000000000 5.75 0.272067
# make sure the date column is converted to a datetime dtype
df.date = pd.to_datetime(df.date)
# extract only the date component of the date column
df.date = df.date.dt.date
# reshape the data for heatmap; if there's no need to aggregate a function, then use .pivot(...)
dfp = df.pivot_table(index='depth', columns='date', values='capf', aggfunc='mean')
# display(dfp.head())
date 2016-08-09 2016-08-11 2016-08-13 2016-08-15 2016-08-17 2016-08-19 2016-08-21 2016-08-23 2016-08-25 2016-09-09
depth
1.50 0.334661 NaN NaN 0.302670 0.314186 0.325257 0.313645 0.263135 NaN NaN
1.75 0.305488 0.303005 0.410124 0.299095 0.313899 0.280732 0.275758 0.260641 NaN 0.318099
2.00 0.322312 0.274105 NaN 0.319606 0.268984 0.368449 0.311517 0.309923 NaN 0.306162
2.25 0.289959 0.315081 NaN 0.302202 0.306286 0.339809 0.292546 0.314225 0.263875 NaN
2.50 0.314227 0.296968 NaN 0.312705 0.333797 0.299556 0.327187 0.326958 NaN NaN
# plot
sns.heatmap(dfp, cmap='GnBu')
【讨论】:
【参考方案2】:标准热图日期时间标签示例
import pandas as pd
import seaborn as sns
dates = pd.date_range('2019-01-01', '2020-12-01')
df = pd.DataFrame(np.random.randint(0, 100, size=(len(dates), 4)), index=dates)
sns.heatmap(df)
我们可以创建一些辅助类/函数来获得更好看的标签和位置。 AxTransformer
支持从数据坐标到刻度位置的转换,set_date_ticks
允许将自定义日期范围应用于绘图。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from collections.abc import Iterable
from sklearn import linear_model
class AxTransformer:
def __init__(self, datetime_vals=False):
self.datetime_vals = datetime_vals
self.lr = linear_model.LinearRegression()
return
def process_tick_vals(self, tick_vals):
if not isinstance(tick_vals, Iterable) or isinstance(tick_vals, str):
tick_vals = [tick_vals]
if self.datetime_vals == True:
tick_vals = pd.to_datetime(tick_vals).astype(int).values
tick_vals = np.array(tick_vals)
return tick_vals
def fit(self, ax, axis='x'):
axis = getattr(ax, f'get_axisaxis')()
tick_locs = axis.get_ticklocs()
tick_vals = self.process_tick_vals([label._text for label in axis.get_ticklabels()])
self.lr.fit(tick_vals.reshape(-1, 1), tick_locs)
return
def transform(self, tick_vals):
tick_vals = self.process_tick_vals(tick_vals)
tick_locs = self.lr.predict(np.array(tick_vals).reshape(-1, 1))
return tick_locs
def set_date_ticks(ax, start_date, end_date, axis='y', date_format='%Y-%m-%d', **date_range_kwargs):
dt_rng = pd.date_range(start_date, end_date, **date_range_kwargs)
ax_transformer = AxTransformer(datetime_vals=True)
ax_transformer.fit(ax, axis=axis)
getattr(ax, f'set_axisticks')(ax_transformer.transform(dt_rng))
getattr(ax, f'set_axisticklabels')(dt_rng.strftime(date_format))
ax.tick_params(axis=axis, which='both', bottom=True, top=False, labelbottom=True)
return ax
这些为我们提供了很大的灵活性,例如
fig, ax = plt.subplots(dpi=150)
sns.heatmap(df, ax=ax)
set_date_ticks(ax, '2019-01-01', '2020-12-01', freq='3MS')
或者如果你真的想变得奇怪,你可以做类似的事情
fig, ax = plt.subplots(dpi=150)
sns.heatmap(df, ax=ax)
set_date_ticks(ax, '2019-06-01', '2020-06-01', freq='2MS', date_format='%b `%y')
对于您的具体示例,您必须将axis='x'
传递给set_date_ticks
【讨论】:
【参考方案3】:我有类似的问题,但日期是索引。我刚刚在绘图之前将日期转换为字符串(pandas 1.0),它对我有用。
heat['date'] = heat.date.astype('string')
【讨论】:
【参考方案4】:您必须对数据框的日期系列使用 strftime 函数才能正确绘制 xtick 标签:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
import random
dates = [datetime.today() - timedelta(days=x * random.getrandbits(1)) for x in xrange(25)]
df = pd.DataFrame('depth': [0.1,0.05, 0.01, 0.005, 0.001, 0.1, 0.05, 0.01, 0.005, 0.001, 0.1, 0.05, 0.01, 0.005, 0.001, 0.1, 0.05, 0.01, 0.005, 0.001, 0.1, 0.05, 0.01, 0.005, 0.001],\
'date': dates,\
'value': [-4.1808639999999997, -9.1753490000000006, -11.408113999999999, -10.50245, -8.0274750000000008, -0.72260200000000008, -6.9963940000000004, -10.536339999999999, -9.5440649999999998, -7.1964070000000007, -0.39225599999999999, -6.6216390000000001, -9.5518009999999993, -9.2924690000000005, -6.7605589999999998, -0.65214700000000003, -6.8852289999999989, -9.4557760000000002, -8.9364629999999998, -6.4736289999999999, -0.96481800000000006, -6.051482, -9.7846860000000007, -8.5710630000000005, -6.1461209999999999])
pivot = df.pivot(index='depth', columns='date', values='value')
sns.set()
ax = sns.heatmap(pivot)
ax.set_xticklabels(df['date'].dt.strftime('%d-%m-%Y'))
plt.xticks(rotation=-90)
plt.show()
【讨论】:
现在给出ValueError: The number of FixedLocator locations (13), usually from a call to set_ticks, does not match the number of ticklabels (25).
,所以不确定它是否完全正确...以上是关于热图中的日期轴 seaborn的主要内容,如果未能解决你的问题,请参考以下文章
通过 geom_tile ggplot R 的热图 - 正确组织每月因子的 y 轴水平