Присвоить цвет значениям

#julia

#julia

Вопрос:

Допустим, у меня есть код, который генерирует мне 2D-массив со значениями 0,1,2 или 3. Например.

 x = rand(Int8.(0:3), (4,4))
  

и теперь я хочу отобразить это на 2D-сетке, тогда как мы присваиваем каждому значению цвет, например:

0: белый, 1: зеленый, 2: синий, 3: красный

Пример:

Предположим, у меня есть матрица

 0 3
2 1
  

тогда я хотел бы иметь следующее изображение:

введите описание изображения здесь

теперь я подумал, что мог бы использовать тепловую карту, но следующий код

 using Plots
data = [0 3; 2 1]
heatmap(data, c=cgrad([:white, :green, :blue, :red], categorical=true))
  

дает мне
введите описание изображения здесь

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

Как я могу это сделать?

Ответ №1:

Вы можете написать, например

 using Plots
heatmap(x, c=cgrad([:white, :green, :blue, :red], categorical=true))
  

если вы хотите отключить ось и легенду и отменить запись строк (используя матричные операции):

 heatmap(reverse(x, dims=1),
        c=cgrad([:white, :green, :blue, :red], categorical=true),
        axis=nothing, legend=:none)
  

или с помощью heatmap kwarg (я сохраняю ось, чтобы показать, что они перевернуты)

 heatmap(x, yflip=true, c=cgrad([:white, :green, :blue, :red], categorical=true))
  

Комментарии:

1. Тепловая карта не работает, поскольку она упорядочивает мои данные. Я в основном хочу интерпретировать свою матрицу как изображение. Сетка фиксируется матрицей. Нет упорядочения данных, нет оси с каким-либо упорядочением. Просто сетка.

2. Я не понимаю вашего комментария — не могли бы вы уточнить? Я предполагаю, что вы хотите, чтобы после вашего обновления не было оси и легенды.

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

4. Да, я не хочу иметь никакого неявного порядка. Ось растет, начинается с 0 и увеличивается до некоторого значения, например, x = 1,2,3,4,5. Итак, если я создам тепловую карту с моей матрицей, она будет ориентирована так, чтобы она соответствовала оси. Это не то, чего я хочу. Мне просто нужна сетка. 🙂 Хотя спасибо

Ответ №2:

Я представляю решение с помощью Gaston.jl, которое использует gnuplot в качестве серверной части.

Обычный способ решить подобную проблему с помощью gnuplot — определить пользовательскую палитру и отобразить матрицу в виде изображения. Гастон настраивает оси так, чтобы матрица «выглядела» одинаково математически и как изображение; другими словами, элемент [1,1] рисуется в левом верхнем углу; элемент в последней строке и последнем столбце рисуется в нижнем правом углу.

Итак, это работает (на первый взгляд):

 using Gaston
M = [0 3; 2 1]
pal = "defined (0 'white', 1 'green', 2 'blue', 3 'red')"
imagesc(M, Axes(palette = pal, colorbox = :off, tics = :off))
  

введите описание изображения здесь

Сложность этого подхода заключается в том, что gnuplot масштабирует как элементы arrray, так и палитру в соответствии с диапазоном [0,1] . Таким образом, крайние значения палитры всегда присваиваются минимальным и максимальным элементам массива. Итак, следующий пример завершается с ошибкой:

 M = [1 0; 0 1];
pal = "defined (0 'white', 1 'green', 2 'blue', 3 'red')"
imagesc(M, Axes(palette = pal, colorbox = :off, tics = :off))
  

введите описание изображения здесь

Мы хотели бы видеть два зеленых квадрата вместо двух красных.

Возможное решение — программно сгенерировать палитру, которая работает. Предполагая, что мы заранее знаем диапазон (целых) элементов массива и палитры, следующая функция вычисляет пользовательскую палитру gnuplot, которая соответствует отображаемой матрице:

 const colors = Dict(0 => "white", 1 => "green", 2 => "blue", 3 => "red")

function define_pal(M)
    entries = unique(M) |> sort
    pal = "defined ("

    for e in entries
        pal *= "$e '$(colors[e])'"
        if e == entries[end]
            pal *= ")"
        else
            pal *= ", "
        end
    end
    return pal
end
  

Два примера:

 M = [1 0; 0 1];
imagesc(M, Axes(palette=define_pal(M), colorbox=:off, tics=:off))
  

введите описание изображения здесь

и

 M = [1 3; 3 1];
imagesc(M, Axes(palette=define_pal(M), colorbox=:off, tics=:off))
  

введите описание изображения здесь

Обратите внимание, что для Gaston требуется установить gnuplot.

Комментарии:

1. Опять же, это приводит к неправильному результату для M = [1 0; 0 1]: наличие системы координат не требуется. Это создает проблемы. 🙂

2. Проблема не в системе координат: gnuplot сопоставляет как элементы M , так и предоставленную палитру с диапазоном [0,1] , так что максимальное значение M всегда присваивается последнему цвету в палитре. Я не вижу никакого способа обойти это в gnuplot; однако, возможно, можно программно создать палитру, настроенную на минимальные и максимальные значения M .

3. @xotix Пожалуйста, посмотрите мой расширенный ответ.

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