Iterate trough a converted datetime pandas dataframe with a external function

120 views Asked by At

https://rhodesmill.org/skyfield/positions.html#azimuth-and-altitude-from-a-geographic-position

Hi I have function that generates a sun-shot azimuth on a specific date and time on a specific place, using the package skyfield for astronomical calculations.

What do I want:

  • iterate trough the df2.cdt rows as fix time, currently astro = Nieuwe_diep.at(ts.utc(2019, 12, 31, 8, 41, 44)).observe(sun) for fix#1

  • add a new column to df2, called: df2.azimuth containing the output of az trough row itteration.

Currently I can only generate the azimuth for the first fix, with this code:

 # Sunshot Azimuth - hour angle method
from skyfield.api import N,S,E,W, wgs84
from skyfield.api import load
import pandas as pd

# location Port of Den Helder, Nieuwe diep:
lat = 52+(57/60)+(26.9/3600)
lon =  4+(46/60)+(37.5/3600)

# fix1 @ 2019-12-31 08:41:44 UTC

ts = load.timescale()
t = ts.utc(2019, 12, 31)
planets = load('de421.bsp')
earth, sun = planets['earth'], planets['sun']

# Altitude and azimuth in the sky for a specific geographic location
earth = planets['earth']
Nieuwe_diep = earth + wgs84.latlon(lat * N, lon * E, elevation_m=6)
astro = Nieuwe_diep.at(ts.utc(2019, 12, 31, 8, 41, 44)).observe(sun)

app = astro.apparent()

alt, az, distance = app.altaz()
print('alt: ' + alt.dstr())
print('az:  ' + az.dstr())
print(distance)


print('lat, lon: ' + str(lat), str(lon))
#dt_utc = df2['datetime_UTC']

print('az: {:.3f}'.format(az.degrees)) # desired output for azimuth in decimal degrees
print('az: '+ az.dstr(format=u'{0}{1}°{2:02}′{3:02}.{4:0{5}}″'))

which results in:

alt: 04deg 18' 42.2"
az:  138deg 52' 22.3"
0.983305 au
lat, lon: 52.95747222222222 4.777083333333334
az: 138.873
az: 138°52′22.3″

I have a pandas dataframe that consists of times of when I want to know the suns Azimuth. The column cdt

# cdt: converted datetime 
df2['cdt'] = df2['datetime_UTC'].dt.strftime('%Y, %m, %d, %H, %M, %S')
print(df2)
cdt = df2.cdt

          date       time        datetime_UTC                       cdt
0   2019-12-31   08:41:44 2019-12-31 08:41:44  2019, 12, 31, 08, 41, 44
1   2019-12-31   08:43:16 2019-12-31 08:43:16  2019, 12, 31, 08, 43, 16
2   2019-12-31   08:44:12 2019-12-31 08:44:12  2019, 12, 31, 08, 44, 12
3   2019-12-31   08:44:52 2019-12-31 08:44:52  2019, 12, 31, 08, 44, 52
4   2019-12-31   08:46:01 2019-12-31 08:46:01  2019, 12, 31, 08, 46, 01
5   2019-12-31   08:46:42 2019-12-31 08:46:42  2019, 12, 31, 08, 46, 42
6   2019-12-31   08:47:21 2019-12-31 08:47:21  2019, 12, 31, 08, 47, 21
7   2019-12-31   08:48:12 2019-12-31 08:48:12  2019, 12, 31, 08, 48, 12
8   2019-12-31   08:48:58 2019-12-31 08:48:58  2019, 12, 31, 08, 48, 58
9   2019-12-31   09:07:08 2019-12-31 09:07:08  2019, 12, 31, 09, 07, 08
10  2019-12-31   09:07:24 2019-12-31 09:07:24  2019, 12, 31, 09, 07, 24
11  2019-12-31   09:07:45 2019-12-31 09:07:45  2019, 12, 31, 09, 07, 45
12  2019-12-31   09:08:03 2019-12-31 09:08:03  2019, 12, 31, 09, 08, 03
13  2019-12-31   09:08:19 2019-12-31 09:08:19  2019, 12, 31, 09, 08, 19
14  2019-12-31   09:08:34 2019-12-31 09:08:34  2019, 12, 31, 09, 08, 34
15  2019-12-31   09:08:50 2019-12-31 09:08:50  2019, 12, 31, 09, 08, 50
16  2019-12-31   09:09:13 2019-12-31 09:09:13  2019, 12, 31, 09, 09, 13
17  2019-12-31   09:09:33 2019-12-31 09:09:33  2019, 12, 31, 09, 09, 33
18  2019-12-31   09:09:57 2019-12-31 09:09:57  2019, 12, 31, 09, 09, 57
19  2019-12-31   09:10:20 2019-12-31 09:10:20  2019, 12, 31, 09, 10, 20
1

There are 1 answers

0
Jonathan Leon On

I think this would work. You'd have to take the output and deal with that in a list, dictionary or some other dataframe. Also, there seems like there should be a better way to pass and parse the utc time but I'm not familiar with the library.

import io
data = '''date  time  datetime_UTC
  2019-12-31   08:41:44  2019-12-31 08:41:44
  2019-12-31   08:43:16  2019-12-31 08:43:16
  2019-12-31   08:44:12  2019-12-31 08:44:12
'''
df2 = pd.read_csv(io.StringIO(data), sep=' \s+', engine='python')
df2['datetime_UTC'] = pd.to_datetime(df2['datetime_UTC'])

df2['cdt'] = df2['datetime_UTC'].dt.strftime('%Y,%m,%d,%H,%M,%S')
# note I changed the formatting to remove spaces for later parsing

def calc_az(tutc):
    yr=int(tutc.split(',')[0])
    mo=int(tutc.split(',')[1])
    da=int(tutc.split(',')[2])
    hr=int(tutc.split(',')[3])
    mi=int(tutc.split(',')[4])
    se=int(tutc.split(',')[5])
    
    # location Port of Den Helder, Nieuwe diep:
    lat = 52+(57/60)+(26.9/3600)
    lon =  4+(46/60)+(37.5/3600)

    # fix1 @ 2019-12-31 08:41:44 UTC

    ts = load.timescale()
    t = ts.utc(2019, 12, 31)
    planets = load('de421.bsp')
    earth, sun = planets['earth'], planets['sun']

    # Altitude and azimuth in the sky for a specific geographic location
    earth = planets['earth']
    Nieuwe_diep = earth + wgs84.latlon(lat * N, lon * E, elevation_m=6)
    # astro = Nieuwe_diep.at(ts.utc(2019, 12, 31, 8, 41, 44)).observe(sun)
    astro = Nieuwe_diep.at(ts.utc(yr, mo, da, hr, mi, se)).observe(sun)

    app = astro.apparent()

    alt, az, distance = app.altaz()
    print('alt: ' + alt.dstr())
    print('az:  ' + az.dstr())
    print(distance)

    print('lat, lon: ' + str(lat), str(lon))
    #dt_utc = df2['datetime_UTC']

    print('az: {:.3f}'.format(az.degrees)) # desired output for azimuth in decimal degrees
    print('az: '+ az.dstr(format=u'{0}{1}°{2:02}′{3:02}.{4:0{5}}″'))
    print('\n'*2)
    return

df2['cdt'].apply(calc_az)

output

alt: 04deg 18' 42.2"
az:  138deg 52' 22.3"
0.983305 au
lat, lon: 52.95747222222222 4.777083333333334
az: 138.873
az: 138°52′22.3″



alt: 04deg 27' 47.3"
az:  139deg 11' 31.5"
0.983305 au
lat, lon: 52.95747222222222 4.777083333333334
az: 139.192
az: 139°11′31.5″



alt: 04deg 33' 17.4"
az:  139deg 23' 11.9"
0.983305 au
lat, lon: 52.95747222222222 4.777083333333334
az: 139.387
az: 139°23′11.9″