10
$\begingroup$

I created a somewhat lengthy Python code to show how the time of sunrise varies over a year, resulting in the following figure (daylight savings were disregarded):

sunrise vs. day

The dataset can be found here. The main difficulty was plotting the times correctly (659 should be adjacent to 700), and the subsequent labeling. My friend suggested without proof that this sort of diagram could be generated very easily (and perhaps more beautifully) in Mathematica and I was curious how one might go about it. My experience with plotting in Mathematica is very limited, but I'd be interested to learn!

$\endgroup$
  • 1
    $\begingroup$ Just look in the documentation under e.g., Sunrise... everything you need is there, including examples... $\endgroup$ – ciao Aug 26 '16 at 23:39
  • $\begingroup$ Searching google for "Mathematica Sunrise" leads you here: reference.wolfram.com/language/ref/Sunrise.html $\endgroup$ – bill s Aug 27 '16 at 2:14
11
$\begingroup$

Importing and converting the data

Import the data (replace "path_to_the_downloaded_file.html" with the file path of the actual data).

data = Import["path_to_the_downloaded_file.html", "Text"];

We know that our data of interest is formatted as (4 digits)(whitespace)(4 digits), so we can extract that, extract time of sunrise from it, and convert the sunrise to minutes:

data = StringCases[data, a : Repeated[DigitCharacter, {4}] ~~
     " " ~~ Repeated[DigitCharacter, {4}] :> 
     Dot[FromDigits /@ StringPartition[a, 2], {60, 1}]];

The list is scrambled, so we need to unscramble that.

Fortunately, the input data has months as columns and days as rows. We can use that property.

First generate a list from 1 to 366 (2016 is a leap year!) and split them according to the length of each month.

days = Internal`PartitionRagged[
 Range[366], {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}];

Then we swap rows and columns (Transpose doesn't work here because the list is ragged. We need Flatten: see (119)):

days = Flatten[days, {2, 1}];

We then use the data and days to rearrange the data in the correct order:

data = Normal@SparseArray@Inner[Rule, days, data, List];

The above codes in one line:

data = Normal@SparseArray@
  Inner[Rule, 
   Flatten[Internal`PartitionRagged[
     Range[366], {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 
      31}], {2, 1}], 
   StringCases[Import["path_to_the_downloaded_file.html", "Text"], 
    a : Repeated[DigitCharacter, {4}] ~~ " " ~~ 
      Repeated[DigitCharacter, {4}] :> 
     Dot[FromDigits /@ StringPartition[a, 2], {60, 1}]], List];

Constructing a plot

Mathematica doesn't have an option to use time as the y-axis, so we use the Ticks option to manually set the tick marks. (see (42528) for details)

With[{ticks = Range[240, 450, 30], 
  toHrMin = DateString[{0, 0, 0, 0, #}, {"Hour", ":", "Minute"}] &}, 
 ListPlot[data, 
  Ticks -> {Automatic, Transpose@{ticks, toHrMin /@ ticks}}, 
  AxesLabel -> {"Day", "Sunrise"}]]

Result!

Graph

Edit

Using the Sunrise Function

data =
 Dot[#[{"Hour", "Minute"}], {60, 1}] & /@ 
  Normal[Sunrise[
     Entity["City", {"Trenton", "NewJersey", "UnitedStates"}], 
     DateRange[{2016, 1, 1}, {2016, 12, 31}, {1, "Day"}], 
     TimeZone -> -5]][[All, -1]];

(* Same code as above *)
With[{ticks = Range[240, 450, 30], 
  toHrMin = DateString[{0, 0, 0, 0, #}, {"Hour", ":", "Minute"}] &}, 
 ListPlot[data, 
  Ticks -> {Automatic, Transpose@{ticks, toHrMin /@ ticks}}, 
  AxesLabel -> {"Day", "Sunrise"}]]

Graph from Sunrise

Note: for an unknown reason, the output of the Sunrise function (which is downloaded from Wolfram database) is not consistent with the data in OP.

$\endgroup$
  • $\begingroup$ Thank you, this is excellent! Even if there is in fact a Sunrise function it's nice to see how one would parse and plot the data in more general cases. $\endgroup$ – glinka Aug 28 '16 at 0:01

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.