pandas - применить функцию UTM к столбцам фрейма данных

Я работаю с этим пакетом python под названием UTM, который преобразует координаты WGS84 в UTM и наоборот. Я хотел бы применить эту функцию к кадру данных pandas. Функция работает следующим образом:

utm.from_latlon(51.2, 7.5)
>>> (395201.3103811303, 5673135.241182375, 32, 'U')

где вход представляет собой пару координат, и он возвращает кортеж тех же координат в системе UTM. Для моих целей меня интересуют только первые два элемента кортежа.

Я работаю над Dataframe под названием cities, например:

City;Latitude;Longitude;minx;maxx;miny;maxy
Roma;41.892916;12.48252;11.27447419;13.69056581;40.99359439;42.79223761
Paris;48.856614;2.352222;0.985506011;3.718937989;47.95729239;49.75593561
Barcelona;41.385064;2.173403;0.974836927;3.371969073;40.48574239;42.28438561
Berlin;52.519171;13.406091;11.92835553;14.88382647;51.61984939;53.41849261
Moscow;55.755826;37.6173;36.01941671;39.21518329;54.85650439;56.65514761

и я хотел бы добавить четыре столбца для каждой строки с именами «utmminx», «utmmax», «utmminy», «utmmaxy» в результате применения функции utm к «minx», «maxx», «miny», « столбцы макси. До сих пор я пробовал следующее, присваивая первое и второе значение полученного кортежа новым столбцам:

cities['utmminx'],cities['utmmaxx'] = utm.from_latlon(cities['minx'],cities['maxx'])[0],utm.from_latlon(cities['minx'],cities['maxx'])[1]

но я получил ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().. Я попытался установить только значение первой строки для функции, и она работает:

utm.from_latlon(cities['minx'][0],cities['maxx'][0])[0],utm.from_latlon(cities['minx'][0],cities['maxx'][0])[1]
>>> (357074.7837193568, 1246647.7959235134)

Я хотел бы избежать классических циклов по фрейму данных, поскольку я думал, что для этого есть классический метод pandas.


person Fabio Lamanna    schedule 03.05.2015    source источник


Ответы (2)


Начиная с вашей рамы

        City   Latitude  Longitude       minx       maxx       miny       maxy
0       Roma  41.892916  12.482520  11.274474  13.690566  40.993594  42.792238
1      Paris  48.856614   2.352222   0.985506   3.718938  47.957292  49.755936
2  Barcelona  41.385064   2.173403   0.974837   3.371969  40.485742  42.284386
3     Berlin  52.519171  13.406091  11.928356  14.883826  51.619849  53.418493
4     Moscow  55.755826  37.617300  36.019417  39.215183  54.856504  56.655148

Мы определяем функцию, которая берет строку, вызывает utm.from_latlon() и возвращает ряд первых двух элементов кортежа, который мы получаем от utm. Затем мы используем метод Pandas apply() для вызова этой функции. Я только что сделал один набор координат, но вы можете сделать то же самое заявление apply() для других.

ИЗМЕНИТЬ Я изменил функцию, чтобы индексировать ее по положению, а не по имени, чтобы функцию можно было использовать повторно.

def getUTMs(row):
    tup = utm.from_latlon(row.ix[0],row.ix[1])
    return pd.Series(tup[:2])

cities[['utmminy','utmminx']] = cities[['miny','maxx']].apply(getUTMs , axis=1)
cities

       City   Latitude  Longitude       minx       maxx       miny  \
0       Roma  41.892916  12.482520  11.274474  13.690566  40.993594   
1      Paris  48.856614   2.352222   0.985506   3.718938  47.957292   
2  Barcelona  41.385064   2.173403   0.974837   3.371969  40.485742   
3     Berlin  52.519171  13.406091  11.928356  14.883826  51.619849   
4     Moscow  55.755826  37.617300  36.019417  39.215183  54.856504   

        maxy        utmminy         utmminx  
0  42.792238  389862.562124  4538871.624816  
1  49.755936  553673.645924  5311803.556837  
2  42.284386  531525.080929  4481738.581782  
3  53.418493  491957.246518  5718764.545758  
4  56.655148  513814.029424  6078844.774914  
person Bob Haffner    schedule 03.05.2015

Вы можете использовать метод apply для таких столбцов, как

Использование лямбда-функции

In [120]: lambdafunc = lambda x: pd.Series(utm.from_latlon(x['minx'], x['maxx'])[:2])

И, применяя построчно

In [121]: cities[['utmminx', 'utmmax']] = cities.apply(lambdfunc), axis=1)

In [122]: cities
Out[122]:
        City   Latitude  Longitude       minx       maxx       miny       maxy        utmminx          utmmax
0       Roma  41.892916  12.482520  11.274474  13.690566  40.993594  42.792238  357074.783719  1246647.795924
1      Paris  48.856614   2.352222   0.985506   3.718938  47.957292  49.755936  579990.155575   108936.764630
2  Barcelona  41.385064   2.173403   0.974837   3.371969  40.485742  42.284386  541385.186664   107751.160445
3     Berlin  52.519171  13.406091  11.928356  14.883826  51.619849  53.418493  487350.117333  1318634.001517
4     Moscow  55.755826  37.617300  36.019417  39.215183  54.856504  56.655148  519389.217259  3986123.464910
person Zero    schedule 03.05.2015
comment
Вау, мы совсем близко! Мне нравится лямбда. - person Bob Haffner; 03.05.2015
comment
Вы опередили меня на секунды =) На самом деле, это может быть однострочник, как cities.apply(lambda x: pd.Series(utm.from_latlon(x['minx'], x['maxx'])[:2])), axis=1), но пришлось разделить лямбда-функцию из-за длины и удобочитаемости! - person Zero; 03.05.2015