#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 на самом деле тоже работает, и я просто сделал что-то не так, когда пытался сделать это вчера. Поскольку я использую собственную реализацию, я пойду с ней. Грустно, что я не могу принять оба.