Построение функции с 4 аргументами в сетке тепловых карт - PullRequest
0 голосов
/ 31 мая 2018

Я использую plotnine в python 2 (но был бы рад решению, использующему matplotlib или любой другой пакет для печати).У меня есть функция (немного упрощенная ниже) с 4 аргументами.Я хочу построить сетку тепловых карт, в которых «супероси» изменяют два параметра, а каждая тепловая карта изменяет два других.Немного похоже на это:

Heatmap grid skeleton diagram

Я придумал этот код:

from plotnine import ggplot, aes, facet_grid, geom_tile
import pandas as pd
import itertools

def fun((i, j, n, p)):
    if n > j:
        return 1 if (p**(3*n)) > ((p+i)**(3*(n-j))) else 0
    return -1

ilist, jlist, nlist, plist = range(1,10), range(1,9), range(8,10), range(4,6)
rows = itertools.product(ilist, jlist, nlist, plist)

df = pd.DataFrame(list(rows))
df.columns = ['i','j','n','p']
df['fun'] = df.apply(fun, axis=1)

(ggplot(df, aes('factor(i)', 'factor(j)')) +
 geom_tile(aes(fill='fun')) +
facet_grid('n ~ p', labeller='label_both'))

Это приводит к следующему:

Heatmap grid

Это (более или менее) имеет форму, к которой я стремлюсь, но тепловые карты кажутся неправильными.(РЕДАКТИРОВАТЬ: я обнаружил, что ошибка была в определении fun, а не в графике - см. Мой ответ).

1 Ответ

0 голосов
/ 01 июня 2018

ОК ... оказалось, что проблема не в графике, а в функции.Я не совсем понимаю, что пошло не так, но я думаю, что некоторые вычисления натолкнулись на проблемы с «огромным целым числом».Когда я запустил его, чтобы сделать сравнение в пространстве журнала, он начал работать.

Я оставлю это здесь, так как это может помочь другим, которые пытаются создать аналогичные сетки тепловых карт, и, возможно, кто-то ответит лучшеспособ сделать это.

Вот мой аннотированный код для создания самой тепловой карты из кадра данных со столбцами ['i', 'j', 'n', 'p']:

# The first two lines are defining the subplots, i.e. the heatmaps
# themselves. I am passing the dataframe, and specifying the names of the
# columns to use as axes. I say 'factor(i)' etc to treat the i column as
# discrete, not continuous (in my case it's integers).
gg = (ggplot(df, aes('factor(i)', 'factor(j)')) +
    geom_tile(aes(fill='fun')) +
# The last bit is to call facet_grid which applies the above code
# in a grid. The parameter 'n ~ p' specifies that I want the grid to be
# over the columns 'n' and 'p' from the dataframe. The labeller
# parameter is what makes the labels at the edges (see top and right in
# image below) show both the column name and the value).
    facet_grid('n ~ p', labeller='label_both'))

Вот полный исправленный код с фиксированным результатом:

from plotnine import ggplot, aes, facet_grid, geom_tile
import pandas as pd
import numpy as np
import itertools

def fun((i, j, n, p)):
    if n > j:
        return 1 if np.log10(p) * (3*n) > np.log10(p+i) * (3*(n-j)) else 0

    return -1

ilist, jlist, nlist, plist = range(1,10), range(1,9), range(8,10), range(4,6)
rows = itertools.product(ilist, jlist, nlist, plist)
df = pd.DataFrame(list(rows))
df.columns = ['i','j','n','p']
df['fun'] = df.apply(fun, axis=1)

gg = (ggplot(df, aes('factor(i)', 'factor(j)')) +
    geom_tile(aes(fill='fun')) +
    facet_grid('n ~ p', labeller='label_both'))

gg.draw()

Corrected heatmap

...