Быстрое преобразование востока и севера в широту и долготу для большого DataFrame местоположений - PullRequest
0 голосов
/ 26 мая 2020

Я использую Pandas и PyProj для преобразования востока и севера в долготу и широту, а затем сохраняю разделенный вывод в 2 столбца, как это ....

v84 = Proj(proj="latlong",towgs84="0,0,0",ellps="WGS84")
v36 = Proj(proj="latlong", k=0.9996012717, ellps="airy",
        towgs84="446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894")
vgrid = Proj(init="world:bng")


def convertLL(row):

    easting = row['easting']
    northing = row['northing']

    vlon36, vlat36 = vgrid(easting, northing, inverse=True)

    converted = transform(v36, v84, vlon36, vlat36)

    row['longitude'] = converted[0]
    row['latitude'] = converted[1]

    return row


values = pd.read_csv("values.csv")
values = values.apply(convertLL, axis=1)

Это работает, но очень медленный и время ожидания для больших наборов данных. Пытаясь улучшить ситуацию, я пытаюсь преобразовать это, чтобы вместо этого использовать функцию lamba в надежде, что это ускорит процесс. У меня есть это пока ...

def convertLL(easting, northing):

    vlon36, vlat36 = vgrid(easting, northing, inverse=True)

    converted = transform(v36, v84, vlon36, vlat36)

    row = row['longitude'] = converted[0]

    return row


values ['longitude'] = values.apply(lambda row: convertLL(row['easting'], row['northing']), axis=1)

Эта преобразованная версия работает и работает быстрее, чем моя старая, и не имеет времени ожидания для больших наборов данных, но это работает только для долготы, есть ли способ чтобы заставить его работать с широтой?

Кроме того, это векторизовано? Могу ли я еще ускорить процесс?

EDIT

Образец данных ...

name | northing | easting | latitude | longitude
------------------------------------------------
tl1  | 378778   | 366746  |          |
tl2  | 384732   | 364758  |          |

1 Ответ

1 голос
/ 26 мая 2020

Из-за предмета, я думаю, мы не могли видеть лес за деревьями. Если мы посмотрим на документы для transform, вы увидите:

  • xx (скаляр или массив (numpy или python)) - Вход Координата x.
  • yy (скаляр или массив (numpy или python)) - Введите координату y.

Отлично; массив numpy - это именно то, что нам нужно. A pd.DataFrame можно рассматривать как словарь массивов, поэтому нам просто нужно изолировать эти столбцы и передать их функции. Есть небольшая загвоздка - столбцы DataFrame будут Series, которые transform отклонят, поэтому нам просто нужно использовать атрибут values. Этот мини-пример прямо эквивалентен вашему первоначальному подходу:

def vectorized_convert(df):
    vlon36, vlat36 = vgrid(df['easting'].values, 
                           df['northing'].values, 
                           inverse=True)
    converted = transform(v36, v84, vlon36, vlat36)
    df['longitude'] = converted[0]
    df['latitude'] = converted[1]
    return df

df = pd.DataFrame({'northing': [378778, 384732],
                   'easting': [366746, 364758]})

print(vectorized_convert(df))

И мы закончили. Помимо этого, мы можем взглянуть на тайминги для 100 строк (текущий подход расширяется для моих обычных 100000 строк для примеров синхронизации):

def current_way(df):
    df = df.apply(convertLL, axis=1)
    return df


def vectorized_convert(df):
    vlon36, vlat36 = vgrid(df['easting'].values, 
                           df['northing'].values, 
                           inverse=True)

    converted = transform(v36, v84, vlon36, vlat36)
    df['longitude'] = converted[0]
    df['latitude'] = converted[1]
    return df


df = pd.DataFrame({'northing': [378778, 384732] * 50,
                   'easting': [366746, 364758] * 50})

Дает:

%timeit current_way(df)
289 ms ± 15.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit vectorized_convert(df)
2.95 ms ± 59.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
...