热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Matplotlib和Numpy-创建日历热图-MatplotlibandNumpy-Createacalendarheatmap

Isitpossibletocreateacalendarheatmapwithoutusingpandas?Ifso,cansomeonepostasimplee

Is it possible to create a calendar heatmap without using pandas? If so, can someone post a simple example?

是否可以在不使用熊猫的情况下创建日历热图?如果是这样,有人可以发一个简单的例子吗?

I have dates like Aug-16 and a count value like 16 and I thought this would be a quick and easy way to show intensity of counts between days for a long period of time.

我有8月16日的日期和16的计数值,我认为这将是一种快速简便的方法,可以显示很长一段时间内天数之间的计数强度。

Thank you

3 个解决方案

#1


14  

It's certainly possible, but you'll need to jump through a few hoops.

这当然是可能的,但你需要跳过一些箍。

First off, I'm going to assume you mean a calendar display that looks like a calendar, as opposed to a more linear format (a linear formatted "heatmap" is much easier than this).

首先,我假设您的意思是日历显示看起来像日历,而不是更线性的格式(线性格式化的“热图”比这更容易)。

The key is reshaping your arbitrary-length 1D series into an Nx7 2D array where each row is a week and columns are days. That's easy enough, but you also need to properly label months and days, which can get a touch verbose.

关键是将任意长度的1D系列重塑为Nx7 2D阵列,其中每行为一周,列为天。这很容易,但你还需要正确标记数月和数天,这可能会让人感到啰嗦。

Here's an example. It doesn't even remotely try to handle crossing across year boundaries (e.g. Dec 2014 to Jan 2015, etc). However, hopefully it gets you started:

这是一个例子。它甚至没有远程尝试跨越年度跨越(例如2014年12月至2015年1月等)。但是,希望它可以让你开始:

import datetime as dt
import matplotlib.pyplot as plt
import numpy as np

def main():
    dates, data = generate_data()
    fig, ax = plt.subplots(figsize=(6, 10))
    calendar_heatmap(ax, dates, data)
    plt.show()

def generate_data():
    num = 100
    data = np.random.randint(0, 20, num)
    start = dt.datetime(2015, 3, 13)
    dates = [start + dt.timedelta(days=i) for i in range(num)]
    return dates, data

def calendar_array(dates, data):
    i, j = zip(*[d.isocalendar()[1:] for d in dates])
    i = np.array(i) - min(i)
    j = np.array(j) - 1
    ni = max(i) + 1

    calendar = np.nan * np.zeros((ni, 7))
    calendar[i, j] = data
    return i, j, calendar


def calendar_heatmap(ax, dates, data):
    i, j, calendar = calendar_array(dates, data)
    im = ax.imshow(calendar, interpolation='none', cmap='summer')
    label_days(ax, dates, i, j, calendar)
    label_months(ax, dates, i, j, calendar)
    ax.figure.colorbar(im)

def label_days(ax, dates, i, j, calendar):
    ni, nj = calendar.shape
    day_of_mOnth= np.nan * np.zeros((ni, 7))
    day_of_month[i, j] = [d.day for d in dates]

    for (i, j), day in np.ndenumerate(day_of_month):
        if np.isfinite(day):
            ax.text(j, i, int(day), ha='center', va='center')

    ax.set(xticks=np.arange(7), 
           xticklabels=['M', 'T', 'W', 'R', 'F', 'S', 'S'])
    ax.xaxis.tick_top()

def label_months(ax, dates, i, j, calendar):
    month_labels = np.array(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
                             'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])
    mOnths= np.array([d.month for d in dates])
    uniq_mOnths= sorted(set(months))
    yticks = [i[mOnths== m].mean() for m in uniq_months]
    labels = [month_labels[m - 1] for m in uniq_months]
    ax.set(yticks=yticks)
    ax.set_yticklabels(labels, rotation=90)

main()

enter image description here

#2


0  

Edit: I now see the question asks for a plot without pandas. Even so, this question is a first page Google result for "python calendar heatmap", so I will leave this here. I recommend using pandas anyway. You probably already have it as a dependency of another package, and pandas has by far the best APIs for working with datetime data (pandas.Timestamp and pandas.DatetimeIndex).

编辑:我现在看到问题要求没有大熊猫的情节。即便如此,这个问题是谷歌搜索“python calendar heatmap”的第一页,所以我将把它留在这里。无论如何,我建议使用熊猫。您可能已经将它作为另一个包的依赖项,并且pandas迄今为止是处理日期时间数据的最佳API(pandas.Timestamp和pandas.DatetimeIndex)。

The only Python package that I can find for these plots is calmap which is unmaintained and incompatible with recent matplotlib. So I decided to write my own. It produces plots like the following:

我可以为这些图找到的唯一Python包是calmap,它是未维护的并且与最近的matplotlib不兼容。所以我决定写自己的。它产生如下图:

calendar heatmap Here is the code. The input is a series with a datetime index giving the values for the heatmap:

这是代码。输入是一个带有日期时间索引的系列,给出热图的值:

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


DAYS = ['Sun.', 'Mon.', 'Tues.', 'Wed.', 'Thurs.', 'Fri.', 'Sat.']
MOnTHS= ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'June', 'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.']


def date_heatmap(series, start=None, end=None, mean=False, ax=None, **kwargs):
    '''Plot a calendar heatmap given a datetime series.

    Arguments:
        series (pd.Series):
            A series of numeric values with a datetime index. Values occurring
            on the same day are combined by sum.
        start (Any):
            The first day to be considered in the plot. The value can be
            anything accepted by :func:`pandas.to_datetime`. The default is the
            earliest date in the data.
        end (Any):
            The last day to be considered in the plot. The value can be
            anything accepted by :func:`pandas.to_datetime`. The default is the
            latest date in the data.
        mean (bool):
            Combine values occurring on the same day by mean instead of sum.
        ax (matplotlib.Axes or None):
            The axes on which to draw the heatmap. The default is the current
            axes in the :module:`~matplotlib.pyplot` API.
        **kwargs:
            Forwarded to :meth:`~matplotlib.Axes.pcolormesh` for drawing the
            heatmap.

    Returns:
        matplotlib.collections.Axes:
            The axes on which the heatmap was drawn. This is set as the current
            axes in the `~matplotlib.pyplot` API.
    '''
    # Combine values occurring on the same day.
    dates = series.index.floor('D')
    group = series.groupby(dates)
    series = group.mean() if mean else group.sum()

    # Parse start/end, defaulting to the min/max of the index.
    start = pd.to_datetime(start or series.index.min())
    end = pd.to_datetime(end or series.index.max())

    # We use [start, end) as a half-open interval below.
    end += np.timedelta64(1, 'D')

    # Get the previous/following Sunday to start/end.
    # Pandas and numpy day-of-week conventions are MOnday=0 and Sunday=6.
    start_sun = start - np.timedelta64((start.dayofweek + 1) % 7, 'D')
    end_sun = end + np.timedelta64(7 - end.dayofweek - 1, 'D')

    # Create the heatmap and track ticks.
    num_weeks = (end_sun - start_sun).days // 7
    heatmap = np.zeros((7, num_weeks))
    ticks = {}  # week number -> month name
    for week in range(num_weeks):
        for day in range(7):
            date = start_sun + np.timedelta64(7 * week + day, 'D')
            if date.day == 1:
                ticks[week] = MONTHS[date.month - 1]
            if date.dayofyear == 1:
                ticks[week] += f'\n{date.year}'
            if start <= date 

#3


0  

Below is a code that can be used to generate a calendar map for daily profiles of a value. """ Created on Tue Sep 4 11:17:25 2018

下面是一个代码,可用于为值的每日配置文件生成日历映射。 “”创建于2010年9月4日星期二11:17:25

@author: woldekidank
"""`enter code here`

import numpy as np
from datetime import date
import datetime
import matplotlib.pyplot as plt
import random


D = date(2016,1,1)
Dord = date.toordinal(D)
Dweekday = date.weekday(D)

Dsnday = Dord - Dweekday + 1 #find sunday
square = np.array([[0, 0],[ 0, 1], [1, 1], [1, 0], [0, 0]])#x and y to draw a square
row = 1
count = 0
while row != 0:
    for column in range(1,7+1):    #one week per row
        prof = np.ones([24, 1])
        hourly = np.zeros([24, 1])
        for i in range(1,24+1):
            prof[i-1, 0] = prof[i-1, 0] * random.uniform(0, 1)
            hourly[i-1, 0] = i / 24
        plt.title('Temperature Profile')
        plt.plot(square[:, 0] + column - 1, square[:, 1] - row + 1,color='r')    #go right each column, go down each row
        if date.fromordinal(Dsnday).mOnth== D.month:
            if count == 0:
                plt.plot(hourly, prof)
            else:
                plt.plot(hourly + min(square[:, 0] + column - 1), prof + min(square[:, 1] - row + 1))

            plt.text(column - 0.5, 1.8 - row, datetime.datetime.strptime(str(date.fromordinal(Dsnday)),'%Y-%m-%d').strftime('%a'))
            plt.text(column - 0.5, 1.5 - row, date.fromordinal(Dsnday).day)

        Dsnday = Dsnday + 1
        count = count + 1

    if date.fromordinal(Dsnday).mOnth== D.month:
        row = row + 1    #new row
    else:
        row = 0    #stop the while loop

Below is the output from this code

以下是此代码的输出

enter image description here

在此处输入图像描述


推荐阅读
author-avatar
杀手也热血_949
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有