2

I have a pandas DataFrame with columns = [A, B, C, D] and rows = [a, b, c, d]. Each cell of my dataframe has a specifc date. I want to create a heatmap were later dates are colored diferent than earlier dates.

I managed to do something with plotly by converting my datetime variable to timestamp. But I want to annotate each cell with the datetime(timestamp). Is there a way to do that with Plotly?

vestland
  • 55,229
  • 37
  • 187
  • 305
  • Convert the dates into int `df.astype('int64')` – Quang Hoang Mar 25 '21 at 13:36
  • You mean, convert an ISO Formated data, such as "2021-03-25" to int? When I try I get this error: invalid literal for int() with base 10: '2021-04-16' – Lucas Corbanez Mar 25 '21 at 13:53
  • You datetime seems to be in string type, `df.astype('datetime64').astype('int64')`. – Quang Hoang Mar 25 '21 at 13:54
  • Oh, sorry. Now it completes the transformation, but still, all I get is a heatmap with int values. How do I convert them back to dates on Plotly after? I'm sorry if I'm not making myself clear. I will edit my question – Lucas Corbanez Mar 25 '21 at 14:11
  • Sorry, I'm not familiar with Plotly.There might be some option to work on the annotation. You can also try drop `astype('int64')` to see if Plotly supports heatmap for datetime type. – Quang Hoang Mar 25 '21 at 14:13
  • No troubles :) Plotly only shows the values as datetime64 = timestamp(datetimestr). – Lucas Corbanez Mar 25 '21 at 14:27

2 Answers2

1

You can use the same approach as in the answer to Plotly: How to round display text in annotated heatmap but keep full format on hover? as long as you handle your dates as a number value for the heatmap input, and grab the dates as string for your annotations. I like to juggle between pd.Timestamp() and to_pydatetime() and set an epoch such as datetime.datetime(1970,1,1) to calculate time differences against. The heatmap below is produced from a pandas dataframe with dates as strings. Let me know id you'd like to start with a dataframe with dates of any other format.

Data

data = {'A': ['2020-6-6', '2020-10-10', '2020-12-12'],
        'B': ['2019-6-6', '2019-10-10', '2019-12-12'],
        'C': ['2018-6-6', '2018-10-10', '2018-12-12']}

Heatmap

enter image description here

Code

import plotly.express as px
import plotly.figure_factory as ff
import pandas as pd
import datetime

# source is a pandas dataframe with dates as strings
data = {'A': ['2020-6-6', '2020-10-10', '2020-12-12'],
        'B': ['2019-6-6', '2019-10-10', '2019-12-12'],
        'C': ['2018-6-6', '2018-10-10', '2018-12-12']}
dfi = pd.DataFrame(data)

# grab dates as strings for use as labels later
z_text = [[y for y in x] for x in dfi.values.tolist()]

# convert df to pandas datetime
dfi = dfi.apply(pd.to_datetime)

# set epoch
epoch = datetime.datetime(1970,1,1)

# convert difference in days from all dates to epoch
# to use as input for color scheme in heatmap
days = [[ (pd.Timestamp(r).to_pydatetime()-epoch).days for r in dfi[col].values] for col in dfi.columns]
df = pd.DataFrame(days)
df.columns, df.index = dfi.columns,  dfi.columns
z = df.values.tolist()

# build heatmap
fig = ff.create_annotated_heatmap(z, x=list(df.columns),
                                     y=list(df.columns),
                                     annotation_text=z_text, colorscale='agsunset')

# add title
fig.update_layout(title_text='<i><b>Heatmap with dates</b></i>',
                  #xaxis = dict(title='x'),
                  #yaxis = dict(title='x')
                 )

# add custom xaxis title
fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=0.5,
                        y=-0.15,
                        showarrow=False,
                        text="",
                        xref="paper",
                        yref="paper"))

# add custom yaxis title
fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=-0.35,
                        y=0.5,
                        showarrow=False,
                        text="",
                        textangle=-90,
                        xref="paper",
                        yref="paper"))

# adjust margins to make room for yaxis title
# fig.update_layout(margin=dict(t=50, l=200))
# add colorbar
# fig['data'][0]['showscale'] = True

fig.show()
vestland
  • 55,229
  • 37
  • 187
  • 305
-1

I used seaborn for heatmaps.

import pandas as pd
import seaborn as sns

df = pd.read_csv('Dataset.csv')

Heatmap
sns.set(rc={'figure.figsize':(11.7,8.27)})
sns.heatmap(df.corr().round(2),square=True,cmap="RdYlGn",annot=True)

Documentation: https://seaborn.pydata.org/generated/seaborn.heatmap.html