#python #pandas #dataframe #apply
#python #панды #фрейм данных #применить
Вопрос:
У меня есть Df следующим образом:
position_latitude position_longitude geohash
0 53.398940 10.069293 u1
1 53.408875 10.052669 u1
2 48.856350 9.171759 u0
3 48.856068 9.170798 u0
4 48.856350 9.171759 u0
Что я хочу знать, так это получение ближайшего узла к этим позициям с использованием разных шейп-файлов на основе Geohash.
Итак, что я хочу сделать, это загрузить навсегда group в Geohash (например, u1) график из файла, а затем использовать этот график в функции для получения ближайшего узла.
Я мог бы сделать это в цикле for, однако я думаю, что есть более эффективные способы сделать это.
Я думал о чем-то подобном:
df['nearestNode'] = geoSub.apply(lambda x: getDistanceToEdge(x.position_latitude,x. position_longitude,x. geohash), axis=1)
Однако я не могу понять, как загружать график только один раз для каждой группы, поскольку для получения его из файла потребуется некоторое время.
что я придумал до сих пор:
groupHashed = geoSub.groupby('geohash')
geoSub['distance'] = np.nan
for name, group in groupHashed:
G = osmnx.graph.graph_from_xml('geohash/' name '.osm', simplify=True, retain_all=False)
geoSub['distance'] = geoSub.apply(lambda x: getDistanceToEdge(x.position_latitude,x.position_longitude, G) if x.geohash == name, axis=1)
определенно, похоже, работает, однако я чувствую, что условие if резко замедляет его
обновление: только что обновлено:
geoSub['distance'] = geoSub.apply(lambda x: getDistanceToEdge(x.position_latitude,x.position_longitude, G) if x.geohash == name, axis=1)
Для:
geoSub['distance'] = geoSub[geoSub['geohash'] == name].apply(lambda x: getDistanceToEdge(x.position_latitude,x.position_longitude, G), axis=1)
теперь это намного быстрее. есть ли еще лучший метод?
Ответ №1:
Вы можете использовать transform
Я заглушаю G
и getDistanceToEdge
(как x y geohash[-1]
) поэтому показываю рабочий пример
import pandas as pd
from io import StringIO
data = StringIO("""
,position_latitude,position_longitude,geohash
0,53.398940,10.069293,u1
1,53.408875,10.052669,u1
2,48.856350,9.171759,u0
3,48.856068,9.170798,u0
4,48.856350,9.171759,u0
""" )
df = pd.read_csv(data, index_col=0).fillna('')
def getDistanceToEdge(x, y, G):
return x y G
def fun(pos):
G = int(pos.values[0][-1][-1])
return pos.apply(lambda x: getDistanceToEdge(x[0], x[1], G))
df['pos'] = list(zip(df['position_latitude'], df['position_longitude'], df['geohash']))
df['distance'] = df.groupby(['geohash'])['pos'].transform(fun)
df = df.drop(['pos'], axis=1)
print (df)
Вывод:
position_latitude position_longitude geohash distance
0 53.398940 10.069293 u1 64.468233
1 53.408875 10.052669 u1 64.461544
2 48.856350 9.171759 u0 58.028109
3 48.856068 9.170798 u0 58.026866
4 48.856350 9.171759 u0 58.028109
Как вы можете видеть, вы можете получить имя группы, используя pos.values[0][-1]
внутри функции fun
. Это потому, что мы заботимся о том, чтобы создать pos
столбец как кортеж (lat, log, geohash), и каждый geohash
в группе после groupby одинаков. Таким образом, с помощью группы мы можем захватить geohash
, взяв последнее значение кортежа ( pos
) любой строки. pos.values[0][-1]
укажите последнее значение кортежа первой строки.
Комментарии:
1. большое спасибо, попробую вашу идею, так как моя последняя попытка (geoSub[‘distance’] = geoSub[geoSub[‘geohash’] == name].apply(lambda x: getDistanceToEdge(x.position_latity,x.position_longitude, G), axis = 1)) уже переопределяет всевычисленные значения равны nan — .-
2. У меня небольшая проблема с интерпретацией того, как вы хотите определить G в вашем примере, поскольку график зависит от имени группы. Итак, у меня есть один график в моей файловой системе для каждой группы, и мне нужно загрузить зависимый график в функцию fun. Не могли бы вы предоставить мне дополнительную информацию о том, как я мог бы решить ее на вашем примере? Смотрите: G = osmnx.graph.graph_from_xml(‘geohash/’ name ‘.osm’, simplify= True, retain_all=False)
3. Обновленный ответ с информацией