Тепловые карты по децилям в plotly.express
Построить тепловую карту (как и почти любую визуализацию данных) в великолепной plotly.express
невероятно просто:
px.density_heatmap(df, x='x', y='y', z='z', marginal_y='histogram').show()
Но иногда хочется разбить данные на децили/квартили/квинтили. Как например, в нашем случае - по оси Y.
К сожалению, “из коробки” plotly.express
не справится.
Если Вы сделаете вот так:
df.y_q = pandas.qcut(df.y, q=10)
px.density_heatmap(df, x='x', y='y_q', z='z', marginal_y='histogram').show()
То ничего не выйдет, plotly будет падать с ошибкой TypeError: Object of type Interval is not JSON serializable
Да, можно потанцевать с бубном и привести Interval
объекты к строке, и у Вас даже получится нарисовать density_heatmap
- но они будут сортироваться как строки и будут перепутаны с точки зрения значений y
.
px.density_heatmap(df, x='x', y=df.y_q.astype(str), z='z', marginal_y='histogram').show()
Можно явно передать plotly порядок для y
- и это будет работать, но код будет выглядеть так:
df['y_q'] = pandas.qcut(df.y, q=10)
order = [str(c) for c in reversed(df.y_q.cat.categories)]
px.density_heatmap(df, x='x', y=df.y_q.astype(str), z='z', \
marginal_y='histogram', category_orders={"y": order}).show()
Из плюсов - на оси Y обозначены понятные интервалы значений y
для каждого дециля.
Есть решение по-проще и по-красивее:
df.y_q, labels = pandas.qcut(df.y, q=10, labels=False, retbins=True)
px.density_heatmap(df, x='x', y='y_q', z='z', marginal_y='histogram').show()
Теперь df.y_q
(как и ось Y на графике) - это порядковый номер дециля, обычный int.
Границы интервалов лежат в numpy.array labels
, это 11 float чисел.
Красиво! И за 2 читаемые строчки!