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$
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]]]
| improve this answer | |
$\endgroup$
  • 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 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$ – Matt Murphy Sep 10 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

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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