BarLegend-Ticks in MatrixPlot verzerrt
Wie in vielen Threads hier gezeigt ( dies , das , ...), Ticksist eine gültige Option von BarLegend. Aber so einfach scheint es nicht gut zu funktionieren MatrixPlot. Einige Zecken fehlen nur und 0,5 ist offensichtlich nicht an der richtigen Stelle (Farbe). Beachten Sie, dass ich das Standarddiagramm mit benutzerdefinierten Häkchen verwenden möchte. Was fehlt mir hier oder eine Problemumgehung?
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]
Aktualisieren:
Ein allgemeinerer Fall mit asymmetrischem Datenbereich
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]
Antworten
Update: Die Funktion Graphics`ArrayPlotDump`Private`HybridRankingAndNaturalScaleführt die mysteriöse "Skalierung basierend auf einer Mischung aus relativem Wert und Rang für jedes Matrixelement" durch . Wir konstruieren eine stückweise Neuskalierungsfunktion ( reScale) mit mpReScaleund verwenden sie, um den Optionswert für Folgendes anzugeben "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] &;
Beispiele:
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]]
Nebenbei: Wir können eine andere undokumentierte Option verwenden, um Tick-Labels anzugeben
BarLegend[Automatic, "TickLabels" -> ticks,
"Ticks" -> (reScale[minmax, cfminmax] /@ ticks)]
um das Bild in der zweiten Handlung oben zu bekommen.
Ändern dataund tickszu
data = Table[Sin[x] Cos[y], {x, 0, 2 Pi, 0.01}, {y, 0, 2 Pi, 0.01}];
ticks = {-0.5, 0, 0.5};
bekommen
Verwenden Sie das zweite Beispiel in 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};
wir bekommen
Mit
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};
wir bekommen
Ursprüngliche Antwort:
Dies scheint mit der speziellen Art und Weise der Skalierung zu tun zu haben, MatrixPlotwie in MatrixPlot >> Details und Optionen beschrieben
Im Fall von OP ist es am einfachsten, die Tick-Spezifikation zu ändern in 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]
Verwenden Sie als alternative (allgemeinere) Problemumgehung die Standardfarbfunktion mit neu skaliertem Argument und der Option 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]
Alternativ können Sie die Farbfunktion angeben in BarLegend:
MatrixPlot[data,
PlotLegends -> BarLegend[{defaultCF[Rescale[#, {-1, 1}]] &, {-1, 1}},
ColorFunctionScaling -> False, "Ticks" -> {-0.5, 0, 0.5}],
LabelStyle -> Large]
kglr hat das Problem bereits gelöst. Hier sind nur einige zusätzliche Analysen und eine weitere mögliche Problemumgehung.
Erstens denke ich nicht, dass dies ein Fehler ist, da standardmäßig MatrixPlotweiß, wie man richtig einstellt Ticksfür BarLegend:
plot = MatrixPlot[data, ImageSize -> 400, PlotLegends -> Automatic]
Wenn plotwir uns das ansehen, stellen wir fest, dass:
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]
*)
Wie wir sehen können, werden die Ticks von BarLegenddurch die undokumentierte TicksOption gesetzt. Wir zeichnen die Ticks:
autotick = Cases[plot[[2, 1]], (Ticks -> a_) :> a][[1]] // Sort
ListLinePlot[autotick]
Es ist nicht schwer zu bemerken, dass es sich um eine stückweise Linie handelt, die sich aufteilt {0.5, 0.}. Wir können dies weiter überprüfen mit LinearModelFit:
LinearModelFit[autotick[[#]], {1, x}, x]["RSquared"] & /@ {;; 3, 3 ;;}
(* {1., 1.} *)
Selbst wenn wir uns dessen nicht bewusst sind Graphics`ArrayPlotDump`Private`HybridRankingAndNaturalScale, können wir die Zecken auf folgende Weise neu skalieren:
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])