1
$\begingroup$

I have data, with units, organized as a list of rules; this is so I can slice the data in different ways based on the variables represented.

I'm trying to find the most direct way to plot this and get axis titles with both the variable from the rule and unit from the values. I don't want to manually label the plots each time, so if Plot doesn't have a built-in then how can I write a function to do the inference? I'm looking for the most DRY approach possible.

This gives me the units, but not the variable names, in the labels:

data = {
   y -> {0, 33.2} (Quantity[1, ("KipsForce")/("Inches")^2]),
   x -> {0, 6} 10^-4
   };
ListLinePlot[Transpose@({x, y} /. data), AxesLabel -> Automatic]

On the same example, is it possible to retain units like "in/in"? I've done this by manually specifying the labels and using HoldForm to avoid evaluating the cancellation, but I can't get that to work with automatic labels as above.

$\endgroup$

2 Answers 2

1
$\begingroup$

This does everything I asked, including keeping the in/in unit:

(edit) I want to be independent of the order of data, but for now it needs to be ordered according to the axes for this to work.

data = {
   x -> {0, 6} 10^-4 Quantity["in/in"]
   y -> {0, 33.2}    Quantity["ksi"],
   };

GetLabels = # /. ((a_ -> b_) :>
  Row[{a, " ", QuantityForm@QuantityUnit@b[[1]]}]) &;

ListLinePlot[Transpose@({x,y} /. data), AxesLabel -> GetLabels@data]

(edit) More complete solution:

I changed GetLabels to take a point so the labels are ordered according to the data as it's given to Plot

data = { y -> ..., x -> ... };

points = Transpose@({x, y} /. data);
kv = (points /. ({a_, b_} :> {x -> a, y -> b}));

GetLabels = # /. ((a_ -> b_) :> 
          Row[{a, " ", QuantityForm@QuantityUnit@b}]) &;

ListLinePlot[points, AxesLabel -> style`size[16] /@ GetLabels@kv[[1]]]
$\endgroup$
2
  • 2
    $\begingroup$ Your labels are on the wrong axes. You should change the definition of data to data = Reverse@{y -> {0, 33.2} Quantity["ksi"], x -> {0, 6} 10^-4 Quantity["in/in"]}; $\endgroup$
    – Bob Hanlon
    Sep 10, 2020 at 20:45
  • 1
    $\begingroup$ Thanks @BobHanlon you're absolutely right! I'll leave this unsolved because order independence is part of what I want out of this $\endgroup$ Sep 10, 2020 at 22:35
1
$\begingroup$
ClearAll[data, x, y, assoc, labelFunc]
data = {x -> Map[Quantity[#, "in/in"] &]@({0, 6} 10^-4) , 
   y -> Map[Quantity[#, "ksi"] &]@({0, 33.2} )};

We define two Associations using data:

assoc = Association @ data;

labelingAssoc = Association @ KeyValueMap[# -> Quantity[#, #2] &] @ 
    QuantityUnit @ Map[First] @ assoc
 <|x -> Quantity[x, ("Inches")/("Inches")],
   y -> Quantity[y,("KipsForce")/("Inches")^2]|>

We can map the two associations on the list of variables

ListLinePlot[Transpose[assoc /@ {x, y}], AxesLabel -> labelingAssoc /@ {x, y}]

or use them with as replacement rules

ListLinePlot[Transpose[{x, y} /. assoc],  AxesLabel -> {x, y} /. labelingAssoc]

to get

enter image description here

Alternatively, define a function for labeling

labelFunc = Map[Quantity[#, QuantityUnit @ First[assoc @ #]] &];

ListLinePlot[Transpose[assoc /@ {x, y}], AxesLabel -> labelFunc @ {x, y}]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.