Kutu BarLegend terdistorsi di MatrixPlot
Seperti yang ditunjukkan di banyak utas di sini ( ini , ini , ...), Ticksadalah opsi yang valid dari BarLegend. Tapi tampaknya tidak berhasil dengan baik dalam hal sederhana ini MatrixPlot. Beberapa tanda centang hilang begitu saja dan 0,5 jelas tidak berada di tempat yang tepat (warna). Perhatikan bahwa saya ingin plot default dengan kutu khusus. Apa yang saya lewatkan di sini atau solusi lainnya?
data = Table[Sin[x] Cos[y], {x, 0, 2 Pi, 0.01}, {y, 0, 2 Pi, 0.01}];
MatrixPlot[data,
PlotLegends -> BarLegend[Automatic, "Ticks" -> {-0.5, 0, 0.5}],
LabelStyle -> Large]
Memperbarui:
kasus yang lebih umum dengan rentang data asimetris
data = Table[Sin[x] Cos[y] + 0.05 x y, {x, 0, 2 Pi, 0.01}, {y, 0, 2 Pi, 0.01}];
MatrixPlot[data, PlotLegends -> BarLegend[Automatic, "Ticks" -> {-0.2, 0.5, 1.1}],
LabelStyle -> Large]
Jawaban
Pembaruan: Fungsi Graphics`ArrayPlotDump`Private`HybridRankingAndNaturalScalemelakukan "penskalaan berdasarkan campuran nilai relatif dan peringkat untuk setiap elemen matriks" yang misterius . Kami membangun fungsi penskalaan ulang sebagian ( reScale) menggunakan mpReScaledan menggunakannya untuk menentukan nilai opsi untuk "Ticks":
ClearAll[reScale, cfMinMax]
reScale[{min_, max_}, {cfmin_, cfmax_}] :=
If[# < 0, Rescale[#, {min, 0}, {cfmin, 1/2}], Rescale[#, {0, max}, {1/2, cfmax}]] &;
cfMinMax = MinMax @ Graphics`ArrayPlotDump`Private`HybridRankingAndNaturalScale[
Union @ SparseArray[#]["NonzeroValues"], 0., {0, 1}, .5] &;
Contoh:
data = {{1, 2, 1}, {2, 0, 1}, {0, -5, -1}};
ticks = {-4, -2, 3/2, 2};
cfminmax = cfMinMax[data];
minmax = MinMax @ data;
Row[{MatrixPlot[data, ImageSize -> 400,
PlotLegends -> BarLegend[Automatic], LabelStyle -> 16,
PlotLabel -> "default"],
MatrixPlot[data, ImageSize -> 400,
PlotLegends -> BarLegend[Automatic,
"Ticks" -> (Transpose[{reScale[minmax, cfminmax] /@ #, #}] & @ ticks)],
LabelStyle -> 16,
PlotLabel -> Row[{"Ticks : ", ticks}]]}, Spacer[10]]
Sebuah samping: Kita dapat menggunakan opsi lain yang tidak terdokumentasi untuk menentukan label centang
BarLegend[Automatic, "TickLabels" -> ticks,
"Ticks" -> (reScale[minmax, cfminmax] /@ ticks)]
untuk mendapatkan gambaran pada plot kedua diatas.
Ubah datadan ticksmenjadi
data = Table[Sin[x] Cos[y], {x, 0, 2 Pi, 0.01}, {y, 0, 2 Pi, 0.01}];
ticks = {-0.5, 0, 0.5};
mendapatkan
Menggunakan contoh kedua di OP:
data = Table[Sin[x] Cos[y] + 0.05 x y, {x, 0, 2 Pi, 0.01}, {y, 0, 2 Pi, 0.01}];
ticks = {-0.2, 0.5, 1.1};
kita mendapatkan
Dengan
data = 1. + Table[Sin[x] Cos[y] + 0.05 x y, {x, 0, 2 Pi, 0.01}, {y, 0, 2 Pi, 0.01}] ;
ticks = {0.1, 0.5, 1.1, 2};
kita mendapatkan
Jawaban asli:
Ini tampaknya terkait dengan cara khusus penskalaan dilakukan MatrixPlotseperti yang disebutkan dalam MatrixPlot >> Detail dan Opsi
Perbaikan termudah dalam kasus OP adalah mengubah spesifikasi tick menjadi Transpose[{Rescale[#, {-1, 1}, {0, 1}], #} &@{-0.5, 0, 0.5}]:
MatrixPlot[data,
PlotLegends ->
BarLegend[Automatic,
"Ticks" -> Transpose[{Rescale[#, {-1, 1}, {0, 1}], #} & @ {-0.5, 0, 0.5}]],
LabelStyle -> Large]
Sebagai alternatif (lebih umum) penyelesaian, gunakan fungsi warna default dengan argumen skala ulang dan opsi ColorFunctionScaling -> False:
defaultCF = "DefaultColorFunction" /.
(Method /. Charting`ResolvePlotTheme[Automatic, MatrixPlot])
Blend[System`PlotThemeDump`$ThemeDefaultMatrix, #1] &
MatrixPlot[data,
ColorFunction -> (defaultCF[Rescale[#, {-1, 1}]] &),
ColorFunctionScaling -> False,
PlotLegends -> BarLegend[Automatic, "Ticks" -> {-0.5, 0, 0.5}],
LabelStyle -> Large]
Atau, tentukan fungsi warna di BarLegend:
MatrixPlot[data,
PlotLegends -> BarLegend[{defaultCF[Rescale[#, {-1, 1}]] &, {-1, 1}},
ColorFunctionScaling -> False, "Ticks" -> {-0.5, 0, 0.5}],
LabelStyle -> Large]
kglr telah menyelesaikan masalah, berikut ini hanya beberapa analisis tambahan dan kemungkinan penyelesaian lainnya.
Pertama-tama, menurut saya ini bukan bug, karena secara default MatrixPlottahu cara mengatur yang tepat Ticksuntuk BarLegend:
plot = MatrixPlot[data, ImageSize -> 400, PlotLegends -> Automatic]
Melihat ke dalam plot, kami menemukan bahwa:
plot[[2, 1]] // InputForm
(*
BarLegend[{Blend[System`PlotThemeDump`$ThemeDefaultMatrix, #1] & ,
{0.2889327547713697, 1.}}, LabelStyle -> {},
LegendLayout -> "Column", LegendMarkerSize -> 400,
Ticks -> {{0.39446607623278385, -0.5}, {0.5, 0.}, {0.3100389372190109,
-0.9}, {0.626985112913238, 0.5}, {0.753970225826476, 1.},
{0.880955338739714, 1.5}, {0.9825434290703043, 1.9000000000000001}},
"PinningPoint" -> 0.5, "SmoothRange" -> False,
Charting`TickSide -> Right, ColorFunctionScaling -> False]
*)
Seperti yang bisa kita lihat, tanda centang BarLegendditetapkan oleh Ticksopsi yang tidak terdokumentasi , kami memplot tanda centang:
autotick = Cases[plot[[2, 1]], (Ticks -> a_) :> a][[1]] // Sort
ListLinePlot[autotick]
Tidak sulit untuk menyadari bahwa itu adalah garis yang terpecah belah {0.5, 0.}. Kami selanjutnya dapat memverifikasi ini dengan LinearModelFit:
LinearModelFit[autotick[[#]], {1, x}, x]["RSquared"] & /@ {;; 3, 3 ;;}
(* {1., 1.} *)
Jadi, meskipun kami tidak menyadarinya Graphics`ArrayPlotDump`Private`HybridRankingAndNaturalScale, kami masih dapat mengubah skala kutu dengan cara berikut:
ticks = {-0.2, 0.5, 1.1}
Clear[rescale]
rescale[tick_List, rest__] := rescale[#, rest] & /@ tick
rescale[tick_?Positive, mysteryminmax_, {min_, max_}] :=
Rescale[tick, {0, max}, {1/2, mysteryminmax[[2]]}]
rescale[tick_, mysteryminmax_, {min_, max_}] :=
Rescale[tick, {min, 0}, {mysteryminmax[[1]], 1/2}]
plot /. (Ticks -> _) :> (Ticks -> {rescale[ticks,
Sequence @@ (autotick[[{1, -1}]]\[Transpose])], ticks}\[Transpose])