Astral solar calculation

Viewed 296

I am fairly new to python and would like to calculate sun's position (azimuth and zenith angle) from a datetime column of a dataframe.

I found Astral module for this task and also made some correct calculations from it using the individual timestamps. But when I try to process the whole datetime column, I get an error.

I also tried to localize the dataframe (datetime column) to a specific timezone, but the error remains the same.

Help appreciated.

Here is the code:

import datetime
from datetime import datetime
import pytz
pytz.all_timezones
from astral import Astral

d1=pd.to_datetime(d1)
d1=d1.dt.tz_localize("Europe/Berlin")

The output looks like:

0   2015-02-04 09:10:21
1   2016-03-05 11:30:25
dtype: datetime64[ns]

Azimuth calculation:

print(Astral().solar_azimuth(d1, 52.52, -13.40))

Error:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-95-2a14f69465f4> in <module>
----> 1 print(Astral().solar_azimuth(d1, 52.52, -13.40))

~\Anaconda3\lib\site-packages\astral.py in solar_azimuth(self, dateandtime, latitude, longitude)
   2276             latitude = -89.8
   2277 
-> 2278         if dateandtime.tzinfo is None:
   2279             zone = 0
   2280             utc_datetime = dateandtime

~\Anaconda3\lib\site-packages\pandas\core\generic.py in __getattr__(self, name)
   5137             if self._info_axis._can_hold_identifiers_and_holds_name(name):
   5138                 return self[name]
-> 5139             return object.__getattribute__(self, name)
   5140 
   5141     def __setattr__(self, name: str, value) -> None:

AttributeError: 'Series' object has no attribute 'tzinfo'
1 Answers

Not sure how you got your code sample to work but basically, you can apply the solar_azimuth function to a pandas.Series like e.g.

import pandas as pd
from astral.location import Location, LocationInfo

# define your location
l = LocationInfo('name', 'region', 'timezone/name', 52.52, -13.40)

# assuming input datetimes are in the form of a pandas Series
d1 = pd.to_datetime(["2015-02-04 09:10:21", "2016-03-05 11:30:25"]).to_series().dt.tz_localize('Europe/Berlin')

azim = d1.apply(Location(l).solar_azimuth)

print(azim)
# 2015-02-04 09:10:21    112.190070
# 2016-03-05 11:30:25    137.505145
# dtype: float64

Note that you can do this without pandas as well, e.g.

from datetime import datetime
from zoneinfo import ZoneInfo # Python 3.9

dt = ["2015-02-04 09:10:21", "2016-03-05 11:30:25"]
# set time zone
dt = [datetime.fromisoformat(t).replace(tzinfo=ZoneInfo('Europe/Berlin')) for t in dt]
# azimut calc
azim = [Location(l).solar_azimuth(t) for t in dt]

print(azim)
# [112.19006967766785, 137.50514457536954]
Related