kamome
kamome

Reputation: 858

Using pandas convert deg-min-sec to decimal degrees without explicitly iterating

I am using pandas to get a dataframe like this:

print (a) 

    0   1   2  3  4   5   6  7
0  36  30  36  N  2  31  18  W
1  36  43  52  N  2  17  25  W 
2  36  43  13  N  2  16  27  W
3  36  29  57  N  2  30  21  W
4  36  29  18  N  2  29  24  W

Then I am trying to use the columns 0, 1, and 2 to obtain the value of latitude. But I need the sign of that based on the hemisphere in column 3.

Desired output would be something like this:

0    36.510000
1    36.731111
2    36.720278
3    36.499167
4    36.488333
5    36.709722
6    36.698889
7    36.477778
8    36.466944
9    36.688056

When I use the hemisphere to get the sign of the coordinate like this:

gg = a[0]+(a[1]+a[2]/60)/60 * -1 if a[3]=='S' else 1

the follower error is raised:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

How can I convert the full column using the string in another column without explicitly iterating through the dataframe?

Upvotes: 0

Views: 1205

Answers (1)

Paul H
Paul H

Reputation: 68146

I took the liberty of giving your dataframe some meaningful names.

You need to apply your logic to each row, like this:

# generate, load data
datastring = StringIO("""\
latD latM  latS latH lonD lonM lonS lonH
36  30  36  N  2  31  18  W
36  43  52  N  2  17  25  W 
36  43  13  N  2  16  27  W
36  29  57  N  2  30  21  W
36  29  18  N  2  29  24  W
""")
df = pandas.read_table(datastring, sep='\s+')

# define function to convert to decimalDegrees
def decimalDegree(degree, minute, second, hemisphere):
    if hemisphere.lower() in ["w", "s", "west", "south"]:
        factor = -1.0
    elif hemisphere.lower() in ["n", "e", "north", "east"]:
        factor = 1.0
    else:
        raise ValueError("invalid hemisphere")

    # check the order of operations in your code
    return factor * (degree + (minute + second/60.)/60.)

# apply that function along to rows, using lambda
# to specify the columns to use as input
df['latitude'] = df.apply(
    lambda row: decimalDegree(row['latD'], row['latM'], row['latS'], row['latH']),
    axis=1
)

df['longitude'] = df.apply(
    lambda row: decimalDegree(row['lonD'], row['lonM'], row['lonS'], row['lonH']),
    axis=1
)

print(df)

And that give me:

   latD  latM  latS latH  lonD  lonM  lonS lonH   latitude  longitude
0    36    30    36    N     2    31    18    W  36.510000  -2.521667
1    36    43    52    N     2    17    25    W  36.731111  -2.290278
2    36    43    13    N     2    16    27    W  36.720278  -2.274167
3    36    29    57    N     2    30    21    W  36.499167  -2.505833
4    36    29    18    N     2    29    24    W  36.488333  -2.490000

Upvotes: 2

Related Questions