Применение функции к каждому наблюдению в кадре данных - PullRequest
2 голосов
/ 16 апреля 2019

У меня большой df координат, который я передаю через функцию (обратный геокодер). Как мне пройти через весь df без итерации (очень долго)

Пример df:

    Latitude    Longitude  
0   -25.66026   28.0914    
1   -25.67923   28.10525    
2   -30.68456   19.21694    
3   -30.12345   22.34256    
4   -15.12546   17.12365 

После запуска нужной мне функции (без цикла for ...) df:

     City
0    HappyPlace
1    SadPlace
2    AveragePlace
3    CoolPlace
4    BadPlace

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

EDIT:

с использованием df.apply () может не работать, так как мой код выглядит следующим образом:

for i in range(len(df)):
    results = g.reverse_geocode(df['LATITUDE'][i], df['LONGITUDE'][i])
    city.append(results.city)

1 Ответ

2 голосов
/ 16 апреля 2019

Более медленный подход Итерирование по списку географических точек и выбор города географической точки

import pandas as pd
import time
d = {'Latitude': [-25.66026,-25.67923,-30.68456,-30.12345,-15.12546,-25.66026,-25.67923,-30.68456,-30.12345,-15.12546], 'Longitude': [28.0914, 28.10525,19.21694,22.34256,17.12365,28.0914, 28.10525,19.21694,22.34256,17.12365]}   
df = pd.DataFrame(data=d)
# example method of g.reverse_geocode() -> geo_reverse
def geo_reverse(lat, long):
    time.sleep(2)
    #assuming that your reverse_geocode will take 2 second
    print(lat, long)
for i in range(len(df)):
    results = geo_reverse(df['Latitude'][i], df['Longitude'][i])

Из-за time.sleep(2). вышеуказанная программа займет не менее 20 секунд, чтобы обработать все десять географических точек.

Лучше, чем выше:

import pandas as pd
import time
d = {'Latitude': [-25.66026,-25.67923,-30.68456,-30.12345,-15.12546,-25.66026,-25.67923,-30.68456,-30.12345,-15.12546], 'Longitude': [28.0914, 28.10525,19.21694,22.34256,17.12365,28.0914, 28.10525,19.21694,22.34256,17.12365]}   
df = pd.DataFrame(data=d)

import threading
def runnable_method(f, args):
    result_info = [threading.Event(), None]
    def runit():
        result_info[1] = f(args)
        result_info[0].set()
    threading.Thread(target=runit).start()
    return result_info

def gather_results(result_infos):
    results = []
    for i in range(len(result_infos)):
        result_infos[i][0].wait()
        results.append(result_infos[i][1])
    return results

def geo_reverse(args):
    time.sleep(2)
    return "City Name of ("+str(args[0])+","+str(args[1])+")"
geo_points = []
for i in range(len(df)):
    tuple_i = (df['Latitude'][i], df['Longitude'][i])
    geo_points.append(tuple_i)

result_info = [runnable_method(geo_reverse, geo_point) for geo_point in geo_points]
cities_result = gather_results(result_info)  
print(cities_result)

Обратите внимание, что метод geo_reverse имеет время обработки 2 секунды для извлечения данных на основе географических точек. Во втором примере коду потребуется всего 2 секунды , чтобы обработать столько точек, сколько вы хотите.

Примечание: Попробуйте оба подхода, предполагая, что ваш geo_reverse займет ок. 2 секунды для получения данных. Первый подход займет 20 + 1 секунд, и время обработки будет увеличиваться с увеличением количества входов, но второй подход будет иметь почти постоянное время обработки (т.е. около 2 + 1) секунд, независимо от того, сколько географических точек вы хотите обработать.

Предположим, g.reverse_geocode() метод geo_reverse() в приведенном выше коде. Запустите оба кода (подхода) выше и посмотрите разницу самостоятельно.

Пояснение: Посмотрите на приведенный выше код и его основную часть - создание списка кортежей и его понимание, передавая каждый кортеж динамически создаваемым потокам (основная часть):

#Converting df of geo points into list of tuples
geo_points = []
for i in range(len(df)):
    tuple_i = (df['Latitude'][i], df['Longitude'][i])
    geo_points.append(tuple_i)
#List comprehension with custom methods and create run-able threads
result_info = [runnable_method(geo_reverse, geo_point) for geo_point in geo_points]
#gather result from each thread.
cities_result = gather_results(result_info)  
print(cities_result)
...