BarLegend ticks déformés dans MatrixPlot
Comme indiqué dans de nombreux threads ici ( this , this , ...), Ticksest une option valide de BarLegend. Mais cela ne semble pas bien fonctionner dans ce simple MatrixPlot. Certains ticks manquent juste et 0.5 n'est évidemment pas à sa bonne place (couleur). Notez que je veux le tracé par défaut avec des graduations personnalisées. Que me manque-t-il ici ou une solution de contournement?
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]
Mettre à jour:
un cas plus général avec une plage de données asymétrique
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]
Réponses
Mise à jour: La fonction Graphics`ArrayPlotDump`Private`HybridRankingAndNaturalScaleeffectue la mystérieuse «mise à l'échelle basée sur un mélange de valeur relative et de classement pour chaque élément de la matrice» . Nous construisons une fonction de redimensionnement par morceaux ( reScale) en utilisant mpReScaleet l'utilisons pour spécifier la valeur d'option pour "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] &;
Exemples:
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]]
Un aparté: nous pouvons utiliser une autre option non documentée pour spécifier des étiquettes de graduation
BarLegend[Automatic, "TickLabels" -> ticks,
"Ticks" -> (reScale[minmax, cfminmax] /@ ticks)]
pour obtenir l'image dans le deuxième graphique ci-dessus.
Changer dataet ticksà
data = Table[Sin[x] Cos[y], {x, 0, 2 Pi, 0.01}, {y, 0, 2 Pi, 0.01}];
ticks = {-0.5, 0, 0.5};
obtenir
En utilisant le deuxième exemple dans 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};
on a
Avec
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};
on a
Réponse originale:
Cela semble être lié à la manière particulière dont la mise à l'échelle est effectuée, MatrixPlotcomme mentionné dans MatrixPlot >> Détails et options
La solution la plus simple est dans le cas de OP est de changer la spécification de la coche en 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]
En guise de solution alternative (plus générale), utilisez la fonction de couleur par défaut avec un argument redimensionné et l'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]
Vous pouvez également spécifier la fonction de couleur dans BarLegend:
MatrixPlot[data,
PlotLegends -> BarLegend[{defaultCF[Rescale[#, {-1, 1}]] &, {-1, 1}},
ColorFunctionScaling -> False, "Ticks" -> {-0.5, 0, 0.5}],
LabelStyle -> Large]
kglr a déjà résolu le problème, voici juste une analyse supplémentaire et une autre solution possible.
Tout d'abord, je ne pense pas que ce soit un bug, car par défaut MatrixPlotsait comment définir correctement Tickspour BarLegend:
plot = MatrixPlot[data, ImageSize -> 400, PlotLegends -> Automatic]
En regardant dans le plot, nous constatons que:
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]
*)
Comme nous pouvons le voir, les graduations de BarLegendsont définies par l' Ticksoption non documentée , nous traçons les graduations:
autotick = Cases[plot[[2, 1]], (Ticks -> a_) :> a][[1]] // Sort
ListLinePlot[autotick]
Il n'est pas difficile de remarquer que c'est une ligne par morceaux, qui se divise {0.5, 0.}. Nous pouvons en outre vérifier cela avec LinearModelFit:
LinearModelFit[autotick[[#]], {1, x}, x]["RSquared"] & /@ {;; 3, 3 ;;}
(* {1., 1.} *)
Ainsi, même si nous ne sommes pas au courant de la Graphics`ArrayPlotDump`Private`HybridRankingAndNaturalScale, nous pouvons toujours redimensionner les graduations de la manière suivante:
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])