如何在Python中的热图的y轴上显示动态(可扩展)时间标签

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

我正在读取一个 csv 文件,其中包含 1 列日期、1 列时间和 120 列整数。 该文件可能包含许多行(可能超过 100,000 行)。

数据点被转换为 0 到 1 之间的颜色索引,并将它们绘制到热图上。

我的问题是将时间列显示为 Y 轴标签。

无论我尝试什么,标签都显示在不可读的视图中。 完整视图 - 标签不可红色

如果我放大以查看更多颜色细节,标签将更易读。 放大 - 标签可读

我希望标签在任何视图中都可读,即使在完整视图中也是如此。 一些标签在缩小视图中不会显示,只有在放大时才会显示,这是可以接受的。

我尝试创建如下所示的 y 刻度,其中“data”是 pandas 数据框,case_times 是带有日期时间对象的数据框。

import numpy as np
import pandas as pd
from datetime import datetime

data = pd.read_csv(csvfile, delimiter=r',|\s|\|', header=None)
data = np.split(dsa_data, [1, 2, 62, 122], axis=1)
case_times = dsa_data[1]
case_times[1] = pd.to_datetime(case_times[1], format='%H:%M:%S').dt.time
case_times = np.squeeze(case_times)

fig, axs = plt.subplots(1,2)
fig.tight_layout()
im1 = axs[0].imshow(data, cmap='DSAColorMap')
    
    
axs[0].set_yticks(ticks=np.arange(1, len(case_times)+1, 1), labels=case_times)
axs[0].set_autoscale_on(True)
plt.show()

然后我尝试从一列字符串而不是数据帧开始,但我得到了相同的结果:

with open(fileName, newline='') as csvfile:
    # Advance rows 3 time to skip headers and extract case start date 
    # without the need to iterate over the file
    row = next(csvfile)
    row = next(csvfile)
    row = next(csvfile) 
    text_to_split = re.split(r',|\s|\|', row)
    case_start_date = text_to_split[0]
    # Remove blank items created after split by '|' delimiter
    text_to_split = text_to_split[:len(text_to_split)-3]
    #Create a list of time stamps to be later used as x axis for the plot
    case_times.append(text_to_split.pop(1)) 
    # Create the first data row
    data.append(text_to_split[1:61])
    spamreader = csv.reader(csvfile, delimiter='|')
    # Iterate over all remaining rows
    # to create the data rows
    for row in spamreader:
            text_to_split = ' '.join(row) # Create a list from all elements of data in a row
            text_to_split = re.split(r',|\s', text_to_split) # split row by delimiters
            text_to_split.pop(len(text_to_split)-1) # Remove last element of the row which is blank
            text_to_split.pop(0) # Remove date from row
            #Create a list of time stamps to be later used as axis labels for the plot
            case_times.append(text_to_split.pop(0)) 
            # Add data row to each hemisphere data list
            data.append(text_to_split[:60])

converted_case_times = [] # transform from string to datetime
for i in range(len(case_times)):
    converted_case_times.append(datetime.strptime(case_times[i], '%H:%M:%S'))
    
fig, axs = plt.subplots(1,2)
fig.tight_layout()
im1 = axs[0].imshow(dsa_data_left, cmap='DSAColorMap')
axs[0].set_yticks(ticks=range(1, len(converted_case_times)+1), labels=converted_case_times)
plt.show()

我还尝试了以下格式更改来解决该问题,但它也不起作用:

from matplotlib.dates import DateFormatter

axs[0].yaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
    plt.setp(axs[0].get_yticklabels(), rotation=45, ha="right",
         rotation_mode="anchor")

我认为问题在于创建刻度(作为固定范围),但是我不知道如何解决这个问题,而且我找不到适合我的情况的解释或示例。

python heatmap axis-labels
1个回答
0
投票

实现此目的的最简单方法是删除部分标签。

更改第一个代码块中的倒数第三行:

indices = np.arange(0,len(case_times), 100)
axs[0].set_yticks(ticks=indices+1, labels=case_times[indices])

这里我使用

step
的可选
arange
参数将其设置为每 100 个元素仅取一个元素。您可能需要根据您拥有的标签数量增加此步骤;一个想法可能就是使用

indices = np.arange(n)/n * len(case_times)

这只会显示

n
标签,间距相等。

编辑:评论后澄清

我相信您还应该看看

ax[0].callbacks.connect
并创建一个根据需要设置索引的函数。它应该看起来像这样:

ticks = np.arange(1, len(case_times)+1)
def generate_yticks(ax):
    ylims = ax.get_ylim()
    ticks_in_window = ticks[ticks>ylims[0]][ticks<ylims[1]]
    shown_ticks = ticks_in_window[np.arange(n)/n * len(ticks_in_window)]
    shown_labels = case_times[shown_ticks-1]
    ax.set_yticks(ticks=shown_ticks, labels=shown_labels)

ax[0].callbacks.connect("ylim_changed", generate_yticks)
© www.soinside.com 2019 - 2024. All rights reserved.