14

Consider the following data indicating temperature in degree Celcius vs time in hours:

SeedRandom[95];
TEMPvsTIME = {Range[100], 
    Accumulate[RandomReal[{-1, 1}, 100]]}\[Transpose];


ListPlot[TEMPvsTIME, Joined -> True, Frame -> True, 
 FrameLabel -> {"Time (hr)", "Temp (C)"}]

enter image description here

How can I include another horizontal and vertical axis on the top and on the right, scaled for the same data/plot to show time in minutes and temperature in Fahrenheit respectively? Unlike this question, I am not plotting 2 datasets and the only way that comes to my mind is to create an empty dataset and use TwoAxisPlot. Is there a better way of doing this?

Michael E2
  • 235,386
  • 17
  • 334
  • 747
Miladiouss
  • 1,883
  • 11
  • 26

3 Answers3

14

Charting`FindTicks

You can also use Charting`FindTicks to get the linearly scaled ticks:

ListPlot[TEMPvsTIME, Joined -> True, Frame -> True,
 FrameTicks -> {{Automatic,   Charting`FindTicks[{0, 100}, {32, 212}]}, 
   {Automatic,  Charting`FindTicks[{0, 1}, {0, 60}]}},
 FrameLabel -> {{"Temp (C)", "Temp (F)"}, {"Time (hr)", "Time (min)"}}]

enter image description here

Update: If you wish to have the same positions but different labels for axes pairs (as suggested by Jose in a comment) you can do

cft = Charting`FindTicks[{0, 1}, {0, 1}];
ListPlot[TEMPvsTIME, Joined -> True, Frame -> True,
 FrameTicks -> {{cft,
    Replace[cft[##], {x_?NumericQ, Except[""], z___} :> {x,  32 + 9/5 x, z}, 1] &},
  {cft,  Replace[cft[##], {x_?NumericQ, Except[""], z___} :> {x, Floor[60  x], z}, 1] &}},
 FrameLabel -> {{"Temp (C)", "Temp (F)"}, {"Time (hr)",  "Time (min)"}}]

enter image description here

Update 2: To add GridLines (thanks @JoseAntonioDiazNavas for the suggestion) and quantity units in temperature labels (as in egwene sedai's answer):

ListPlot[TEMPvsTIME, Joined -> True, Frame -> True, 
  FrameTicks -> {{Replace[cft[##], {x_?NumericQ, Except[""], z___} :> 
     {x, Quantity[x, "Celsius"], z}, 1] &, 
    Replace[cft[##], {x_?NumericQ, Except[""], z___} :>
     {x,  UnitConvert[Quantity[x, "Celsius"], "Fahrenheit"], z},  1] &}, 
   {cft, Replace[cft[##], {x_?NumericQ, Except[""], z___} :> {x, Floor[60 x], z}, 1] &}}, 
   FrameLabel -> {{"Temp (C)", "Temp (F)"}, {"Time (hr)",  "Time (min)"}}, 
  GridLines -> {Automatic, (DeleteCases[cft[##], {_, "", ___}][[All, 1]] &)}]

enter image description here

kglr
  • 394,356
  • 18
  • 477
  • 896
12

You can use FrameTicks to specify the kind of ticks you want. I like using Charting`ScaledTicks to specify ticks, so the following would be my approach:

ListPlot[
    TEMPvsTIME,
    Joined->True,
    Frame->True,
    FrameTicks->{
        {Automatic,Charting`ScaledTicks[{5/9(#-32)&,9/5#+32&}]},
        {Automatic,Charting`ScaledTicks["Linear",{#/60&,# 60&},"Nice"]}
    },
    FrameLabel->{{"Temp (C)", "Temp (F)"},{"Time (hr)", "Time (min)"}}
]

enter image description here

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
11

You may use the SciDraw Package:

Needs["SciDraw`"];

SeedRandom[95];
TEMPvsTIME = {Range[100], 
    Accumulate[RandomReal[{-1, 1}, 100]]}\[Transpose];


ListPlot[TEMPvsTIME, Joined -> True, Frame -> True, 
 FrameLabel -> {{"Temp (C)", "Temp (F)"}, {"Time (hr)", 
    "Time (min)"}}, 
 FrameTicks -> {{LinTicks[0, 6, 1, 2], 
    LinTicks[0, 6, 1, 2, 
     TickLabelFunction -> (UnitConvert[Quantity[#, "Celsius"], 
         "Fahrenheit"] &)]}, {LinTicks[0, 100, 20, 2], 
    LinTicks[0, 100, 20, 2, TickLabelFunction -> (#*60 &)]}}]

enter image description here

egwene sedai
  • 2,355
  • 16
  • 24
  • note: Carl Woll's answer works wonderfully and does not require 3rd party packages; here you need to load the extra package, but it is better documented than Charting `ScaledTicks – egwene sedai Feb 13 '18 at 20:30
  • seai, I did not know about SciDraw. I'll start using it. Thanks! – Miladiouss Feb 14 '18 at 04:36